agents: Rocko row 122 round 1 candidate and verification packet
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# Row 122 design — agent settings and organization writes (#1616)
|
||||
|
||||
Design first, for Sage to post before implementation. Rocko, GPT-6.1-Sol.
|
||||
Brief: docs/plans/2026-10-14_prd-1.2-build.md, pinned 240d25518,
|
||||
section Agent limits as settings, with the organization-file write path.
|
||||
Requirements: REQ-ROLE-3, REQ-LIMIT-1, REQ-LAUNCH-1, REQ-WEB-1.
|
||||
No live organization/configuration/secrets were read. No product code or
|
||||
migration has run. Decision144 leaves Jason's file to Jason.
|
||||
|
||||
## Proposed schema
|
||||
|
||||
Keep businessVersion1, launch.by and launch.instances. Replace launch.max
|
||||
with launch.models and launch.limits. Example defaults, with provider/model
|
||||
values explicitly chosen by the operator rather than inferred:
|
||||
|
||||
```json
|
||||
{
|
||||
"launch": {
|
||||
"by": "pm",
|
||||
"instances": ["coder", "reviewer", "cto"],
|
||||
"models": {
|
||||
"opus": {"provider": "anthropic", "model": "claude-opus-5-5"},
|
||||
"sonnet": {"provider": "anthropic", "model": "claude-sonnet-5-5"}
|
||||
},
|
||||
"limits": {
|
||||
"models": {
|
||||
"anthropic": {"claude-opus-5-5": 4, "claude-sonnet-5-5": 4}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Model-table keys are stable configuration ids; each entry requires a provider
|
||||
and an exact external model string. Each role's vars.model selects a table
|
||||
key, for example pm -> opus, coder/reviewer -> sonnet. Harness selection
|
||||
stays where it is today; row65 later converts harnesses through the loader.
|
||||
The table's provider/model override the provider/model used to launch that
|
||||
instance, and are recorded in its manifest, running-session registry and
|
||||
launch log. No provider allowlist or provider module is introduced here.
|
||||
Unknown references fail closed; matching a family substring disappears.
|
||||
|
||||
limits has only these optional keys:
|
||||
|
||||
- total: count across all running sessions in the organization.
|
||||
- providers: object mapping exact provider names to counts.
|
||||
- models: object mapping provider names to objects mapping exact external
|
||||
model names to counts.
|
||||
|
||||
An absent key means unlimited. Empty objects are valid, and an empty limits
|
||||
object means no concurrency limits. null, fractions, negatives and strings
|
||||
refuse; accepted counts are nonnegative safe integers, with no configured
|
||||
upper bound beyond lossless JSON integer representation. 0 stops a new
|
||||
launch in that scope. Four and four are editable starter/migration values,
|
||||
not a validator ceiling or a value injected when a key is absent. Removing
|
||||
an entry explicitly unsets that limit. Aliases for the same provider/model
|
||||
share the same counter, so a second table key cannot bypass a model limit.
|
||||
Provider/model limits need not have a currently selected role: they can be
|
||||
configured before changing an instance's model.
|
||||
|
||||
## Migration and Jason's exact change
|
||||
|
||||
`mosaic limits migrate --business ID --models FILE` prints the converted
|
||||
whole document by default. Only explicit --write by a verified human uses
|
||||
the write path. FILE supplies the model table and the exact mapping from
|
||||
old external model strings to table keys. No provider inference, substring
|
||||
routing or automatic write on read/start. Unknown/ambiguous mappings refuse
|
||||
with the unchanged input. Repeating on an already migrated valid document
|
||||
is idempotent.
|
||||
|
||||
For old launch.max = {opus:4,sonnet:4}, map each family to one explicitly
|
||||
supplied table key and translate those values to the two corresponding
|
||||
provider/model limits. Preserve launch.by, launch.instances, harnesses,
|
||||
credentials, role definitions and unrelated document values. Convert each
|
||||
role's effective old model selection to its mapped table key; use explicit
|
||||
instance overrides where a selection was inherited. Do not alter a shared
|
||||
system execution setting. Require mappings for launch.by and every
|
||||
launchable instance. Do not invent a total8 or provider8 limit: the old
|
||||
shape had neither. Legacy family limits that require multiple exact models
|
||||
per family cannot be faithfully split; refuse and require an operator's
|
||||
explicit new limits rather than silently widening capacity.
|
||||
|
||||
The example above illustrates the exact shape, not a claim about Jason's
|
||||
provider, ids or instances. The fixture migration produces the replacement
|
||||
launch block plus per-instance vars.model changes. The build packet will
|
||||
include that exact JSON patch and command for Jason, with provider/model
|
||||
mapping explicitly supplied and reviewed through Sage/Mos. It will not
|
||||
assert that anthropic is Jason's provider or execute a live migration. The
|
||||
new validator refuses an unmigrated launch.max with a migration instruction.
|
||||
Re-pin therefore follows Jason's applied migration and Mos's go; the old
|
||||
host must not launch between schema migration and the coordinated re-pin.
|
||||
|
||||
## One write path, fail closed
|
||||
|
||||
A trusted host module owns writes to the resolved businessFilePath for a
|
||||
validated organization id. It accepts an authenticated actor supplied by
|
||||
the human channel, never an actor string from a browser/CLI payload.
|
||||
Limits endpoints may change only launch limits/model-table entries and
|
||||
role model selection. The shared internal module can validate a whole-file
|
||||
replacement for row123's later chief-of-staff verb; this row grants no
|
||||
chief-of-staff writer and exposes no unrestricted browser file write.
|
||||
|
||||
Serialize writes per organization with a filesystem lock shared by writers;
|
||||
compare a submitted revision/hash against the current bytes to refuse lost
|
||||
updates. Read the current regular file without following a symlink, validate
|
||||
the entire proposed document using the existing role-aware validator, then
|
||||
prepare same-directory temporary bytes. Preserve an immutable previous
|
||||
version and an append-only actor/change record with field paths, old/new
|
||||
values and before/after hashes. Fsync evidence and candidate before atomic
|
||||
rename, then fsync the directory. Journal prepared/committed outcomes and
|
||||
recover an interrupted transaction by hashes; an uncertain outcome refuses
|
||||
new writes until reconciled. Invalid or stale proposals never replace the
|
||||
old file. Success is reported only after the committed receipt. No secret
|
||||
contents are logged: unrelated credential references remain references.
|
||||
|
||||
CLI and Settings use the same human-only read/update operation behind the
|
||||
existing human proof. No direct CLI bypass. CLI stays out of transport.mjs;
|
||||
Settings POST repeats the existing enabled-send, named-host, authenticated
|
||||
header, exact Origin, same-origin Fetch Metadata, body-size and strict-key
|
||||
checks. Both submit a revision and receive current normalized settings and
|
||||
counts; no retry on unknown outcome. GET remains available through the
|
||||
existing read path. Form inputs distinguish unset from0, show all three
|
||||
limit kinds and every instance's table selection, and report refusals.
|
||||
|
||||
## Launch behavior and acceptance evidence
|
||||
|
||||
Within the launcher's existing serialized launch queue, re-read and validate
|
||||
current limits and model selections for every attempt, including host-start
|
||||
launches. A missing/invalid file refuses; never fall back to cached limits.
|
||||
Check total, then provider, then exact provider/model counters, counting the
|
||||
launcher itself and all still-running registry entries. A launch at the
|
||||
limit refuses because it would exceed it; unset imposes no check. Lowering
|
||||
a limit leaves existing sessions alive. Their recorded provider/model tuple
|
||||
continues to count even after their instance is assigned a different model.
|
||||
Each refusal logs the hit scope, configured value and running count; each
|
||||
launch logs harness/provider/model. Existing authority/credential/sandbox
|
||||
checks remain, and unrelated permission changes still follow their existing
|
||||
reload/re-pin rules.
|
||||
|
||||
Builder tests cover whole-file validation, atomic publication, previous
|
||||
bytes, actor/old/new receipts and crash/stale-write refusal; every limit
|
||||
kind unset/0/at/over; live re-read and unchanged existing sessions; exact
|
||||
model routing; fixture-only print/write migration; human-only CLI; form
|
||||
send checks. One killed mutant per acceptance check, listed in the packet.
|
||||
Targeted builder gate and mutants need Sage's slot. No product code starts
|
||||
until Sage posts this design note on #1616. Landing public/ changes awaits
|
||||
Mos (decision123); any live step still requires re-pin (decision109).
|
||||
|
||||
## Superseding migration ruling — decisions 145 and sage-0254
|
||||
|
||||
The earlier optional write/local helper description is superseded: migration
|
||||
is print-only, has no --write and uses no organization writer or human proof.
|
||||
Only broker-backed `mosaic limits` and Settings write. Jason installs the output
|
||||
himself in Mos's window with the PM run idle and the re-pin in that same window.
|
||||
Both exact Claude table entries use provider `anthropic`, per Mos via Sage
|
||||
sage-0254. Map pm, cto and reviewer to opus; coder to sonnet. Keep exact model
|
||||
limits four/four, no total or provider limit, and leave execution.provider alone.
|
||||
@@ -0,0 +1,123 @@
|
||||
# Row 122 / #1616 — Agent limits as settings
|
||||
|
||||
Base: f529cf485c8a0ac214076052cb8e16f14864c7a0 (row130 included). Candidate
|
||||
code is uncommitted in detached worktree `/mnt/storage/src/mosaic-stack-rocko-122`.
|
||||
Sage posted design note as #1616 comment28516. Decision145 supersedes its
|
||||
optional migration write: migration is print-only, and has no write helper.
|
||||
|
||||
## Behavior and authority
|
||||
|
||||
`launch.models` is an explicit selection-key → provider/external-model table.
|
||||
`launch.limits` has optional total, provider and exact provider/model counts.
|
||||
Absence is unlimited, zero denies new launches, safe whole numbers have no
|
||||
policy ceiling. The example and Jason's migration use editable four/four model
|
||||
limits, not fallback limits inserted by code. Roles select table keys through
|
||||
vars.model; harness selection and the shared execution.provider stay unchanged.
|
||||
Other provider names route/count independently; aliases share exact tuple counts.
|
||||
|
||||
One organization writer validates the complete proposed document, checks the
|
||||
expected SHA-256 revision, saves exact previous bytes, fsyncs and atomically
|
||||
renames a candidate, and logs actor/hashes/field old/new values with prepared
|
||||
and committed receipts. A concurrent writer, unsafe/symlink file, stale revision,
|
||||
invalid document or uncertain receipt refuses. Host-start recovery can finish
|
||||
or abort a prepared receipt by hashes. A stale writer lock refuses until an
|
||||
operator verifies the old writer is gone; no automatic stale-lock deletion race.
|
||||
|
||||
The broker exposes human-only limits / limits.set using the existing proof.
|
||||
Role, reader and tester capabilities cannot write or forge the actor. CLI limits
|
||||
and Console Settings both go through that broker path. Console POST Settings
|
||||
requires send mode, named Host, verified identity, exact Origin, same-origin
|
||||
Fetch Metadata, bounded JSON and strict writable keys. No automatic retry.
|
||||
The form shows every configured limit, model table and role selection (held CTO
|
||||
included), keeps a failed draft and explicitly offers re-read. Existing GETs
|
||||
and preview remain reads. Launcher reloads policy on every serialized attempt
|
||||
and again after asynchronous checkout preparation; lowering limits keeps existing
|
||||
sessions, whose recorded exact tuple continues counting. Refusal logs name the
|
||||
hit; launch logs name harness/provider/model.
|
||||
|
||||
## Migration and cut-over
|
||||
|
||||
See MIGRATION.md, migration-map.json and jason-migration.patch.json. Provider
|
||||
facts come from Mos via Sage sage-0254: both Claude entries use anthropic.
|
||||
The pure CLI prints the converted whole document without bus/config access,
|
||||
refuses unknown/ambiguous mappings, prints migrated input idempotently and never
|
||||
writes its input. The packet maps pm, cto and reviewer to opus; coder to sonnet.
|
||||
Only the two exact model limits four/four are added. No live file was read.
|
||||
|
||||
Jason's edit and the re-pin happen in one window Mos runs, with the PM run idle.
|
||||
|
||||
Settings public assets require Mos's landing go (decision123). No bus/Console
|
||||
unit, live organization file or shared wrapper was changed. Only a separate
|
||||
re-pin can make this candidate live (decision109).
|
||||
|
||||
## Targeted builder gate (decision136)
|
||||
|
||||
Changed packages: business, bus, cli, harness, seat, webui. Importers of those
|
||||
packages in current source: control-board, conversation, ledger, tasks. Run all
|
||||
node test files in those ten packages; ledger is run directly despite lacking
|
||||
package.json. Browser form coverage is part of webui, including the new
|
||||
settings-form.test.mjs. Gate serializes files (`--test-concurrency=1`).
|
||||
|
||||
Exact affected shell readers:
|
||||
- scripts/test-queue.sh syntax-checks and executes changed scripts/mosaic.
|
||||
- scripts/test-task.sh invokes scripts/mosaic-task.mjs, which statically imports
|
||||
BusinessError/validateRoleDocument from changed business/src/index.mjs and
|
||||
transitively the changed validator and vocabulary.
|
||||
|
||||
scripts/test-discord.sh is an additional regression run for the existing
|
||||
connector command surface; it is not claimed as a direct reader of the patch.
|
||||
The other test-*.sh read unchanged config/auth/release/foundation/extension/
|
||||
conductor/landing paths or scratch fixture trees, not the changed files.
|
||||
|
||||
DOCKER_HOST=unix:///nonexistent.sock throughout normal runs. Docker-required
|
||||
cases will be separately rerun with DOCKER_HOST unset if needed and recorded;
|
||||
no daemon/socket/volume changes. Slot granted by Sage sage-0259. Each mutant
|
||||
uses its own process group and whole-group SIGKILL on timeout; a timeout is not
|
||||
a kill. One recurrence of #258/#261/#262/#263 is noted; a second stops the gate.
|
||||
|
||||
## Verification results
|
||||
|
||||
Final broad targeted gate passed all 13 steps. The late durability and migration
|
||||
audit changes were followed by complete business, bus and CLI reruns; those
|
||||
passing reruns replace their earlier logs in gate/results.json. The bus count
|
||||
increased by one for an integration check through runtime's real shared writer.
|
||||
All node cases below passed, with zero skips/failures.
|
||||
|
||||
| Node suite | Passed |
|
||||
| --- | ---: |
|
||||
| business | 75 |
|
||||
| bus | 158 |
|
||||
| seat | 132 |
|
||||
| harness | 81 |
|
||||
| cli | 194 |
|
||||
| webui (browser form included) | 112 |
|
||||
| control-board | 124 |
|
||||
| conversation | 182 |
|
||||
| ledger (direct) | 86 |
|
||||
| tasks | 92 |
|
||||
|
||||
Shell: queue 28 plus its 156 node tests; Discord 78 plus 183 node tests;
|
||||
task 98. Queue intentionally omits only the canonical-root verify/render checks
|
||||
in the detached worktree. Task ran with DOCKER_HOST unset and Docker server
|
||||
29.7.2; all 98 cases ran, so no Docker branches were skipped. Queue, Discord,
|
||||
all node suites and mutants used DOCKER_HOST=unix:///nonexistent.sock.
|
||||
The worktree's mosaic-stack-rocko-122_default network existed after Docker
|
||||
and was removed successfully; no daemon/socket/volume changes.
|
||||
|
||||
Initial failures were fixture/expectation updates, not known flakes: harness's
|
||||
probe-model needed a table entry; shell.test's exact single-POST assertion
|
||||
needed the explicitly authorized Settings POST. First failure logs are retained
|
||||
under gate/*-before-*.log. The new runtime integration fixture initially lacked
|
||||
its disposable data directory, fixed before the final bus rerun. No recurrence
|
||||
of #258/#261/#262/#263 occurred.
|
||||
|
||||
All 33 mutants were killed, with no syntax/import-only kills, survivors or
|
||||
timeouts. See MUTANTS.md and mutants/results.json for individual sites, commands
|
||||
and logs. Every mutant used a separate process group; source was restored and
|
||||
all 43 candidate hashes were checked afterwards (manifest-check.txt). The
|
||||
post-run cwd/path-scoped node/chromium sweep found no runners before or after
|
||||
(sweep.log). Slot returned to Sage at 2026-10-15 01:04:27 UTC.
|
||||
|
||||
Candidate manifest SHA-256:
|
||||
667441df2411db4c085ec6981d8c9c5f55578debc02a389a2f4df9283df775ae.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Jason’s print-only migration (decision 145)
|
||||
|
||||
Mapping facts: Sage sage-0252 and Mos via Sage sage-0254. Anthropic serves both
|
||||
Claude models directly; the system execution.provider stays unchanged. The
|
||||
held CTO maps to opus too. Only the two exact provider/model limits are set:
|
||||
opus four, sonnet four. There is no total limit or provider-wide limit.
|
||||
|
||||
The adjacent JSON Patch names the exact entry changes. Jason supplies his
|
||||
organization-file path to this command, after checking the output destination:
|
||||
|
||||
```sh
|
||||
ORGANIZATION=/path/to/organization.json
|
||||
scripts/mosaic limits migrate --file "$ORGANIZATION" --models /mnt/storage/src/mosaic-stack/agents/rocko/work/queue-122/r1/migration-map.json --roles-dir roles > /path/to/converted-organization.json
|
||||
```
|
||||
|
||||
Run the command from the newly reviewed copy so the command and role definitions
|
||||
match. It reads fixtures in builder/reviewer gates; no agent runs it on the live
|
||||
file. It does not contact a bus, write its input or offer --write. Jason reviews
|
||||
and installs the complete output himself; the patch is explanatory, not an
|
||||
automatically applied migration.
|
||||
|
||||
Jason's edit and the re-pin happen in one window Mos runs, with the PM run idle.
|
||||
|
||||
Old code cannot consume the new shape, and new code refuses launch.max. Keep the
|
||||
converted document and reviewed copy ready before the window; do not migrate
|
||||
early or re-pin early. Provider remains a table value for a later proxy change.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Row122 mutants
|
||||
|
||||
| Check / fault | Result | Test |
|
||||
| --- | --- | --- |
|
||||
| 01-whole-document-validation | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 02-atomic-publication | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 03-previous-version | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 04-authenticated-actor | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 05-old-new-receipt | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 06-stale-revision | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 07-uncertain-recovery | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 08-total-limit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 09-provider-limit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 10-model-limit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 11-at-limit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 12-unset-unlimited | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 13-nonnegative-counts | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 14-no-policy-ceiling | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 15-exact-provider-count | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 16-provider-routing | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 17-reread-every-launch | KILLED (1) | packages/cli/tests/launch-limits.test.mjs |
|
||||
| 18-refusal-hit-logged | KILLED (1) | packages/cli/tests/launch-limits.test.mjs |
|
||||
| 19-migration-preserve-counts | KILLED (1) | packages/cli/tests/limits.test.mjs |
|
||||
| 20-migration-ambiguity | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 21-print-only-migration | KILLED (1) | packages/cli/tests/limits.test.mjs |
|
||||
| 22-human-only-settings | KILLED (1) | packages/bus/tests/limits.test.mjs |
|
||||
| 23-settings-origin | KILLED (1) | packages/webui/tests/settings-write.test.mjs |
|
||||
| 24-settings-fetch-metadata | KILLED (1) | packages/webui/tests/settings-write.test.mjs |
|
||||
| 25-settings-send-mode | KILLED (1) | packages/webui/tests/settings-write.test.mjs |
|
||||
| 26-settings-strict-keys | KILLED (1) | packages/webui/tests/settings-write.test.mjs |
|
||||
| 27-form-instances | KILLED (1) | packages/webui/tests/settings-form.test.mjs |
|
||||
| 28-form-limit-payload | KILLED (1) | packages/webui/tests/settings-form.test.mjs |
|
||||
| 29-migration-idempotent | KILLED (1) | packages/cli/tests/limits.test.mjs |
|
||||
| 30-zero-stops-new | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 31-instance-model-edit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 32-model-table-edit | KILLED (1) | packages/business/tests/launch-settings.test.mjs |
|
||||
| 33-runtime-writer-wiring | KILLED (1) | packages/bus/tests/limits.test.mjs |
|
||||
|
||||
All mutations restored their original bytes in finally blocks. Each command was
|
||||
`node --test TEST`, with DOCKER_HOST=unix:///nonexistent.sock in a new process
|
||||
group. Whole-group SIGKILL on timeout; timeouts are failures, never kills.
|
||||
No timeout, syntax error or missing module contributed a kill.
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"base": "f529cf485c8a0ac214076052cb8e16f14864c7a0",
|
||||
"canonicalHead": "46117feb87d38aa2c1393244113acf5864416a24",
|
||||
"drift": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
f529cf485c8a0ac214076052cb8e16f14864c7a0
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
59de512efd425a045b9ae00f0192b49d3cf832665c5710743ca331cb4c885ba8 docs/TOOLS.md
|
||||
4f7a196c4fcf6ba2f07bb35294217cd456cd63cc53b85f707714199ce71f7e4b packages/bus/src/broker.mjs
|
||||
c486eeed430afc1fd1de70c5b3e4299bbab392c04a4bc29167def6d1b39c9825 packages/bus/src/runtime.mjs
|
||||
c64427cfbffd5ec32532d5d18009e5080185c14d9c831cd67b5acbd64e4ccee6 packages/bus/tests/limits.test.mjs
|
||||
37c129d82bc3194a3a21be5510f67b9943e77ed87c6736667ea91f9ca6b836db packages/business/README.md
|
||||
6704bb0d86fd68fcae9c0483ad99577ffbbbf61a9c2db8366697f8aebd152f40 packages/business/examples/mosaic-stack.example.json
|
||||
4f35eded02507e3cbf5c392b8b96d5abedd51738e3b235bf623ed26cff9aba61 packages/business/src/business.mjs
|
||||
4c09f9eeba15f5589ad7a3cfcb7547c713d313fb08541e11ce532695cbb24f55 packages/business/src/index.mjs
|
||||
020c9c7c8097c35a987be3be3ee4ffe4021d861a37cb89a8971c00b6fa2a32a0 packages/business/src/launch-settings.mjs
|
||||
42afbe81d2017b056098773b479c934d351af2a65d6fe0b67b7713abc32cdbc4 packages/business/src/launch.mjs
|
||||
40b296a2a9aec340c0c154ef467c24aecba46d92c5e17edb4b08144609e4c6b7 packages/business/src/migrate-launch.mjs
|
||||
9ae19e9e637e2f668c10455c93085b834817bf9b793e17cee2f1657c8a71197d packages/business/src/organization.mjs
|
||||
b551725cea3cd2699f186b988d1cc627df00d9906f2129ae4e5d667d7cff66d4 packages/business/src/vocabulary.mjs
|
||||
92b07694e40878e92f71e2cb3a539024dca54fbcf5bd71b246571d846959ad87 packages/business/tests/business.test.mjs
|
||||
251d38ac3ba90330c4ff8a8dd3032c8a8fb73037d6819c3ac60a47daefce8fd6 packages/business/tests/chief-of-staff.test.mjs
|
||||
5bfa5a9348f216d67451eb5dbe360d8004055937e6f5e8a6988076faa3a7ac27 packages/business/tests/helpers.mjs
|
||||
c6274d94b559760b431e206a235d2bbf3f45801cff15ddd88666fc10654b673c packages/business/tests/launch-settings.test.mjs
|
||||
e49ddf4bbea1266c272effd7bc15988c5f2f6b55bf8bf0762082ab622b46fabb packages/business/tests/resolve.test.mjs
|
||||
0488d15c54e05bfa6129ba971e5beefbf928b62159250d30a62c18a47aac9190 packages/cli/README.md
|
||||
20f8c4152e4d49d02695c18fe356556789dcb2ee221bbe7cca427d87e4759f28 packages/cli/src/cli.mjs
|
||||
de3b06388f02839b55d27e0821907994bd5ab2e07447a1bf1ba72c0c8127b194 packages/cli/src/config.mjs
|
||||
d84d7fa771e84b84e5ba510e24f3d952272d59bbfaf2b1b8128e1b26fc078e47 packages/cli/src/launcher.mjs
|
||||
b50f7c4924dabacfc03b5fca4eb9cd34e75cdce43ffc5b9405b25082c20dc505 packages/cli/src/limits.mjs
|
||||
a4207650a0ad5d41226c893870a38f20315ff8e8ba53165c5e97d1b9b4a159d6 packages/cli/tests/launch-limits.test.mjs
|
||||
8096a4efa5c4728aba25483e2d1454c5c71dd3c188d76e5e7c91bf1e8a2f5591 packages/cli/tests/launcher.test.mjs
|
||||
427d0f6fc8aebfe50e15d98691f9a99061311d087e665a5c38a60cc39222c7ae packages/cli/tests/limits.test.mjs
|
||||
00b905170134f7154d1851dabcd93318dbc5446ff29f80b00c459c61df36d525 packages/harness/src/bundle.mjs
|
||||
20f91e3423661d442ba7c01280b0776a75cb10050d86ffdee9208d497957e56d packages/harness/tests/pi-session.test.mjs
|
||||
4085e77fe81093b2938cd1f97ff40cd30dbc6684b5f37ba617cc404763263e2c packages/harness/tests/runner.test.mjs
|
||||
86ed3187d74cc3eecacd641aefaa96cff4a04b39a37069059dbd274914699ac1 packages/seat/src/session.mjs
|
||||
bcbc021d1984f93b9ac682bf53e7dfa6a1e7aa4029bb115bc800b862af40e0e0 packages/seat/tests/session.test.mjs
|
||||
a035076c6596e6de0d634d3fb5a1b2859800ad2346811dc747ff86c0c8b612b4 packages/webui/src/bus.mjs
|
||||
7855d1e29e2561eae21ee6c429f3a8fc085f429cc7a25909185db909e8dc9ee8 packages/webui/src/cli.mjs
|
||||
a75bdd407e379be9ea87741db9413dfc4eb85d8d774f994762f475fcde635e3c packages/webui/src/public/bus.js
|
||||
f6fc93ae58d5af73848567164b6d5c7b6e8d506e9c32b90851247adb9373282f packages/webui/src/reads.mjs
|
||||
c69b76b7489c261b992dc1d6c680e51fd960a7c9f24e07148f7b59eb40e91d75 packages/webui/src/serve.mjs
|
||||
7b9b03f183c603227a53df5a8824348f063a46161ceced32796f459160f9eae1 packages/webui/tests/reads-fixture.mjs
|
||||
d8cd0b9af738245f0ccf44e02106533a41a43d8fc6a8c189458afd83825ca0c1 packages/webui/tests/reads.test.mjs
|
||||
955b0c9f8bbc2c7c71dad45aee0890eed54e34198bd7970961bc180b5bff68b2 packages/webui/tests/settings-form.test.mjs
|
||||
b8433e87f04753be7b5ce3cf6f93173a30eada336cf360b8420b8ff75696f2e6 packages/webui/tests/settings-write.test.mjs
|
||||
c55237b952cdd860828e12c6b746cdfeddda6c85a48b986587abaf01a7534963 packages/webui/tests/shell.test.mjs
|
||||
7cef4e9c8caa93dc68a7b2057c540da3eafe07c6258c884c3f52e10a46382cb1 packages/webui/tests/views.test.mjs
|
||||
db18760a6e93c0db45d272da278717af9844e06c2b859607971661b0aee82121 scripts/mosaic
|
||||
@@ -0,0 +1,3 @@
|
||||
pkg-business 0
|
||||
pkg-bus 0
|
||||
pkg-cli 0
|
||||
@@ -0,0 +1,13 @@
|
||||
pkg-business 0
|
||||
pkg-bus 0
|
||||
pkg-seat 0
|
||||
pkg-harness 0
|
||||
pkg-cli 0
|
||||
pkg-webui 0
|
||||
pkg-control-board 0
|
||||
pkg-conversation 0
|
||||
pkg-ledger 0
|
||||
pkg-tasks 0
|
||||
script-queue 0
|
||||
script-discord 0
|
||||
script-task 0
|
||||
@@ -0,0 +1,7 @@
|
||||
pkg-business 0
|
||||
pkg-bus 0
|
||||
pkg-seat 0
|
||||
pkg-harness 1
|
||||
pkg-harness 0
|
||||
pkg-cli 0
|
||||
pkg-webui 1
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Decision136 builder gate. No live files or services; processes isolated by group."""
|
||||
import os,pathlib,signal,subprocess,sys,json
|
||||
root=pathlib.Path(sys.argv[1] if len(sys.argv)>1 else '/mnt/storage/src/mosaic-stack-rocko-122');out=pathlib.Path(__file__).resolve().parent/'gate';out.mkdir(exist_ok=True)
|
||||
env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'}
|
||||
steps=[('pkg-'+p,['node','--test','--test-concurrency=1','--test-reporter=spec',*map(str,sorted(pathlib.Path('packages',p,'tests').glob('*.test.mjs')))]) for p in []]
|
||||
# Discover paths from the candidate, not the directory from which the runner is invoked.
|
||||
steps=[]
|
||||
for p in ['business','bus','seat','harness','cli','webui','control-board','conversation','ledger','tasks']:
|
||||
files=[str(f.relative_to(root)) for f in sorted((root/'packages'/p/'tests').glob('*.test.mjs'))]
|
||||
steps.append(('pkg-'+p,['node','--test','--test-concurrency=1','--test-reporter=spec',*files]))
|
||||
# The changed script dispatcher is read by queue and discord; task resolves changed business code.
|
||||
for p in ['queue','discord','task']:
|
||||
steps.append(('script-'+p,['bash','scripts/test-'+p+'.sh']))
|
||||
results=[]
|
||||
if os.environ.get('GATE_ONLY'):
|
||||
names=set(os.environ['GATE_ONLY'].split(','));steps=[s for s in steps if s[0] in names];results=[r for r in json.loads((out/'results.json').read_text()) if r['suite'] not in names]
|
||||
if len(sys.argv)>2:
|
||||
start=next(i for i,s in enumerate(steps) if s[0]==sys.argv[2]); prior=json.loads((out/'results.json').read_text()); names={s[0] for s in steps[start:]};results=[r for r in prior if r['suite'] not in names];steps=steps[start:]
|
||||
for name,cmd in steps:
|
||||
with (out/(name+'.log')).open('w') as log:
|
||||
step_env=dict(env)
|
||||
if name=='script-task':step_env.pop('DOCKER_HOST',None)
|
||||
child=subprocess.Popen(cmd,cwd=root,env=step_env,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try:rc=child.wait(timeout=1200)
|
||||
except subprocess.TimeoutExpired:os.killpg(child.pid,signal.SIGKILL);child.wait();rc='timeout'
|
||||
results.append(dict(suite=name,exit=rc,command=cmd));(out/'results.json').write_text(json.dumps(results,indent=2)+'\n');print(name,rc,flush=True)
|
||||
if rc!=0:sys.exit(1)
|
||||
@@ -0,0 +1,166 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (14.844026ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (12.84997ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (24.058901ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (9.610497ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (12.163566ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (11.497937ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (13.045578ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (13.691207ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (60.514285ms)
|
||||
✔ agents: stranded is per role and per business (22.578807ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (8.480099ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (14.332615ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (16.273286ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (16.436354ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (10.662472ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (10.682626ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (15.903014ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (9.710863ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (17.117199ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (6.66024ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (12.1309ms)
|
||||
✔ authority never transfers between action, run, target, unresolved or replaced role holder (16.039823ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (8.367375ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (13.120536ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (8.469146ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (14.163195ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (14.202759ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (1.277516ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (11.733145ms)
|
||||
✔ credentials refuses a role session and any argument (11.043972ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (12.679265ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (60.659373ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (2.434158ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (1.398852ms)
|
||||
✔ expiry refuses use and env references never become client data (0.427332ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (0.982795ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.225205ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (24.262806ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (13.779696ms)
|
||||
✔ a human withdraw sends one message with the note (13.946399ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (16.592904ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (16.832577ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (17.774439ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (15.435615ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (14.373193ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (18.826278ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (18.860754ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (18.099987ms)
|
||||
✔ recent stops at RECENT rows (61.151889ms)
|
||||
✔ every row is what trail already gives the same session for that id (25.72803ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (26.245239ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (24.325387ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (11.888158ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (12.142498ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (11.299436ms)
|
||||
✔ endLaunch leaves a claim another run took alone (11.192429ms)
|
||||
✔ refuse records action.refused against the caller with the code only (8.878521ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (12.2991ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (74.551448ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (1.422526ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.532394ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.673358ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.226372ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (14.707559ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (30.922283ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (16.797386ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (11.38752ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (15.162452ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (221.892602ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (17.100906ms)
|
||||
✔ views messages passes only its paging arguments through (0.259275ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (11.524709ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (63.405794ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (45.269985ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (60.060361ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (86.501212ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (60.928301ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (45.211966ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (62.162379ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (23.889961ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (12.39846ms)
|
||||
✔ a message with no reply gives an empty list (9.48174ms)
|
||||
✔ replies come oldest first and stop at REPLIES (49.716775ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (20.072931ms)
|
||||
✔ strict arguments; a role session gets human-required (22.342641ms)
|
||||
✔ views passes replies through as one call with the id (0.260172ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (16.641329ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (9.395777ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (9.59052ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (19.512113ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (14.089612ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (17.15279ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (23.373996ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (14.766611ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (19.524567ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (24.137758ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (16.089347ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (49.431895ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (19.654508ms)
|
||||
✔ another run cannot consume an approval; a failed check leaves it usable (13.371078ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (10.341648ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (20.298967ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (14.035778ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (14.607792ms)
|
||||
✔ class drift gated to within-role refuses before consumption (13.626736ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (17.835935ms)
|
||||
✔ class drift within-role to gated refuses before consumption (11.807707ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (12.243654ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (14.383965ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (17.045277ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (11.499786ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (8.844644ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (9.451341ms)
|
||||
✔ a tombstone is not open (7.491171ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (10.774382ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (8.625774ms)
|
||||
✔ a human session reads the same state, with the same cap (10.692408ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (8.892325ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (9.611322ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (9.573132ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (8.974715ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (39.250321ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (7.215517ms)
|
||||
✔ async transactions refuse before invoking their function (5.430372ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (122.72866ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (73.228304ms)
|
||||
✔ each filter, alone and together, and total counts every match (158.759482ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (91.831499ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (72.869861ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (323.431485ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (26.185887ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (28.12096ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (6.885219ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (15.927479ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (6.046892ms)
|
||||
✔ a bad entry refuses the whole record (7.099587ms)
|
||||
✔ taskView reads the projection for one business (7.452228ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (14.539223ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (275.563631ms)
|
||||
✔ without an adapter the server refuses every task verb (16.321608ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (16.333511ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (112.065291ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (47.309984ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (14.194129ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (30.940516ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (13.036098ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (16.731485ms)
|
||||
✔ the tester reads the human views a reader reads (18.626743ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.222216ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.343674ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.20371ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (16.118503ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (649.730112ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (19.448606ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (13.892211ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (7.902246ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (11.78367ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (9.56165ms)
|
||||
ℹ tests 158
|
||||
ℹ suites 0
|
||||
ℹ pass 158
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5885.311646
|
||||
@@ -0,0 +1,83 @@
|
||||
✔ config directory and file path follow MOSAIC_CONFIG (1.18386ms)
|
||||
✔ the fixture business validates and comes back frozen (3.580921ms)
|
||||
✔ two instances may share a definition (1.13356ms)
|
||||
✔ top-level refusals (3.055382ms)
|
||||
✔ arbiters and projects (4.175821ms)
|
||||
✔ role instances (2.100841ms)
|
||||
✔ Vikunja bots (5.371142ms)
|
||||
✔ a role without Vikunja takes no tracker block (1.948392ms)
|
||||
✔ credential references match the definition's services (2.234079ms)
|
||||
✔ launch (8.242374ms)
|
||||
✔ loadBusiness: file checks (1.740668ms)
|
||||
✔ loadBusiness: not a regular file (40.650523ms)
|
||||
✔ loading writes nothing (1.145129ms)
|
||||
✔ names that are Object.prototype properties don't count as declared (2.617169ms)
|
||||
✔ the shipped example refuses as written and validates once filled in (0.598597ms)
|
||||
✔ the role file loads and resolves through loadBusiness (4.456847ms)
|
||||
✔ the shipped file is exactly decision 104's list (0.564224ms)
|
||||
✔ the resolved record matches decision 104, so a widened file fails (1.372699ms)
|
||||
✔ message.send is within role and every other action is gated (1.102117ms)
|
||||
✔ a business grant of a gated action through limits does not widen the role (1.098151ms)
|
||||
✔ a launch block whose by is the chief-of-staff instance is refused (1.362043ms)
|
||||
✔ the instance takes no credential references and no tracker (1.899047ms)
|
||||
✔ usage errors exit 4 (278.455448ms)
|
||||
✔ validate: a good business exits 0 and prints instance digests (66.302021ms)
|
||||
✔ validate: project files (332.045786ms)
|
||||
✔ validate: missing files and a broken system config (253.615006ms)
|
||||
✔ validate: credential reference problems exit 2 and name each one (68.879982ms)
|
||||
✔ validate: a token file inside the repository is refused (67.533211ms)
|
||||
✔ validate: role definitions come from MOSAIC_ROLES_DIR (205.856296ms)
|
||||
✔ resolve: prints one instance's record (204.121726ms)
|
||||
✔ resolve: refusals (393.464875ms)
|
||||
✔ parse: exactly one of file or env, plus the service's date (2.004385ms)
|
||||
✔ check: a good file has no problems (0.652115ms)
|
||||
✔ check never opens the file: a write-only token passes (0.319827ms)
|
||||
✔ check: file problems (0.632456ms)
|
||||
✔ check: token files can't live in the repository or dataRoot, even through a linked directory (0.652236ms)
|
||||
✔ check: dates and environment references (0.317422ms)
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.573375ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.653926ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (17.49534ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.528225ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.044508ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.250792ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.874518ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.994965ms)
|
||||
✔ path and load (1.756178ms)
|
||||
✔ refusals (0.861804ms)
|
||||
✔ systemVars flattens the validated config (1.525582ms)
|
||||
✔ precedence: system, business, project, project role, agent (4.080718ms)
|
||||
✔ limits narrow the definition and never widen it (1.765003ms)
|
||||
✔ role.launch stays within-role only for the instance the launch block names (3.530498ms)
|
||||
✔ limits.authority without role.launch leaves the launcher with no launch block (1.455845ms)
|
||||
✔ limits.authority narrows cross-role actions too (0.782821ms)
|
||||
✔ classify (0.907971ms)
|
||||
✔ the record carries what the broker and launcher need (0.80907ms)
|
||||
✔ digest: key order doesn't matter, any value change does (5.292689ms)
|
||||
✔ refusals (2.106715ms)
|
||||
✔ the four shipped version 2 roles load (2.500675ms)
|
||||
✔ shipped role scopes match addendum B section 2 and the SR runbook (0.75362ms)
|
||||
✔ shipped authority follows the note's table (0.42448ms)
|
||||
✔ version 1 files keep loading with no authority (0.850995ms)
|
||||
✔ the conductor policy isn't a role (0.166299ms)
|
||||
✔ a missing role file is exit 4, a symbolic link too (0.319969ms)
|
||||
✔ version 2 refusals (1.049353ms)
|
||||
✔ authority: closed vocabulary, no gated-only action, no overlap (1.575016ms)
|
||||
✔ credentials: Gitea scopes (0.638998ms)
|
||||
✔ credentials: Vikunja scopes are a group-to-verbs map from the grantable list (0.848161ms)
|
||||
✔ credentials: services (0.436933ms)
|
||||
✔ contract: a non-empty regular Markdown file beside the role file (0.507218ms)
|
||||
✔ every key names known layers and a merge rule (0.671028ms)
|
||||
✔ unknown keys and wrong layers refuse (0.554604ms)
|
||||
✔ types (1.454297ms)
|
||||
✔ merge: defaults, then the most specific layer wins (0.221482ms)
|
||||
✔ merge: limits only narrow, and provenance lists each source (0.260633ms)
|
||||
✔ merge doesn't change its inputs (0.104325ms)
|
||||
ℹ tests 75
|
||||
ℹ suites 0
|
||||
ℹ pass 75
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 2500.242245
|
||||
@@ -0,0 +1,204 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1278.704706ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (67.101096ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (154.69603ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (232.701302ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (49.702496ms)
|
||||
✔ the app shows the same decide text as mosaic decide (21.498969ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (189.635405ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (67.38363ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (252.87903ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (31.111355ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (21.272017ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (406.393948ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (31.559779ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (29.539585ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (45.860524ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (288.6538ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8804.337388ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (74.762976ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (30.73264ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (15.599306ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (79.945703ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (15.981151ms)
|
||||
✔ no business: the app says so and :business picks one (9.246726ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (2.12037ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (179.815355ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.469133ms)
|
||||
✔ decide with --note still asks; a No sends nothing (9.983645ms)
|
||||
✔ the app's business comes from a live bus host only (1.236473ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (7.324949ms)
|
||||
✔ draw is pure: same state, same frame (0.812099ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (15.445037ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (12.421187ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (10.171392ms)
|
||||
✔ decide prints a declining choice as declining (9.32729ms)
|
||||
✔ an unknown outcome is reported once and never resent (8.527882ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (8.56156ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (8.79217ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (7.63574ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (7.475851ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (8.263908ms)
|
||||
✔ agents and tasks print through the broker (7.649261ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.221258ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (33.647505ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (57.423514ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (27.827898ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (33.083445ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (29.587825ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (53.080733ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (23.414197ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (23.489038ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (204.112686ms)
|
||||
✔ follow refuses agent context and bad arguments (8.332772ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (9.002956ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (9.574746ms)
|
||||
✔ empty views say so (0.687517ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (0.807911ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.129675ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (309.910835ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (318.91968ms)
|
||||
✔ the size cap refuses a push before any byte (148.721924ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (310.749936ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (148.091236ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (252.37343ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (191.79541ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (186.143444ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (129.96021ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (130.290264ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (541.923639ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (417.761507ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (478.166313ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (42.009833ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (447.646311ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (23.899623ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.537137ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (327.539306ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (824.682544ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (150.209323ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (84.168343ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (457.956777ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.817915ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.75735ms)
|
||||
✔ a live host's lock stays, however old the file is (0.474798ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (762.452242ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (211.651983ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (28.888665ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (35.658326ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (30.005067ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (31.664316ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (92.356977ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (85.179268ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (89.363107ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (96.340225ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (202.056182ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (33.233068ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (81.738181ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (191.888155ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (188.378305ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (188.869775ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1088.017083ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (162.145253ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (82.498429ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (132.441485ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (129.332943ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (75.470125ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (131.472463ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (83.33189ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (140.237861ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (21.443295ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (202.705832ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (255.646099ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (106.595628ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (707.287367ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (58.735833ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (73.849685ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (14.699619ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (9.071232ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (22.048257ms)
|
||||
✔ bus start --pm: the PM runs under its own PID namespace, registered, with a manifest (1215.210163ms)
|
||||
✔ the PM launches a coder through its launch tool; the coder answers; refusals name their code (567.015844ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3542.382384ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --pm and from a session, with no run and no clone left (121.871852ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (190.750037ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (94.678967ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (183.350054ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (243.708479ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (103.265966ms)
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1058.178885ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (631.04212ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3575.03614ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (89.901345ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (93.372049ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (96.932271ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1225.325197ms)
|
||||
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.777212ms)
|
||||
✔ migration needs no bus/config, prints whole converted document, is idempotent and never writes (8.788908ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.130774ms)
|
||||
✔ zoned uses the IANA zone across DST (12.223992ms)
|
||||
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (15.160599ms)
|
||||
✔ two blocking decisions get two DMs with different nonces (9.77422ms)
|
||||
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.187995ms)
|
||||
✔ a failed DM is journaled, backs off, and is retried until it lands (9.906592ms)
|
||||
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (11.869016ms)
|
||||
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (13.092666ms)
|
||||
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (8.828931ms)
|
||||
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (70.484892ms)
|
||||
✔ a restart after the second refusal does not send before that refusal's 30 min are up (36.140142ms)
|
||||
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (10.136365ms)
|
||||
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (8.004457ms)
|
||||
✔ an inbox read failure is logged and the next poll retries (0.660019ms)
|
||||
✔ no Discord id reaches the journal or the log (8.501141ms)
|
||||
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (1.977196ms)
|
||||
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (2.282988ms)
|
||||
✔ the journal: a whole file that is one torn line truncates to empty (1.378782ms)
|
||||
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (0.532459ms)
|
||||
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (0.549922ms)
|
||||
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (1.781663ms)
|
||||
✔ the journal: a symlinked directory refuses and says it is a link (1.715995ms)
|
||||
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.466661ms)
|
||||
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.367042ms)
|
||||
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.427882ms)
|
||||
✔ digest content stays within Discord's 2000 characters (0.270176ms)
|
||||
✔ runLoop never overlaps ticks and stops after the one in flight (111.851273ms)
|
||||
✔ a human command refused with human-required prints the other-tree line and exits 3 (2.205783ms)
|
||||
✔ a --tester command refused with tester-required prints the other-tree line and exits 3 (0.755949ms)
|
||||
✔ other exit-3 refusals print no other-tree line (1.027143ms)
|
||||
✔ the line names no path (0.080224ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (422.653413ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (406.648568ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (400.787255ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (275.50621ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (3283.281506ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (608.139532ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (192.28216ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (218.849037ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (185.836867ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (234.547851ms)
|
||||
✔ inherited service.d override refuses without changing the unit (235.087609ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (187.22481ms)
|
||||
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (28.939242ms)
|
||||
✔ talk --tester refuses text without the [mos test] prefix before any call (10.358056ms)
|
||||
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (16.265535ms)
|
||||
✔ decide, stop and launches take no --tester (10.993645ms)
|
||||
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.607425ms)
|
||||
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (1.807292ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (304.117008ms)
|
||||
✔ the transport writes {business, verb, args} to the child and reads its JSON (42.021624ms)
|
||||
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2188.859738ms)
|
||||
✔ busExit and refuseInsideAgent (0.510023ms)
|
||||
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (42.992061ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1016.166315ms)
|
||||
✔ a late reply the Console has listed still reaches the next talk (2022.348286ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (16.262453ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (12.012683ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (12.491876ms)
|
||||
ℹ tests 194
|
||||
ℹ suites 0
|
||||
ℹ pass 194
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 52132.36275
|
||||
@@ -0,0 +1,132 @@
|
||||
✔ explicit request, Seen, ordinary completion and a new request have distinct attention states (3.75205ms)
|
||||
✔ attention convention ignores reasoning/quoted examples and permits leading blank lines (0.237076ms)
|
||||
✔ completed smoke replies and ordinary questions are idle, not human blockers (0.740896ms)
|
||||
✔ only an explicit first-line input request makes a finished reply waiting (0.181397ms)
|
||||
✔ tool activity, user text, errors and unfinished turns override attention text (0.128617ms)
|
||||
✔ STOP access failure is unknown, not absence, under a non-root identity (27.65209ms)
|
||||
✔ connector Task never inherits Discord routing envelopes; ordinary Task still uses user text (2.878614ms)
|
||||
✔ connector discovery keeps only safe identity; rejects modes, mismatches, links and traversal (1.440799ms)
|
||||
✔ canonical owner identity and STOP are independent; no tmux fallback or forged registration (4.933163ms)
|
||||
✔ connector reply refusal precedes forged live tmux registration; ordinary agent still sends (0.534542ms)
|
||||
✔ server rescans connector discovery and refuses HTTP reply without transport (31.558183ms)
|
||||
✔ connector session links and linked directories are not read (1.12112ms)
|
||||
✔ newer live matching launch marks old activity, preserves history/attention/attribution, then clears on new activity (2.528749ms)
|
||||
✔ CLI print uses the relaunch notice instead of old current preview (59.628491ms)
|
||||
✔ connector owner and fixed task never inherit a native relaunch notice (1.837603ms)
|
||||
✔ equality, stale/unknown/offline, mismatched registration and unknown activity do not assert relaunch (1.488687ms)
|
||||
✔ loadConfig: missing file throws ConfigError (1.348379ms)
|
||||
✔ loadConfig: invalid JSON throws ConfigError (0.283309ms)
|
||||
✔ loadConfig: missing dataRoot throws ConfigError (0.226376ms)
|
||||
✔ loadConfig: relative dataRoot throws ConfigError (0.217024ms)
|
||||
✔ loadConfig: valid config returns dataRoot (0.655765ms)
|
||||
✔ findNewestSession: picks the newest by mtime among two files (0.503274ms)
|
||||
✔ findNewestSession: finds files in nested subdirectories (0.310007ms)
|
||||
✔ findNewestSession: returns null for a missing dir (0.126137ms)
|
||||
✔ readSession: extracts fields, collapses/truncates text, counts a truncated final line (0.640449ms)
|
||||
✔ readSession: model and provider follow the latest model_change entry or assistant turn; null when the log names neither; scanAgent carries them (1.359768ms)
|
||||
✔ readSession: lastError carries the assistant errorMessage only when the last assistant turn errored (0.510907ms)
|
||||
✔ findNewestSession/scan: never read sibling auth or secrets next to a sessions dir (1.137813ms)
|
||||
✔ deriveState: full state table (0.165548ms)
|
||||
✔ rule: newest entry is an assistant message with a tool call, after a question-looking text, is working (0.322908ms)
|
||||
✔ rule: newest entry is a tool result with no assistant text after it is working (0.269971ms)
|
||||
✔ rule: a finished ordinary turn is idle, even if it says your move (0.252313ms)
|
||||
✔ task: the first user message of the session, from text blocks (0.255779ms)
|
||||
✔ task: a plain-string user content is accepted, whitespace collapsed and long text capped (0.259583ms)
|
||||
✔ task: no user message in the log means null (shown as unknown), never a guess (0.240526ms)
|
||||
✔ workspace: the live tmux pane path wins; the session cwd is the fallback; neither means null (0.33869ms)
|
||||
✔ activeProject: basename of the nearest .git directory or .git file above the workspace; none means null (0.454611ms)
|
||||
✔ scan: the written record carries task, workspace and activeProject (0.423141ms)
|
||||
✔ registration: overrides task, project and workspace; every source says registration; registered carries the launch fields; the grouping column is untouched (0.533018ms)
|
||||
✔ registration: empty task and null project/workspace leave the derived values in place; registered is still non-null (0.340643ms)
|
||||
✔ registration: a record whose pid is gone is stale; derived values win, sources say derived, registered stays with alive false; a pid the probe cannot decide is not stale; pidAlive itself (0.88427ms)
|
||||
✔ registration: no registration leaves the Gate A fields exactly as before, and registered is null (0.373513ms)
|
||||
✔ loadRegistrations: a missing seatsDir gives empty lists (0.167388ms)
|
||||
✔ loadRegistrations: one good record, one malformed JSON, one with an unknown field; a stray file under seatsDir is ignored (0.653707ms)
|
||||
✔ matchRegistration: matches by sessionsDir, and by realpath through a symlink; sessionsDir null never matches; same seat name with a different sessionsDir does not match (fleet vs repo darkwing) (0.296212ms)
|
||||
✔ scan: writes the registration override to disk; index.json carries registered and registrationErrors (0.587071ms)
|
||||
✔ scan: a relative seatsDir throws ConfigError; an omitted seatsDir behaves as before (0.687735ms)
|
||||
✔ scanAgent: waitingOnYou is true for waiting/error and false otherwise (0.45922ms)
|
||||
✔ scanAgent: ageSeconds is computed from the injected now (0.234589ms)
|
||||
✔ scanAgent: sessionFile null and state idle when sessions dir is empty but alive (0.137337ms)
|
||||
✔ discoverRepoAgents: finds agents with a sessions dir, skips those without, sorted by name (0.285456ms)
|
||||
✔ discoverFleetAgents: finds agents with a sessions dir, sorted by name, fleet tmux fields (0.39289ms)
|
||||
✔ scan: writes per-agent files and index.json, rerun overwrites, no leftover tmp files (0.749603ms)
|
||||
✔ scan: relative boardDir throws ConfigError (0.08125ms)
|
||||
✔ CLI: scan with assume-alive liveness exits 0, prints board summary, writes board files (53.748453ms)
|
||||
✔ CLI: missing config exits 2 with a refused: message (52.838569ms)
|
||||
✔ CLI: unknown command exits 2 (50.517081ms)
|
||||
✔ CLI: unknown --liveness value exits 2 (49.256105ms)
|
||||
✔ panesRunPi: true when any trimmed line equals 'pi' (0.195637ms)
|
||||
✔ panesRunPi: false for bash-only, claude, empty, or node-pi-style lines (0.069057ms)
|
||||
✔ tmuxIsAlive: a pane running pi is alive (0.156437ms)
|
||||
✔ tmuxIsAlive: session exists but pi has exited is not alive (0.072861ms)
|
||||
✔ tmuxIsAlive: no such tmux session is not alive (0.050394ms)
|
||||
✔ tmuxIsAlive: tmux could not be run at all is unknown (null), never assumed alive (0.059031ms)
|
||||
✔ tmuxIsAlive: passes -L <socket> only when a socket is given (0.092924ms)
|
||||
✔ parsePanes: one pane per line, command and optional tab-separated path (0.079341ms)
|
||||
✔ tmuxInspect: reports the path of the pane running pi, not of a shell pane (0.070498ms)
|
||||
✔ tmuxInspect: no pi pane, no session, or no tmux gives no workspace and the matching liveness (0.09033ms)
|
||||
✔ loadSeen: missing file returns {} (0.18902ms)
|
||||
✔ loadSeen: invalid JSON throws ConfigError (0.212722ms)
|
||||
✔ loadSeen: a JSON array throws ConfigError (0.154707ms)
|
||||
✔ loadSeen: a non-string value throws ConfigError (0.161107ms)
|
||||
✔ markSeen: seen true adds the key and writes seen.json mode 0600, no leftover tmp files (0.307616ms)
|
||||
✔ markSeen: seen false deletes the key (0.233311ms)
|
||||
✔ markSeen: missing, empty, or non-string fields throw ConfigError (0.207346ms)
|
||||
✔ markSeen: project containing '/' throws ConfigError (0.115812ms)
|
||||
✔ markSeen: non-boolean seen throws ConfigError (0.10141ms)
|
||||
✔ scanAgent: a seen mark matching the waiting session's lastTimestamp clears waitingOnYou (0.261188ms)
|
||||
✔ scanAgent: a stale mark (agent wrote something newer) is not seen and waitingOnYou is true (0.22145ms)
|
||||
✔ scanAgent: a working session with a matching mark is not seen (marks only apply to waiting/error) (0.242863ms)
|
||||
✔ scanAgent: an error-state session with a matching mark is seen (0.221702ms)
|
||||
✔ scan: index.seen and waitingOnYou reflect seen.json, which scan never rewrites or deletes (0.467473ms)
|
||||
✔ scan: a corrupt seen.json makes scan throw ConfigError (fail closed) (0.174092ms)
|
||||
✔ taskSetBy: a registered task carries the record's setter; a record without the field (pre-#1511) reads unknown; the value is not copied into registered (0.591007ms)
|
||||
✔ taskSetBy: null whenever the task shown is not the registered one: no registration, an empty registered task, a stale registration; the field is always present (0.552957ms)
|
||||
✔ taskSetBy: scan() reads the field from disk through the seat package (bounded there), writes it to the per-agent record and index, and an invalid on-disk value is a registrationError, never a row value (0.927347ms)
|
||||
✔ isLoopbackHost: recognizes loopback hosts (1.136913ms)
|
||||
✔ isLoopbackHost: rejects non-loopback hosts (3.98672ms)
|
||||
✔ startServer: refuses a non-loopback host with ConfigError, never opens a socket (2.91531ms)
|
||||
✔ startServer: serves page, healthz, and a rescanning /api/board (30.887042ms)
|
||||
✔ startServer: a seatsDir registration overrides the row and index.registered reflects it (5.176596ms)
|
||||
✔ startServer: /api/board returns 500 JSON with an error field when scan throws (2.067307ms)
|
||||
✔ CLI: serve refuses a non-loopback host with exit 2 and a refused: message (50.952826ms)
|
||||
✔ CLI: serve rejects a non-numeric --port with exit 2 (53.249748ms)
|
||||
✔ CLI: scan still works after the async cli refactor (53.22716ms)
|
||||
✔ CLI: live serve prints its URL and answers /healthz (63.739063ms)
|
||||
✔ page.html: esc() escapes every HTML-significant character (1.046684ms)
|
||||
✔ POST /api/seen marks a row; GET /api/board still shows it seen; seen:false clears it (8.351111ms)
|
||||
✔ POST /api/seen without a JSON content-type returns 400 and does not write a mark (3.230604ms)
|
||||
✔ POST /api/seen with invalid JSON returns 400 (2.191135ms)
|
||||
✔ POST /api/seen with a body over 4096 bytes returns 400 (or resets the connection) and writes no mark (2.497317ms)
|
||||
✔ POST /api/seen with a missing agent returns 400 (2.002926ms)
|
||||
✔ POST /api/board returns 405; PUT /api/seen returns 405 (2.145403ms)
|
||||
✔ CLI: scan --print marks a seen row with 's' and the summary line ends with 'N seen)' (54.741614ms)
|
||||
✔ page.html: seenControl() escapes rec.project/agent/lastActivity, and the POST uses a JSON content-type (0.334991ms)
|
||||
✔ page.html: has a collapsed Seen section that lists seen rows with the shared row builder (0.309151ms)
|
||||
✔ page.html: each project has a Hide seen checkbox (default on) beside Hide offline, with a hidden-count note (0.184981ms)
|
||||
✔ page.html: a project header reads "N of N" only while a checkbox hides rows (0.157765ms)
|
||||
✔ page.html: every row shows Task and Active project, derived or the word unknown, with the workspace in the detail (0.31252ms)
|
||||
✔ page.html: task and active project cells show their source via sourceTag(); the detail has a Registered row via registeredText(); SOURCE_LABEL maps registration to registered; every dynamic value in sourceTag/fromSource/registeredText is escaped (0.618644ms)
|
||||
✔ POST /api/reply: runs agent-send.sh with -s from the registration, -S <host>:control-board, -m text plus the fixed trailer, no -L on the default socket, MOSAIC_TMUX_SOCKET stripped; answers delivered with the exit code and both streams (32.706831ms)
|
||||
✔ POST /api/reply: a registration with a tmux socket adds -L <socket> (29.678616ms)
|
||||
✔ POST /api/reply: a non-zero tool exit is a 200 with delivered false, the exit code and the stderr verbatim (27.912241ms)
|
||||
✔ POST /api/reply: refusals before the tool runs: empty or blank or long text 400, unknown row 404, no registration 409, stale registration 409, no tmux session 409, bad JSON 400; the tool is never called (16.019508ms)
|
||||
✔ POST /api/reply: a missing agent-send.sh is a 500 with the path in the error, not a crash (5.496797ms)
|
||||
✔ replyToRow: DEFAULT_AGENT_SEND is the repository's tools/tmux/agent-send.sh and it is executable (0.194523ms)
|
||||
✔ page.html: the reply box appears only where canReply() holds (live registration with a tmux session), the detail has a Reply row, the submit posts JSON to /api/reply, receipts and drafts survive a refresh, and every receipt value is escaped (0.628604ms)
|
||||
✔ startServer: /api/board carries taskSetBy from a live registration and null for the derived rows (2.720726ms)
|
||||
✔ page.html: the task cell and detail show who set a registered task via setByTag()/setByText(), both escaped, only from rec.taskSetBy; the reply gate does not read it (0.31026ms)
|
||||
✔ Host/Origin guard: GET /api/board and POST /api/reply refuse a foreign Host, a wrong port and a cross-origin Origin with 403 JSON, before any scan or send, and never send CORS headers (10.582797ms)
|
||||
✔ Host/Origin guard: loopback names on this port are accepted, with or without a same-origin Origin (32.911417ms)
|
||||
✔ conversation routes (F16): a foreign Host, a wrong port and a cross-origin Origin get 403 before the reader runs, with no CORS headers (7.127992ms)
|
||||
✔ every refusal code the reader can raise has an HTTP status (1.447595ms)
|
||||
✔ conversation routes: catalogue, first page, next page and follow over HTTP; refusals map to 4xx with their code; nothing is written (59.446544ms)
|
||||
ℹ tests 124
|
||||
ℹ suites 0
|
||||
ℹ pass 124
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 1283.867383
|
||||
@@ -0,0 +1,190 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (128.785295ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (7.501402ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (4.045852ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (127.65419ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (191.627471ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (134.726541ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (19.47196ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (15.816745ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.661486ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (5922.87706ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (25122.036615ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (159.106132ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (102.776695ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (287.631416ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (212.09447ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (235.226198ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (36.722154ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (117.431313ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (34.35896ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (100.385078ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (25.170254ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (61.622545ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (59.580643ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.15187ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.260028ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (2.168042ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (6.769396ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (286.980245ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (154.155109ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (281.135157ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2309.924102ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (200.048741ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (308.831133ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (217.276899ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (4425.035389ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (447.645633ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (376.962548ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (270.485921ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (64.649087ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (33.400498ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (44.587852ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3027.905936ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (4.882583ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (31.87394ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (28.068983ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (85.432079ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (195.040466ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (309.231358ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (737.576481ms)
|
||||
✔ E1: a natural engine exit with no member left: an engine-exit stop, stopped on a proof naming the engine, and the scope released (205.855468ms)
|
||||
✔ E2: an engine exit with a tool child alive: the stop ends uncertain and nothing is released; a force stop then ends it (2263.385627ms)
|
||||
✔ E3: an engine exit and a force stop take one escalation slot, in either order (645.671679ms)
|
||||
✔ E4: a shim that doesn't answer: the engine-exit stop misses its deadline, ends uncertain and frees the slot (699.834651ms)
|
||||
✔ E5: an engine exit after a force stop ended uncertain starts no engine-exit stop; the force stop stays current (2446.555171ms)
|
||||
✔ E6: the engine-exit observation refuses a reaped process that isn't the recorded engine: another PID or start ticks (189.030458ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (397.784447ms)
|
||||
✔ R6: releaseCohort releases nothing while the engine runs, for another invocation ID, or for a cohort without a scope (134.003024ms)
|
||||
✔ R7: controller killed after the claim is stopped, before the release: the restart releases the scope (2359.66517ms)
|
||||
✔ R8: controller killed between the two keys' stopped revisions: the restart releases the scope (256.14461ms)
|
||||
✔ R9: a release that ended unavailable is tried again on a confirmed recover, not a refused one (213.726874ms)
|
||||
✔ R10: close releases and signals nothing for a stopped binding whose proof no longer verifies (Filbert N3 on #1536) (195.731648ms)
|
||||
✔ R11: close({ killEngine: true }) after a proven stop sends no signal to the recorded engine PID; a restart releases nothing more (2283.904952ms)
|
||||
✔ R12: a restart onto a claim stopped on a boot proof releases nothing, though its scope is listed (173.201859ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (6.081796ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (31.589628ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (21.47064ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (15.470576ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (27.061272ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (14.310895ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.397788ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (15.552114ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (120.747704ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (37.81147ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (15.275417ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (27.015583ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (24.136558ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.739011ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (24.77177ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (40.205933ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (33.939341ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (19.850611ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.412471ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.269043ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.313492ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.486233ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.209405ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.511ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.878604ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.472922ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.353932ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.107185ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (205.45317ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (39.887732ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (74.335136ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (123.355447ms)
|
||||
✔ H4: self-takeover is refused (13.797372ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (81.242459ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (70.33587ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (18.873513ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (68.602324ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (128.735851ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (15.245785ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (13.48888ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (133.083217ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (67.143985ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (17.46898ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (56.011651ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (22.439209ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (54.463473ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (14.086706ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (118.059955ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.695536ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (468.818598ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (359.064959ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (326.576468ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2413.639817ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (469.903704ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (6.368734ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (5.711992ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.551619ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.554124ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.210776ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.293083ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.656915ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.661976ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.060875ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (6.316356ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (3.957573ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.013926ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (3.979053ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.231957ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.137318ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.472996ms)
|
||||
✔ F9: registrations never add or redirect a root (1.448789ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.740997ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.675387ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.455416ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.742228ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.175212ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.667152ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (489.026588ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.536646ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.542255ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.164936ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.044583ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.768173ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (713.702799ms)
|
||||
✔ the engine pin holds for the installed package (1.734826ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (239.76786ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (478.585097ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (239.886179ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (59.130738ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (29.352805ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (16.733231ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.247928ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (23.915039ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (19.272247ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (113.82729ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (35.679668ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1529.522081ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (14.325818ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (70.287524ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (15.549196ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (16.422768ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (32.704942ms)
|
||||
✔ N10: fake conformance (31.22561ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (30.529752ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (20.899616ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (66.139469ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (29.93512ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (31.285228ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (29.531431ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (16.98411ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (33.770099ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (119.209662ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (141.545796ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (91.271127ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (21.664131ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (17.905369ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (18.05507ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (47.137312ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (36.041072ms)
|
||||
ℹ tests 182
|
||||
ℹ suites 0
|
||||
ℹ pass 182
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 77907.718753
|
||||
@@ -0,0 +1,211 @@
|
||||
✔ sessionModel: agent vars win, then the system's execution settings (8.168026ms)
|
||||
✔ a pi bundle: prompt, policy, tools and manifest, 0600 in a 0700 directory (3.468791ms)
|
||||
✔ a claude-code bundle adds the wrapped gate hook and the MCP config (1.867555ms)
|
||||
✔ the prompt's built-in tools line is the harness's own names, as the manifest lists them (6.597892ms)
|
||||
✔ the prompt names the project clones in the workspace, and none when there are none (4.283634ms)
|
||||
✔ the prompt explains the review loop to a role with push_working, and reviews to one with fetch_review (5.056082ms)
|
||||
✔ a bundle is written once: an existing file refuses (1.122933ms)
|
||||
✔ a path with a single quote can't go into the hook command (1.350921ms)
|
||||
✔ allow exits 0, a deny exits 2 with the reason on stderr (103.262138ms)
|
||||
✔ a missing or wrong policy, or a bad event, exits 2 (80.472006ms)
|
||||
✔ the bundle's wrapped command: a missing gate or node still blocks (1082.988083ms)
|
||||
✔ claude: typed tools through MCP, the hook blocks, builtins outside --tools don't exist (696.331276ms)
|
||||
✔ claude: the hook alone blocks a path outside the workspace (406.874491ms)
|
||||
✔ claude: a second turn resumes the first turn's session (703.495429ms)
|
||||
✔ claude adapter: --restricted is always passed (5.064352ms)
|
||||
✔ claude adapter: MOSAIC_CLAUDE_BIN wins over PATH and must be an absolute executable (18.693934ms)
|
||||
✔ claude adapter: a directory pin exits 2 before it runs; a pin with a space runs (7.780854ms)
|
||||
✔ claude: CLAUDE.md files and auto-memory don't reach the model; without --restricted they do (757.047567ms)
|
||||
✔ claude: a missing hook or MCP file refuses before claude starts (8.332149ms)
|
||||
✔ pi: policy tools and typed tools pass, anything else is blocked (2.648416ms)
|
||||
✔ claude: builtins map from pi names, typed tools need the mcp prefix (0.605139ms)
|
||||
✔ file tool paths must resolve inside the workspace (0.919548ms)
|
||||
✔ pi's own path normalisation can't be used to step out (0.769313ms)
|
||||
✔ a symlink inside the workspace that points out is outside (0.631131ms)
|
||||
✔ a dangling symlink is refused at any depth, in both harnesses (2.289178ms)
|
||||
✔ read is checked under every spelling pi's read would open, in both harnesses (11.540262ms)
|
||||
✔ other spellings cover directories, dangling links and pi's cwd (1.464126ms)
|
||||
✔ a relative path climbs from the workspace's real path, in both harnesses (3.672073ms)
|
||||
✔ claude path fields per tool (0.605885ms)
|
||||
✔ glob patterns stay inside the workspace (0.562484ms)
|
||||
✔ a path that can't be checked is blocked (0.354909ms)
|
||||
✔ fetch_review's have lists the working refs before origin's, and no more than HAVE_MAX (184.84487ms)
|
||||
✔ fetch_review's have orders the working refs newest first within each clone, one clone after another (133.418103ms)
|
||||
✔ a runner git past its time: SIGTERM reaches its process group, and SIGKILL follows after the grace period (1810.578134ms)
|
||||
✔ once a signalled runner git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (303.758884ms)
|
||||
✔ initialize, ping and tools/list (34.02771ms)
|
||||
✔ tools/call goes through the tool socket; a refusal is an isError result (29.45861ms)
|
||||
✔ replies are compact JSON; over the cap a tool error names the size and the cap (33.356564ms)
|
||||
✔ unknown tools and methods are JSON-RPC errors and never reach the socket (29.65213ms)
|
||||
✔ a missing argument is a usage error (24.461637ms)
|
||||
✖ pi: typed tools reach the socket, the gate blocks, agent_end writes the marker (11.63517ms)
|
||||
✖ pi: a reply over the cap is a tool error naming the size and the cap; list_tasks asks for open tasks (3.442663ms)
|
||||
✖ pi: a write through a dangling symlink is blocked, and nothing appears outside (1.875445ms)
|
||||
✖ pi: a read is refused when pi would open another spelling outside (1.602109ms)
|
||||
✖ pi: a relative path climbs from the real path of a workspace behind a symlink (1.618577ms)
|
||||
✖ pi: a relative path climbs from the real path of a dataRoot behind a symlink (1.642946ms)
|
||||
✖ pi: a missing extension refuses before any model call (1.509153ms)
|
||||
✖ pi: an extension without its configuration fails pi's start (1.36882ms)
|
||||
✔ founderCheck: founder variables, then a needed service without a usable token (1.008021ms)
|
||||
✔ turnRequest names the sender, class, reply and decision (0.159275ms)
|
||||
✔ turnRequest says a tester's message is a test and never Jason's instruction (0.185449ms)
|
||||
✔ turnRequest shows the message's own sent time, a day old as well as new (0.137153ms)
|
||||
✔ stateBlock names the launch state with its time and event, and the open tasks with the cap (0.187658ms)
|
||||
✔ a message becomes a turn, the answer goes back as a RESULT, SIGTERM releases and exits 0 (151.046888ms)
|
||||
✔ launches revoked and then restored: the turn's block reads allowed and gives the restore time (167.956836ms)
|
||||
✔ a task closed on the tracker is missing from the next turn's open list (169.133259ms)
|
||||
✔ a message read a day after it was sent shows the time it was sent (88.788867ms)
|
||||
✔ a decision the human resolves becomes a turn citing the decision and the answer (140.097611ms)
|
||||
✔ a failed state read fails the turn: no adapter runs, the sender hears why, the message is read (63.167868ms)
|
||||
✔ a SIGTERM before the claim stops the runner with exit 0 and no claim (54.868212ms)
|
||||
✔ typed tools carry the runner's capability; launch goes to the host's launch socket (271.273677ms)
|
||||
✔ a RESULT gets no automatic reply; failed turns reply with the reason (1197.434566ms)
|
||||
✔ SIGTERM during a turn kills the turn's process group and still exits 0 (126.019891ms)
|
||||
✔ founder credentials stop before the claim (20) (112.482337ms)
|
||||
✔ a refused claim exits 21; an ended run's capability exits 22 (123.073494ms)
|
||||
✔ the launch ending under a running session exits 22 (110.847666ms)
|
||||
✔ a broker that stays unreachable exits 23 after brokerRetries polls (219.098974ms)
|
||||
✔ a broker that is down at the claim exits 23, not 21 (67.915658ms)
|
||||
✔ no capability, or a malformed one, on stdin exits 2 (197.408099ms)
|
||||
✔ a missing or malformed policy exits 2 before the claim (111.898351ms)
|
||||
✔ the PM gets launch, its task verbs and the reads (6.210887ms)
|
||||
✔ list_requirements reads the requirement ids, for a task.create holder with a tracker (3.868419ms)
|
||||
✔ a coder gets no launch, no resolve_decision, and no task tools without a tracker (1.170383ms)
|
||||
✔ a coder with a tracker gets its own task tools and no task_reassign (1.026278ms)
|
||||
✔ launch only when the business's launch block names the instance as launcher (0.952137ms)
|
||||
✔ an action outside the instance's authority has no tool (0.993193ms)
|
||||
✔ the review loop: push_working and request_review for the coder, fetch_review and review_verdict for the reviewer, none for the PM (3.783169ms)
|
||||
✔ callTool: one JSON line out, the result back, a refusal rejects (6.731688ms)
|
||||
✔ list_tasks takes the broker's filters and pages; get_task takes a task_ref (1.916931ms)
|
||||
✔ callTool sends list_tasks done false unless the session names done; other tools as given (1.901888ms)
|
||||
✔ replyText: compact JSON up to the cap, an error naming the size and the cap over it (0.604045ms)
|
||||
ℹ tests 81
|
||||
ℹ suites 0
|
||||
ℹ pass 73
|
||||
ℹ fail 8
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 17599.392947
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:67:1
|
||||
✖ pi: typed tools reach the socket, the gate blocks, agent_end writes the marker (11.63517ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-WaHaiD/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:68:33)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:102:1
|
||||
✖ pi: a reply over the cap is a tool error naming the size and the cap; list_tasks asks for open tasks (3.442663ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-yTEg0Q/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:103:28)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:126:1
|
||||
✖ pi: a write through a dangling symlink is blocked, and nothing appears outside (1.875445ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-DyVqIz/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:127:38)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:150:1
|
||||
✖ pi: a read is refused when pi would open another spelling outside (1.602109ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-uuKz9o/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:161:38)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:211:3
|
||||
✖ pi: a relative path climbs from the real path of a workspace behind a symlink (1.618577ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-jIOToM/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:212:40)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:211:3
|
||||
✖ pi: a relative path climbs from the real path of a dataRoot behind a symlink (1.642946ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-eLp8m1/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:212:40)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:242:1
|
||||
✖ pi: a missing extension refuses before any model call (1.509153ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-izCzMw/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:243:32)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/harness/tests/pi-session.test.mjs:250:1
|
||||
✖ pi: an extension without its configuration fails pi's start (1.36882ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-harness-biz-m6Aiu6/businesses/acme.json launch: instance pm selects unknown model probe-model
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:132:125)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at resolvedFor (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/helpers.mjs:27:20)
|
||||
at session (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:26:20)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/harness/tests/pi-session.test.mjs:251:27)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
✔ sessionModel: agent vars win, then the system's execution settings (7.818791ms)
|
||||
✔ a pi bundle: prompt, policy, tools and manifest, 0600 in a 0700 directory (3.958461ms)
|
||||
✔ a claude-code bundle adds the wrapped gate hook and the MCP config (2.006285ms)
|
||||
✔ the prompt's built-in tools line is the harness's own names, as the manifest lists them (6.767726ms)
|
||||
✔ the prompt names the project clones in the workspace, and none when there are none (4.321076ms)
|
||||
✔ the prompt explains the review loop to a role with push_working, and reviews to one with fetch_review (5.229878ms)
|
||||
✔ a bundle is written once: an existing file refuses (1.138055ms)
|
||||
✔ a path with a single quote can't go into the hook command (1.178722ms)
|
||||
✔ allow exits 0, a deny exits 2 with the reason on stderr (105.209197ms)
|
||||
✔ a missing or wrong policy, or a bad event, exits 2 (75.667182ms)
|
||||
✔ the bundle's wrapped command: a missing gate or node still blocks (1086.870053ms)
|
||||
✔ claude: typed tools through MCP, the hook blocks, builtins outside --tools don't exist (747.639312ms)
|
||||
✔ claude: the hook alone blocks a path outside the workspace (437.905122ms)
|
||||
✔ claude: a second turn resumes the first turn's session (712.601477ms)
|
||||
✔ claude adapter: --restricted is always passed (5.580292ms)
|
||||
✔ claude adapter: MOSAIC_CLAUDE_BIN wins over PATH and must be an absolute executable (18.712325ms)
|
||||
✔ claude adapter: a directory pin exits 2 before it runs; a pin with a space runs (6.03325ms)
|
||||
✔ claude: CLAUDE.md files and auto-memory don't reach the model; without --restricted they do (717.696021ms)
|
||||
✔ claude: a missing hook or MCP file refuses before claude starts (8.027014ms)
|
||||
✔ pi: policy tools and typed tools pass, anything else is blocked (2.436629ms)
|
||||
✔ claude: builtins map from pi names, typed tools need the mcp prefix (0.545655ms)
|
||||
✔ file tool paths must resolve inside the workspace (0.907059ms)
|
||||
✔ pi's own path normalisation can't be used to step out (0.797671ms)
|
||||
✔ a symlink inside the workspace that points out is outside (0.728073ms)
|
||||
✔ a dangling symlink is refused at any depth, in both harnesses (2.222052ms)
|
||||
✔ read is checked under every spelling pi's read would open, in both harnesses (10.70842ms)
|
||||
✔ other spellings cover directories, dangling links and pi's cwd (1.051642ms)
|
||||
✔ a relative path climbs from the workspace's real path, in both harnesses (3.527694ms)
|
||||
✔ claude path fields per tool (0.560541ms)
|
||||
✔ glob patterns stay inside the workspace (0.485835ms)
|
||||
✔ a path that can't be checked is blocked (0.294007ms)
|
||||
✔ fetch_review's have lists the working refs before origin's, and no more than HAVE_MAX (175.213151ms)
|
||||
✔ fetch_review's have orders the working refs newest first within each clone, one clone after another (125.803885ms)
|
||||
✔ a runner git past its time: SIGTERM reaches its process group, and SIGKILL follows after the grace period (1810.345907ms)
|
||||
✔ once a signalled runner git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (306.760621ms)
|
||||
✔ initialize, ping and tools/list (35.641176ms)
|
||||
✔ tools/call goes through the tool socket; a refusal is an isError result (28.433447ms)
|
||||
✔ replies are compact JSON; over the cap a tool error names the size and the cap (36.25454ms)
|
||||
✔ unknown tools and methods are JSON-RPC errors and never reach the socket (27.383742ms)
|
||||
✔ a missing argument is a usage error (25.253669ms)
|
||||
✔ pi: typed tools reach the socket, the gate blocks, agent_end writes the marker (337.882943ms)
|
||||
✔ pi: a reply over the cap is a tool error naming the size and the cap; list_tasks asks for open tasks (314.761128ms)
|
||||
✔ pi: a write through a dangling symlink is blocked, and nothing appears outside (321.01008ms)
|
||||
✔ pi: a read is refused when pi would open another spelling outside (318.063812ms)
|
||||
✔ pi: a relative path climbs from the real path of a workspace behind a symlink (313.87451ms)
|
||||
✔ pi: a relative path climbs from the real path of a dataRoot behind a symlink (315.529524ms)
|
||||
✔ pi: a missing extension refuses before any model call (6.587803ms)
|
||||
✔ pi: an extension without its configuration fails pi's start (280.495828ms)
|
||||
✔ founderCheck: founder variables, then a needed service without a usable token (0.977707ms)
|
||||
✔ turnRequest names the sender, class, reply and decision (0.165136ms)
|
||||
✔ turnRequest says a tester's message is a test and never Jason's instruction (0.194422ms)
|
||||
✔ turnRequest shows the message's own sent time, a day old as well as new (0.118702ms)
|
||||
✔ stateBlock names the launch state with its time and event, and the open tasks with the cap (0.191277ms)
|
||||
✔ a message becomes a turn, the answer goes back as a RESULT, SIGTERM releases and exits 0 (151.877608ms)
|
||||
✔ launches revoked and then restored: the turn's block reads allowed and gives the restore time (170.374365ms)
|
||||
✔ a task closed on the tracker is missing from the next turn's open list (167.916173ms)
|
||||
✔ a message read a day after it was sent shows the time it was sent (89.418575ms)
|
||||
✔ a decision the human resolves becomes a turn citing the decision and the answer (141.776777ms)
|
||||
✔ a failed state read fails the turn: no adapter runs, the sender hears why, the message is read (64.117418ms)
|
||||
✔ a SIGTERM before the claim stops the runner with exit 0 and no claim (49.325445ms)
|
||||
✔ typed tools carry the runner's capability; launch goes to the host's launch socket (272.981431ms)
|
||||
✔ a RESULT gets no automatic reply; failed turns reply with the reason (1191.823731ms)
|
||||
✔ SIGTERM during a turn kills the turn's process group and still exits 0 (94.329678ms)
|
||||
✔ founder credentials stop before the claim (20) (93.650679ms)
|
||||
✔ a refused claim exits 21; an ended run's capability exits 22 (99.618949ms)
|
||||
✔ the launch ending under a running session exits 22 (105.158034ms)
|
||||
✔ a broker that stays unreachable exits 23 after brokerRetries polls (207.676602ms)
|
||||
✔ a broker that is down at the claim exits 23, not 21 (46.942533ms)
|
||||
✔ no capability, or a malformed one, on stdin exits 2 (156.480452ms)
|
||||
✔ a missing or malformed policy exits 2 before the claim (87.86403ms)
|
||||
✔ the PM gets launch, its task verbs and the reads (6.088115ms)
|
||||
✔ list_requirements reads the requirement ids, for a task.create holder with a tracker (3.626245ms)
|
||||
✔ a coder gets no launch, no resolve_decision, and no task tools without a tracker (1.182533ms)
|
||||
✔ a coder with a tracker gets its own task tools and no task_reassign (1.040036ms)
|
||||
✔ launch only when the business's launch block names the instance as launcher (0.983847ms)
|
||||
✔ an action outside the instance's authority has no tool (0.975084ms)
|
||||
✔ the review loop: push_working and request_review for the coder, fetch_review and review_verdict for the reviewer, none for the PM (3.958918ms)
|
||||
✔ callTool: one JSON line out, the result back, a refusal rejects (6.993845ms)
|
||||
✔ list_tasks takes the broker's filters and pages; get_task takes a task_ref (1.928614ms)
|
||||
✔ callTool sends list_tasks done false unless the session names done; other tools as given (1.906119ms)
|
||||
✔ replyText: compact JSON up to the cap, an error naming the size and the cap over it (0.611221ms)
|
||||
ℹ tests 81
|
||||
ℹ suites 0
|
||||
ℹ pass 81
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 19769.962427
|
||||
@@ -0,0 +1,94 @@
|
||||
✔ a raw token file, with or without one trailing newline, reaches curl only through the config stream (123.37792ms)
|
||||
✔ the raw path accepts nothing else, and refuses before curl runs (382.30632ms)
|
||||
✔ the file checks still apply on the raw path: mode, symlink, missing, directory (279.615075ms)
|
||||
✔ the raw path base URL has no override (58.875076ms)
|
||||
✔ the JSON path is unchanged, and JSON never falls through to the raw path (246.894533ms)
|
||||
✔ a file that changes between the two reads refuses before curl runs, with or without a body (711.523072ms)
|
||||
✔ the token reaches no child environment, even with an inherited CFG or SHELLOPTS=allexport (692.970545ms)
|
||||
✔ real helper GET HTTP 200 preserves exit 0 without credentials (17.045287ms)
|
||||
✔ real helper POST HTTP 201 preserves exit 0 without credentials (11.892058ms)
|
||||
✔ real helper GET HTTP 403 preserves exit 1 without credentials (9.797874ms)
|
||||
✔ fixture git subjects only, follow-ups and three session kinds (108.197829ms)
|
||||
✔ text and JSON carry same numbers, open and truncated title (177.417933ms)
|
||||
✔ missing credentials exit 2, no-issues never calls API and shows unknown (138.506559ms)
|
||||
✔ empty range gives no rows and zero totals (100.981912ms)
|
||||
✔ inclusive UTC dates, first-line preamble only, role and seat boundaries (111.506391ms)
|
||||
✔ close-only issue included, even median, missing metadata stays unknown (101.039364ms)
|
||||
✔ unique commits but per-issue links count multiple tags once each (101.368301ms)
|
||||
✔ issue pages of 50, 50 and 7 read 107 issues in 3 pages (292.49288ms)
|
||||
✔ one short page reads 1 page; --no-issues reads none and says so (200.29336ms)
|
||||
✔ a short page 10 is read; a full page 10 refuses at the ceiling (674.027271ms)
|
||||
✔ an issue number on two pages refuses (121.109099ms)
|
||||
✔ a failing page 2 refuses the whole read without its stderr (113.937829ms)
|
||||
✔ page 2 with a malformed record refuses (118.587004ms)
|
||||
✔ page 2 with more than 50 rows refuses (115.787453ms)
|
||||
✔ bad API payload not JSON refuses (92.30169ms)
|
||||
✔ bad API payload {} refuses (91.394246ms)
|
||||
✔ bad API payload [{"number":1}] refuses (89.559933ms)
|
||||
✔ partial or malformed session log refuses with location, not content (101.874754ms)
|
||||
✔ a U+2028 or U+2029 inside a session string is one line, not a malformed record (101.655912ms)
|
||||
✔ no sessions is an empty table; symlink source refuses (165.079235ms)
|
||||
✔ reads only refactor even when another branch is checked out (104.449653ms)
|
||||
✔ invalid dates, reverse dates and duplicate options refuse (63.865815ms)
|
||||
✔ T3 agent assignments do not count as human in Table 2 (106.852182ms)
|
||||
✔ preamble parsing and issue number boundaries (0.54731ms)
|
||||
✔ T3 header: agent, or board from control-board; anything short of the full header is human (0.154119ms)
|
||||
✔ no closed issues with human messages means undefined ratio, not invented zero (0.205236ms)
|
||||
✔ T3: seat, archived, unmapped and Researcher threads count; imported, deleted and other-project threads do not (200.913104ms)
|
||||
✔ T3: the default path is read from HOME and prints no path line; --no-t3 says so (418.774499ms)
|
||||
✔ T3: a HOME with no database exits 1 and names --no-t3 (95.977524ms)
|
||||
✔ T3: a file that is not a database exits 1 and names --no-t3 (100.002614ms)
|
||||
✔ T3: a seat thread renamed to another seat exits 1 naming thread, title and roles (120.187889ms)
|
||||
✔ T3: an unmapped thread addressed as a seat exits 1 (124.910032ms)
|
||||
✔ T3: a header to another thread id is not cross-checked (124.564553ms)
|
||||
✔ T3: no project, or two, for this root exits 1 (307.802161ms)
|
||||
✔ T3: a removed column exits 1 and names it (119.517879ms)
|
||||
✔ T3: a missing table exits 1 and names it (113.365299ms)
|
||||
✔ T3: a counted row with an unknown role exits 1 without its text (119.962024ms)
|
||||
✔ T3: a counted row with role reasoning without the reasoning: id prefix exits 1 without its text (122.224398ms)
|
||||
✔ T3: a counted row with non-text content exits 1 without its text (119.543402ms)
|
||||
✔ T3: a counted row with an unparseable created_at exits 1 without its text (123.503581ms)
|
||||
✔ T3: a reasoning summary is skipped before any check and counted as excluded (312.361041ms)
|
||||
✔ T3: a missing orchestration_events makes the diagnostic unknown and keeps the counts (212.934483ms)
|
||||
✔ T3: a human message with no event counts in humanWithoutEvent (120.021881ms)
|
||||
✔ T3: an unparseable event makes the diagnostic unknown and keeps the counts (215.900187ms)
|
||||
✔ T3: an event with no string messageId makes the diagnostic unknown and keeps the counts (217.498886ms)
|
||||
✔ T3: an error that is not from SQLite is rethrown, not reported as a database failure (64.012897ms)
|
||||
✔ T3: a symlink at ~/.t3 exits 1 (89.535883ms)
|
||||
✔ T3: a symlink at ~/.t3/userdata exits 1 (89.449768ms)
|
||||
✔ T3: a symlink at ~/.t3/userdata/state.sqlite exits 1 (92.576756ms)
|
||||
✔ T3: with --t3-db, a symlinked file or directory exits 1 (171.398258ms)
|
||||
✔ T3 WAL: the newest message only in -wal, writer attached, is counted (125.927814ms)
|
||||
✔ T3 WAL: stopped cleanly, counts are correct and the main file is unchanged (135.451618ms)
|
||||
✔ T3 WAL: -wal without -shm in a writable directory is read (146.617888ms)
|
||||
✔ T3 WAL: -wal without -shm in a read-only directory exits 1 (144.474456ms)
|
||||
✔ T3 WAL: stopped cleanly in a read-only directory exits 1 (123.799419ms)
|
||||
✔ T3: a lock held past the 5 s busy timeout exits 1 and names --no-t3 (5125.24606ms)
|
||||
✔ a done row whose closing issue is open is a violation; a row that is not done is not (1.940006ms)
|
||||
✔ an issue several rows close is expected closed only once all of them are done (0.531751ms)
|
||||
✔ closure needs positive evidence: unknown is undecided, and so is a skipped or short issue check (0.362485ms)
|
||||
✔ each owner of an in-progress or in-review row gets one liveness class (7.967527ms)
|
||||
✔ a required row not done after 14 days is a violation; a legacy row uses genesis as its lower bound (0.368263ms)
|
||||
✔ an ISO requiredSince, as `set required` writes it, ages from its UTC day; one that does not parse is a violation (0.240271ms)
|
||||
✔ the text section always ends in a count and a result, and never prints a full pass (0.322675ms)
|
||||
✔ pidAlive: a running pid is present, an exited one is gone, and EPERM still means present (24.736297ms)
|
||||
✔ issue states: open list first, then the metric page, then at most 10 lookups (285.312304ms)
|
||||
✔ a full open list: lookups settle what it leaves out, and only an unsettled issue keeps it undecided (369.131828ms)
|
||||
✔ the open list refuses on a failed call or a bad record, and never echoes the helper (171.638932ms)
|
||||
✔ a helper call past the deadline is killed with its child, and the call reports it (2009.864394ms)
|
||||
✔ readQueue loads queue.json through the queue validator and refuses anything else (92.627838ms)
|
||||
✔ protected changes list every in-range entry that changes a required or parked row (262.64392ms)
|
||||
✔ the CLI prints the queue section above the weekly table and under a queue key in --json (511.19307ms)
|
||||
✔ a queue with nothing wrong prints 0 violations and a reduced pass, never a full pass (208.335657ms)
|
||||
✔ --no-issues makes no call and leaves the issue checks undecided; --no-queue skips the section (280.702631ms)
|
||||
✔ the CLI refuses a bad queue before any call, and a failed open list with exit 2 (254.41276ms)
|
||||
✔ --unsupported-runtime repeats once per seat and takes a seat name (314.94377ms)
|
||||
✔ an unreadable config makes every owner invalid instead of passing them (139.36013ms)
|
||||
ℹ tests 86
|
||||
ℹ suites 0
|
||||
ℹ pass 86
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 20644.355848
|
||||
@@ -0,0 +1,145 @@
|
||||
✔ a first launch clones the root at its branch, with the root's path as origin (34.762772ms)
|
||||
✔ the clone is not at its place until git clone has finished (24.392972ms)
|
||||
✔ a later launch fast-forwards a clean clone after a commit to the root, then finds it current (67.507913ms)
|
||||
✔ a clone ahead of the root keeps its commits and counts as current (42.201437ms)
|
||||
▶ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves
|
||||
✔ a modified file (50.384168ms)
|
||||
✔ an untracked file (50.349337ms)
|
||||
✔ a staged file (50.439993ms)
|
||||
✔ another branch (48.82057ms)
|
||||
✔ a detached HEAD (48.576973ms)
|
||||
✔ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves (249.93949ms)
|
||||
✔ a diverged clone gets the fetch into refs/remotes and is kept, not-fast-forward (50.569586ms)
|
||||
▶ a clone kept before the branch check, or for a failed status, gets no fetch
|
||||
✔ not-a-clone (29.013035ms)
|
||||
✔ hooks-present (31.155339ms)
|
||||
✔ submodule (40.261519ms)
|
||||
✔ config-changed (38.451507ms)
|
||||
✔ root-unreadable (33.102566ms)
|
||||
✔ root-detached (37.862623ms)
|
||||
✔ status-failed, on the root's branch and clean (42.163126ms)
|
||||
✔ status-failed, dirty (40.986973ms)
|
||||
✔ a clone kept before the branch check, or for a failed status, gets no fetch (294.484876ms)
|
||||
✔ a dirty clone whose fetch fails is kept, fetch-failed, exactly as it was (44.693348ms)
|
||||
✔ every git call the host makes, for a new clone and an existing one, carries maintenance.auto=false and gc.auto=0 (52.290939ms)
|
||||
✔ a clone with loose objects enough for gc --auto gets no maintenance or gc from the fetch and the merge (82.04286ms)
|
||||
▶ a clone with user.name or user.email in its config is kept, and git runs nothing in it
|
||||
✔ user.name (30.396975ms)
|
||||
✔ user.email (30.005667ms)
|
||||
✔ a clone with user.name or user.email in its config is kept, and git runs nothing in it (60.936933ms)
|
||||
✔ a commit git can't read after the fast-forward is null (57.418257ms)
|
||||
✔ a new clone whose commit can't be read refuses the launch and leaves nothing behind (25.980558ms)
|
||||
▶ a clone the session rigged is kept, and git runs nothing and writes nothing outside it
|
||||
✔ core.fsmonitor (48.085258ms)
|
||||
✔ core.hooksPath (39.547321ms)
|
||||
✔ a hook file (37.168737ms)
|
||||
✔ include.path (39.409975ms)
|
||||
✔ includeIf (40.458444ms)
|
||||
✔ a filter driver (40.964003ms)
|
||||
✔ origin moved (40.172867ms)
|
||||
✔ a second origin url (39.382989ms)
|
||||
✔ the origin url twice, both the root (41.912462ms)
|
||||
✔ an ext:: origin (40.168172ms)
|
||||
✔ a branch tracking another remote (40.686981ms)
|
||||
✔ a branch merging a tag (41.672265ms)
|
||||
✔ a fetch line onto local branches (45.138665ms)
|
||||
✔ no origin (40.438794ms)
|
||||
✔ a config file over the size cap (38.140512ms)
|
||||
✔ config a symlink to /dev/zero (37.94704ms)
|
||||
✔ the clone a symlink to the bait (36.366921ms)
|
||||
✔ the clone a file (37.654287ms)
|
||||
✔ the clone a plain directory (37.07824ms)
|
||||
✔ .git a gitdir: file (37.825589ms)
|
||||
✔ .git a symlink (37.033947ms)
|
||||
✔ .git/logs a symlink (37.571622ms)
|
||||
✔ .git/refs/heads a symlink (38.068007ms)
|
||||
✔ .git/objects a symlink (36.400729ms)
|
||||
✔ a reflog hard-linked to a file outside (35.937711ms)
|
||||
✔ HEAD a fifo (42.206739ms)
|
||||
✔ a commondir file (36.229585ms)
|
||||
✔ an alternates file (36.235378ms)
|
||||
✔ a gitlink staged, no .gitmodules (50.611631ms)
|
||||
✔ a gitlink and .gitmodules staged (52.084673ms)
|
||||
✔ a gitlink to a repository with its own gitlink (61.234361ms)
|
||||
✔ a gitlink and .gitmodules committed (56.278986ms)
|
||||
✔ a gitlink and submodule.active in config (51.309571ms)
|
||||
✔ a .git/modules with no gitlink (39.854539ms)
|
||||
✔ a clone the session rigged is kept, and git runs nothing and writes nothing outside it (1416.525614ms)
|
||||
▶ a root that can't be cloned refuses with the project id and leaves nothing behind
|
||||
✔ missing (11.973295ms)
|
||||
✔ not a repository (12.419977ms)
|
||||
✔ a plain directory inside another repository (17.475556ms)
|
||||
✔ unreadable (11.920103ms)
|
||||
✔ on no branch (13.403861ms)
|
||||
✔ missing an object (18.089899ms)
|
||||
✔ a root that can't be cloned refuses with the project id and leaves nothing behind (86.292472ms)
|
||||
✔ a clone whose root is on no branch, or gone, is kept and named (35.270044ms)
|
||||
✔ no credential or forge remote of the root reaches a clone (54.944664ms)
|
||||
✔ every project in the business file gets its own clone at its own branch (42.280157ms)
|
||||
✔ a clone past its time gets SIGTERM and refuses the launch, with nothing left in the workspace (516.579089ms)
|
||||
✔ a clone that ignores SIGTERM gets SIGKILL once the grace period is over (1020.612382ms)
|
||||
✔ a timeout signals git's process group, so a process git started dies with it (517.21997ms)
|
||||
✔ once a signalled git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (516.732595ms)
|
||||
✔ RUNNER_FILES is exactly what the runner and the harness sources it starts import (1.713811ms)
|
||||
✔ sandboxProblem names a missing bwrap and a bwrap that fails (9.281003ms)
|
||||
✔ every bind says why; the bundle and session file stay read-only over the run directory (1.297611ms)
|
||||
✔ the host's git socket is bound only when given, read-only and before the writable binds (0.773336ms)
|
||||
✔ the git identity is the instance's, at <instance>@<business>.mosaic.invalid, and sandboxArgv refuses without it (1.119561ms)
|
||||
✔ a confined session's shell reaches its own workspace and run directory and nothing of the founder's or another session's (1901.554686ms)
|
||||
✔ a bind that exposes a stand-in, or a missing workspace bind, fails the matching check (2762.626808ms)
|
||||
✔ a confined session that runs tester-cli.mjs is refused as tester, and the same shim outside the sandbox binds (236.97772ms)
|
||||
✔ resolveSeat: by name under --repo resolves the repo layout (1.255593ms)
|
||||
✔ resolveSeat: by path resolves the fleet layout (0.322748ms)
|
||||
✔ resolveSeat: refusals for missing dir, missing launch.sh, non-executable launch.sh, invalid name, and unknown layout (0.771443ms)
|
||||
✔ tmuxContext: outside tmux, default socket, custom socket, and exec failure (0.635453ms)
|
||||
✔ makeRegistration produces a record that validates; each shape violation throws SeatError (0.804646ms)
|
||||
✔ writeRegistration/readRegistration: round trip, permissions, absence, and malformed records (1.29069ms)
|
||||
✔ updateTask: changes task, taskSetBy and updatedAt only, and refuses appropriately (1.190737ms)
|
||||
✔ CLI launch: registers, execs the fake launch script, and passes args through (32.522791ms)
|
||||
✔ CLI launch: --harness lands in the record (29.016832ms)
|
||||
✔ CLI launch: the launch script's own exit code passes through (29.300911ms)
|
||||
✔ CLI launch: relaunching a seat rewrites the one registration record (64.063432ms)
|
||||
✔ CLI launch: omitting --task records an empty string, not null (28.472264ms)
|
||||
✔ CLI seat task: updates only the task after a launch, and refuses on an unlaunched seat (85.438256ms)
|
||||
✔ CLI refusals: no args, unknown flag, missing config, already-registered env, and exec failure (136.64763ms)
|
||||
✔ samePath: equal paths, symlinked dirs, distinct dirs, and non-strings (0.474047ms)
|
||||
✔ resolveSetBy: explicit --by wins over the environment; absent or empty environment gives unknown; invalid explicit or environment values refuse with exit 4 (0.687802ms)
|
||||
✔ validateRegistration/readRegistration: taskSetBy is optional; a record without it (written before #1511) still loads unchanged; an invalid one is refused; the version does not change (0.80486ms)
|
||||
✔ updateTask: records setBy, preserves startedAt and every unrelated field, upgrades an old record in place only when the task is set, and replaces a previous attribution (1.221718ms)
|
||||
✔ CLI seat task: --by beats MOSAIC_AGENT_NAME, the environment beats nothing, empty environment is unknown, invalid --by or environment refuses with exit 4 and leaves the record byte for byte (276.061984ms)
|
||||
✔ REQ-LIMIT-1: family substring matching is no longer exported (0.737535ms)
|
||||
✔ sessionEnv passes only the allowlist, the repo's bin on PATH, and the run id (0.728638ms)
|
||||
✔ sessionExit gives a runner's signal death back as the signal; a session credential is one whole set of nonempty variables (0.253899ms)
|
||||
✔ newRun: short ids, 0700 directories, and a refusal when the socket path won't fit (1.658932ms)
|
||||
✔ session file and launch log: 0600, the session file written once (1.136586ms)
|
||||
✔ endReason maps the runner's exit codes; a signal is killed (0.159886ms)
|
||||
✔ Registry mirrors to sessions.json; readSessions marks live entries; bad files refuse (1.495976ms)
|
||||
✔ stopSession refuses an unknown run, reports a stale one, and won't signal a pid that isn't a runner (1.01627ms)
|
||||
✔ a session runs in its sandbox as pid 1 of its namespace, claims, answers, and stops on mosaic stop (240.892431ms)
|
||||
✔ workRef and validBranch take only what a ref name can hold (1.139115ms)
|
||||
✔ a push lands as the task's work ref, a fast-forward lands after it, and main is the root's (103.64255ms)
|
||||
✔ a rewritten branch refuses non-fast-forward and the work ref stays (93.406115ms)
|
||||
✔ a branch with no history in common with main refuses unrelated-history (50.81908ms)
|
||||
✔ a bundle that needs commits the working repository lacks refuses missing-prerequisite (42.953755ms)
|
||||
✔ main is fetched from the root again before each push, so a clone of a newer root pushes (107.037534ms)
|
||||
✔ a root moved back after the clone leaves the push's base unknown: missing-prerequisite (67.97108ms)
|
||||
✔ a commit with a broken object refuses invalid-bundle, and only because fsck is on (65.955193ms)
|
||||
✔ only a v2 bundle with the named branch is read (50.76779ms)
|
||||
✔ a branch named main, or named for another task, moves only this task's work ref (82.120058ms)
|
||||
✔ a record that throws moves the work ref back, or removes a new one (116.563588ms)
|
||||
✔ a work ref that can't go back refuses rollback-failed, naming the ref and the commit (328.351104ms)
|
||||
✔ a root that can't be read refuses root-unreadable (33.484681ms)
|
||||
✔ a git past its time gets SIGTERM, leaves no ref lock, and the next push lands (2134.550969ms)
|
||||
✔ a git that ignores SIGTERM gets SIGKILL once the grace period is over (1029.78467ms)
|
||||
✔ a working repository path that isn't a directory refuses (27.346715ms)
|
||||
✔ review bundles a pushed commit as refs/mosaic/review, leaving out what the reviewer has (108.963346ms)
|
||||
✔ review of a project with no working repository refuses unknown-commit (14.536127ms)
|
||||
✔ the runner's git tools hold the host's limits and branch rule (1.265638ms)
|
||||
ℹ tests 132
|
||||
ℹ suites 0
|
||||
ℹ pass 132
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 15879.176534
|
||||
@@ -0,0 +1,100 @@
|
||||
✔ the boot config is checked before anything starts (12.939495ms)
|
||||
✔ a business with no tracker entry refuses task verbs (10.215351ms)
|
||||
✔ credential.expiring and .expired are recorded once per instance (22.865583ms)
|
||||
✔ a token file that changes on disk records credential.changed (10.058617ms)
|
||||
✔ autostart polls, reconciles and retries a startup the tracker was down for (34.035585ms)
|
||||
✔ a refusal a restart must clear is not retried by the poll (7.113779ms)
|
||||
✔ a poll that fires while two are queued is dropped (9.125266ms)
|
||||
✔ close waits for a running verb and refuses one that has not started (37.50242ms)
|
||||
✔ the bundled Vikunja is the pinned upstream image the runbook names (0.685362ms)
|
||||
✔ every published port is on 127.0.0.1, and no secret is in the file (0.262815ms)
|
||||
✔ the committed table loads frozen; its verbs are the broker task verbs (1.364965ms)
|
||||
✔ a write names a verb the table has as its own key, not one it inherits (0.462961ms)
|
||||
✔ the schema refuses any other shape (2.634625ms)
|
||||
✔ the Field table in the slice 1 plan names the verbs each field is written by (0.598395ms)
|
||||
✔ each verb refuses, asks for a decision and writes as the table and the role files say (143.12078ms)
|
||||
✔ the list holds the PRD's requirement ids, in its order, at its version (1.330409ms)
|
||||
✔ the committed list loads frozen (0.580302ms)
|
||||
✔ the schema refuses any other shape (2.291123ms)
|
||||
✔ the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent (84.454655ms)
|
||||
✔ the project list holds recorded project objects in the recorded list envelope (7.012049ms)
|
||||
✔ the recorded task bodies pass the checks S3 applies to every read (0.551728ms)
|
||||
✔ the client works against the fake over real HTTP with the platform fetch (94.208593ms)
|
||||
✔ a correct install starts, and the first reconcile records tasks that already exist (22.103798ms)
|
||||
✔ verbs refuse while a business is starting and after startup refused it (12.358145ms)
|
||||
✔ startup refuses a token that can do more than its role needs (31.249429ms)
|
||||
✔ startup refuses an unsupported version and flags an untested one (21.590274ms)
|
||||
✔ startup refuses a board that the runbook did not install (25.944417ms)
|
||||
✔ startup refuses a project the sync bot cannot read (6.42912ms)
|
||||
✔ startup refuses a configured label the pm bot cannot see (7.439894ms)
|
||||
✔ startup refuses an expired credential and a missing sync credential (13.435271ms)
|
||||
✔ an unreachable tracker refuses with tracker-unavailable (6.891073ms)
|
||||
✔ an edit in the UI is recorded once, with the fields that changed (73.523817ms)
|
||||
✔ a move between open buckets is seen on the board, though updated does not change (36.156003ms)
|
||||
✔ a person's comment is counted and a bot's is not (64.370885ms)
|
||||
✔ the hourly reconcile catches a comment through comment_count (78.421175ms)
|
||||
✔ a task closed in the UI leaves the open view with its done bucket (113.742077ms)
|
||||
✔ a task that leaves the board is recorded as deleted, moved or out of reach (64.192387ms)
|
||||
✔ a poll that read before a verb wrote does not overwrite the verb (35.283025ms)
|
||||
✔ a tracker fault during a tick is reported and the next tick catches up (35.036956ms)
|
||||
✔ a malformed answer refuses the tick with tracker-shape (11.725937ms)
|
||||
✔ no token value reaches the database, the log or a refusal (45.129224ms)
|
||||
✔ the first look at a task counts only comments inside the window (34.33865ms)
|
||||
✔ with descendants off the adapter reads no project list and no child, as in v0 (40.852277ms)
|
||||
✔ a three-level tree is read per project, and a project outside it is not (17.34619ms)
|
||||
✔ a watch-only child keeps the business ready, and a failed child read refuses as transient (19.716976ms)
|
||||
✔ a root without the installed buckets refuses with descendants on (6.533414ms)
|
||||
✔ the project list refuses without read_all, and skips archived projects and saved filters (16.366636ms)
|
||||
✔ descendants must be true or false (6.752431ms)
|
||||
✔ a move inside the tree is a moved tombstone plus a snapshot under the new ref (59.370477ms)
|
||||
✔ a child made after startup joins the tree at the next reconcile (53.308118ms)
|
||||
✔ a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history (57.93008ms)
|
||||
✔ a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses (82.094241ms)
|
||||
✔ a reconcile that fails keeps the previous tree (32.201321ms)
|
||||
✔ a closed task the cursor missed takes its own project's done bucket (31.982887ms)
|
||||
✔ closed tasks read at startup take their own project's done bucket (9.130078ms)
|
||||
✔ a closed task the cursor returns takes its own project's done bucket (34.579827ms)
|
||||
✔ a task moved out of a child that leaves the tree at the same time is moved, not no-access (32.496281ms)
|
||||
✔ a task in a bucket outside the five keeps its raw bucket id (30.205531ms)
|
||||
✔ bucket 0 on a watch-only task never becomes a bucket or a state (79.195315ms)
|
||||
✔ a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only (55.835367ms)
|
||||
✔ a child dropped at a tick comes back at the next reconcile once the bot reads it again (34.263031ms)
|
||||
✔ task.create needs a recorded human request and a requirement id (31.063883ms)
|
||||
✔ task.create takes only an approved requirement id (18.702928ms)
|
||||
✔ task.create cites the request a received message carries, not the message's id (14.046276ms)
|
||||
✔ only labels named in the business file can be written (19.739237ms)
|
||||
✔ task.schedule sets and clears a due date and relations (25.309948ms)
|
||||
✔ assign and reassign move the role bots and record task.assigned (51.98631ms)
|
||||
✔ task.update.assigned is for the assignee and records task.state (49.654829ms)
|
||||
✔ a wrong expected digest records task.conflict and writes nothing (16.955346ms)
|
||||
✔ a cross-role verb needs a resolved decision, used once (21.87719ms)
|
||||
✔ task.close needs a verdict; after it every verb refuses with task-done (21.895181ms)
|
||||
✔ a task with pushed work closes only citing an approve verdict for its latest push, and a refusal writes nothing (27.397801ms)
|
||||
✔ a lost answer is settled by a re-read and never retried (25.270444ms)
|
||||
✔ a create whose answer is lost is reported uncertain, and the poll finds the task (35.087452ms)
|
||||
✔ a task the sync bot cannot read refuses and records nothing (15.288889ms)
|
||||
✔ verbs and polls for one business run one at a time (84.94132ms)
|
||||
✔ a due date with milliseconds is written to the second (61.982374ms)
|
||||
✔ every write landed and the final read failed: the verb succeeds and records what it wrote (37.158072ms)
|
||||
✔ some writes landed and the final read failed: write-uncertain, and nothing is recorded (13.776414ms)
|
||||
✔ a create whose final read fails succeeds and records task.created (33.116555ms)
|
||||
✔ an edit between the last write and the final read shows as external on the next poll (36.242553ms)
|
||||
✔ task.created is recorded when a later label write fails (13.160218ms)
|
||||
✔ every verb acts in an installed child, on the child's own board (46.311697ms)
|
||||
✔ task.create refuses a project outside the tree, a watch-only one and one that is not an id (25.563841ms)
|
||||
✔ with descendants off, task.create takes only the root project (13.078948ms)
|
||||
✔ a verb on a watch-only task, or a relation to one, refuses with project-not-installed (17.138205ms)
|
||||
✔ a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found (23.736392ms)
|
||||
✔ a task moved to another project of the tree refuses its old ref with task-moved and takes its new one (15.955465ms)
|
||||
✔ a verb and a create in the child record the final read of the child's board (15.228615ms)
|
||||
✔ a create in the child whose final read fails records the child's todo bucket (36.836704ms)
|
||||
✔ a lost answer in the child is settled by a re-read of the child's board (22.822732ms)
|
||||
✔ every related task is read before authority, not only the first (17.252143ms)
|
||||
ℹ tests 92
|
||||
ℹ suites 0
|
||||
ℹ pass 92
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3367.053617
|
||||
@@ -0,0 +1,149 @@
|
||||
✔ the Board: held roles with no machine sessions, a claim with no address, the toggle kept across a reload, and Message addressed to the role (2936.46848ms)
|
||||
✔ a redirect answer on a Board read, a bus read, a conversation read, a board POST, a module read and a send signs the page out: one line, nothing stale, no further reads (5160.113941ms)
|
||||
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (1117.923305ms)
|
||||
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
|
||||
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (1230.96683ms)
|
||||
✔ the README says a refused field table names the file or the key at fault, never a path (0.886823ms)
|
||||
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2781.992981ms)
|
||||
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (59.703386ms)
|
||||
✔ decisions route serves the roles and recent lists from the reader view (29.498354ms)
|
||||
✔ credentials route serves the broker credential status from the reader view (9.731256ms)
|
||||
✔ replies route serves the replies to one message from the reader view (26.988739ms)
|
||||
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (53.175621ms)
|
||||
✔ bus refusals map to statuses and never carry a path or a stack (26.271469ms)
|
||||
✔ humanCall speaks the human transport protocol without blocking the server (1645.751599ms)
|
||||
✔ busReader takes --business, else the live bus host, else refuses (157.728493ms)
|
||||
✔ humanCall kills a transport that runs past its timeout (528.059019ms)
|
||||
✔ serve refuses a --business value that is not a business id (230.043003ms)
|
||||
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (973.712811ms)
|
||||
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2188.131636ms)
|
||||
✔ conversation view: a newer session with no readable history keeps the marker (900.775925ms)
|
||||
✔ conversation view: seats without history say so and offer no reply (682.449342ms)
|
||||
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (686.773153ms)
|
||||
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (51751.477942ms)
|
||||
✔ messages HTTP read pages and preserves metadata; bad arguments refuse before a read; other reads unchanged (75.405984ms)
|
||||
✔ Console Messages lists late unsolicited messages on polling with sender class time read state and trail; nav count includes beyond the page; reads never deliver (954.850693ms)
|
||||
✔ Messages nav count polls on Tasks and Board and clears on a Board refusal; messages 403 refuses local pages (1685.341916ms)
|
||||
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (587.640323ms)
|
||||
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (531.372817ms)
|
||||
✔ copy writes nothing when an archived path is missing at the commit (188.042734ms)
|
||||
✔ a copy that loses the rename race leaves no read-only temp directory behind (348.856837ms)
|
||||
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (356.607411ms)
|
||||
✔ a copy that meets a target holding files says exists: and moves nothing into it (350.927896ms)
|
||||
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (351.566855ms)
|
||||
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (695.842035ms)
|
||||
✔ serve refuses a --checkout that is not an absolute directory path (224.69692ms)
|
||||
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (49.882789ms)
|
||||
✔ preview options are all three or none, and each is checked (6.379186ms)
|
||||
✔ the CLI refuses a partial or invalid preview flag set at start (526.700182ms)
|
||||
✔ the CLI with all three flags serves the preview mode (110.620917ms)
|
||||
✔ a request for the public name needs the header equal to the user id, else 401 and nothing read (15.446418ms)
|
||||
✔ the header name matches without regard to case, and the value compare is exact (3.253706ms)
|
||||
✔ the public name with the header reads the bus views, and the Host and Origin are checked first (24.872198ms)
|
||||
✔ in preview mode every write answers 403 read-only, from the public name and loopback, and reaches nothing (9.199418ms)
|
||||
✔ loopback requests are unchanged in preview mode, and the bus views work with the board down (4.139645ms)
|
||||
✔ a proxy that rewrites Host to the loopback port gets 403 on its first request, whatever the user (14.194931ms)
|
||||
✔ a repeated Host is 400 before any other check, in preview mode and without it (6.349018ms)
|
||||
✔ without the preview flags the public name is refused and writes still reach the board (3.889054ms)
|
||||
✔ redactor: config, dataRoot, any absolute path, Discord ids and the JSON parser quote (1.281636ms)
|
||||
✔ credential state from the date alone, as the bus states it (0.13224ms)
|
||||
✔ queue: rows, one row, ids and methods, notes; no path or id from a row (340.408388ms)
|
||||
✔ queue: a refused read fails closed with the store's text, redacted (177.524053ms)
|
||||
✔ queue: a store that fails to load, or a child that dies, gives a fixed message with no path or stack (739.384273ms)
|
||||
✔ business: names, vars on the allowlist, authority, credential metadata only (8.653435ms)
|
||||
✔ business: missing or invalid file refuses with the module's text, redacted (6.508019ms)
|
||||
✔ business without --business: the live bus host, else no-bus-host; no system config: not-configured (6.103561ms)
|
||||
✔ settings: release, board, loopback address, notifier binding name only (103.215201ms)
|
||||
✔ task fields: the committed table with no reads configured, GET only; a bad table refuses with no path (17.429816ms)
|
||||
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (659.268356ms)
|
||||
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (20790.594595ms)
|
||||
✔ the send box: held roles, the draft and caret across a refresh, each receipt, one POST per Send, and the trail link; the board Reply on a 4xx and a 5xx (2241.476145ms)
|
||||
✔ a sent receipt lists its replies as the page refreshes, oldest first and capped, and marks none delivered or read (11016.08513ms)
|
||||
✔ startServer takes send only as a function and only with the preview mode (5.229073ms)
|
||||
✔ the CLI refuses --send without the preview flags, and without a configured bus (356.936204ms)
|
||||
✔ the CLI with --send and a configured bus sends through the human transport and logs one line (112.837016ms)
|
||||
✔ without --send the route is read-only like every other write, and config says no send (7.314181ms)
|
||||
✔ with --send every other write is still 403 read-only, and nothing reaches the board or bus (5.087457ms)
|
||||
✔ config says send only on the public name with --send on (1.664219ms)
|
||||
✔ a send without the signed-in user is 401 and is neither sent nor logged, loopback included (3.387943ms)
|
||||
✔ each request check refuses before anything is sent, and logs the refusal without the body (11.613877ms)
|
||||
✔ a send passes exactly to, body and in_reply_to, answers the id, and logs it (2.521875ms)
|
||||
✔ a crafted role name cannot forge a log line (1.766539ms)
|
||||
✔ a bus refusal is not sent, with its status; an outcome the bus could not confirm is unknown and never retried (5.693423ms)
|
||||
✔ through the human transport the request is exactly the business, message.send and the keys (74.546824ms)
|
||||
✔ against a real broker: the message is written once as a human send, and its refusals map (19.009327ms)
|
||||
✔ loopback host and board origin fail closed (5.269612ms)
|
||||
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (68.201322ms)
|
||||
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (43.146382ms)
|
||||
✔ unreachable board reports URL; CLI rejects unsupported options (335.477528ms)
|
||||
✔ render prints the unit without the preview flags (8.890971ms)
|
||||
✔ render carries every serve flag, the preview set included (7.253684ms)
|
||||
✔ a partial preview set is refused (14.446438ms)
|
||||
✔ a value the unit cannot carry is refused, for every flag (236.335431ms)
|
||||
✔ the rendered unit names none of the human proof agent markers and sets no agent variable (17.828342ms)
|
||||
✔ install into --dir with --no-reload writes the file whole, then reports unchanged (49.983065ms)
|
||||
✔ install without --no-reload runs daemon-reload and nothing that starts the unit (20.880475ms)
|
||||
✔ uninstall refuses while the unit is running, with or without --no-reload, and removes it once it is not (112.922295ms)
|
||||
✔ status prints the unit state and GET /healthz on the installed port (166.074725ms)
|
||||
✔ usage: an unknown verb or flag, and start or enable, exit 4 (57.966193ms)
|
||||
✔ without --send, render is the template with its placeholders filled, byte for byte (27.48719ms)
|
||||
✔ render --send with the preview set ends ExecStart with --send and changes nothing else (43.456606ms)
|
||||
✔ --send without the whole preview set is refused and writes nothing (109.534677ms)
|
||||
✔ install --send into --dir with --no-reload writes the sending unit, and status says whether it sends (201.937915ms)
|
||||
✔ uninstall and status take no --send (30.070766ms)
|
||||
✔ install refuses while the unit is running, in any state but inactive or failed, and changes nothing (224.376705ms)
|
||||
✔ when the state read fails, install and uninstall refuse with one line and change nothing (57.773885ms)
|
||||
✔ install needs --copy naming a copy that exists, and refuses outside the canonical checkout without --allow-worktree (51.486268ms)
|
||||
✔ install refuses unless the bus unit runs from the same copy, naming both paths, and changes nothing (198.682561ms)
|
||||
✔ render --copy runs the copy and reads the queue in the checkout; without --copy the unit is unchanged (15.724965ms)
|
||||
✔ the uid header takes only an Authentik uid; the username header still takes a username (267.953527ms)
|
||||
✔ a preview value cannot start with - or . (28.32794ms)
|
||||
✔ status names the copy and whether refactor has moved past it, and says when the unit runs from no copy (372.989062ms)
|
||||
✔ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (1017.458276ms)
|
||||
2026-10-15T00:54:07.323Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (16.213763ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (6.173636ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (4.653737ms)
|
||||
✔ tokens.css and icons.svg are byte copies of docs/design (0.96681ms)
|
||||
✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.439387ms)
|
||||
✖ shipped strings are unchanged, and the web keeps its write boundary (3.472041ms)
|
||||
✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5432.864335ms)
|
||||
✔ five states on Board, Inbox, Tasks, Agents and Trail (2611.992641ms)
|
||||
✔ Queue, Business and Settings in their five states, with no move button (3006.229456ms)
|
||||
✔ seeded secrets, Discord ids and paths reach no response and no page; business refusals in the module's words (1127.178669ms)
|
||||
✔ the server log names no config path when the system config refuses (312.740449ms)
|
||||
ℹ tests 112
|
||||
ℹ suites 0
|
||||
ℹ pass 111
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 135408.0237
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/shell.test.mjs:37:1
|
||||
✖ shipped strings are unchanged, and the web keeps its write boundary (3.472041ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
[
|
||||
+ "fetch('/api/settings',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(payload),cache:'no-store',redirect:'manual'});",
|
||||
"fetch('/api/bus/message', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ to, body: text }), cache: 'no-store', redirect: 'manual' });"
|
||||
]
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/shell.test.mjs:57:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ "fetch('/api/settings',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(payload),cache:'no-store',redirect:'manual'});", "fetch('/api/bus/message', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ to, body: text }), cache: 'no-store', redirect: 'manual' });" ],
|
||||
expected: [ "fetch('/api/bus/message', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ to, body: text }), cache: 'no-store', redirect: 'manual' });" ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
✔ the Board: held roles with no machine sessions, a claim with no address, the toggle kept across a reload, and Message addressed to the role (2863.950841ms)
|
||||
✔ a redirect answer on a Board read, a bus read, a conversation read, a board POST, a module read and a send signs the page out: one line, nothing stale, no further reads (4864.831584ms)
|
||||
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (1097.656001ms)
|
||||
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
|
||||
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (1227.543634ms)
|
||||
✔ the README says a refused field table names the file or the key at fault, never a path (0.774443ms)
|
||||
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2782.645471ms)
|
||||
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (60.43979ms)
|
||||
✔ decisions route serves the roles and recent lists from the reader view (29.511702ms)
|
||||
✔ credentials route serves the broker credential status from the reader view (8.842728ms)
|
||||
✔ replies route serves the replies to one message from the reader view (26.939026ms)
|
||||
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (54.182902ms)
|
||||
✔ bus refusals map to statuses and never carry a path or a stack (25.179974ms)
|
||||
✔ humanCall speaks the human transport protocol without blocking the server (1646.554502ms)
|
||||
✔ busReader takes --business, else the live bus host, else refuses (151.868756ms)
|
||||
✔ humanCall kills a transport that runs past its timeout (528.758312ms)
|
||||
✔ serve refuses a --business value that is not a business id (224.287754ms)
|
||||
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (987.665612ms)
|
||||
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (1313.685564ms)
|
||||
✔ conversation view: a newer session with no readable history keeps the marker (894.880222ms)
|
||||
✔ conversation view: seats without history say so and offer no reply (631.331401ms)
|
||||
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (632.107231ms)
|
||||
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (52071.125014ms)
|
||||
✔ messages HTTP read pages and preserves metadata; bad arguments refuse before a read; other reads unchanged (76.491612ms)
|
||||
✔ Console Messages lists late unsolicited messages on polling with sender class time read state and trail; nav count includes beyond the page; reads never deliver (893.797452ms)
|
||||
✔ Messages nav count polls on Tasks and Board and clears on a Board refusal; messages 403 refuses local pages (1617.331849ms)
|
||||
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (610.982136ms)
|
||||
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (533.749186ms)
|
||||
✔ copy writes nothing when an archived path is missing at the commit (185.823072ms)
|
||||
✔ a copy that loses the rename race leaves no read-only temp directory behind (343.228509ms)
|
||||
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (343.098285ms)
|
||||
✔ a copy that meets a target holding files says exists: and moves nothing into it (343.996734ms)
|
||||
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (341.418762ms)
|
||||
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (659.034186ms)
|
||||
✔ serve refuses a --checkout that is not an absolute directory path (233.89929ms)
|
||||
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (50.511818ms)
|
||||
✔ preview options are all three or none, and each is checked (6.284519ms)
|
||||
✔ the CLI refuses a partial or invalid preview flag set at start (521.45779ms)
|
||||
✔ the CLI with all three flags serves the preview mode (111.378664ms)
|
||||
✔ a request for the public name needs the header equal to the user id, else 401 and nothing read (15.704123ms)
|
||||
✔ the header name matches without regard to case, and the value compare is exact (3.860039ms)
|
||||
✔ the public name with the header reads the bus views, and the Host and Origin are checked first (24.541682ms)
|
||||
✔ in preview mode every write answers 403 read-only, from the public name and loopback, and reaches nothing (8.978146ms)
|
||||
✔ loopback requests are unchanged in preview mode, and the bus views work with the board down (4.298663ms)
|
||||
✔ a proxy that rewrites Host to the loopback port gets 403 on its first request, whatever the user (14.038561ms)
|
||||
✔ a repeated Host is 400 before any other check, in preview mode and without it (6.289714ms)
|
||||
✔ without the preview flags the public name is refused and writes still reach the board (4.297741ms)
|
||||
✔ redactor: config, dataRoot, any absolute path, Discord ids and the JSON parser quote (1.195968ms)
|
||||
✔ credential state from the date alone, as the bus states it (0.138527ms)
|
||||
✔ queue: rows, one row, ids and methods, notes; no path or id from a row (334.253616ms)
|
||||
✔ queue: a refused read fails closed with the store's text, redacted (178.141087ms)
|
||||
✔ queue: a store that fails to load, or a child that dies, gives a fixed message with no path or stack (728.521995ms)
|
||||
✔ business: names, vars on the allowlist, authority, credential metadata only (8.729596ms)
|
||||
✔ business: missing or invalid file refuses with the module's text, redacted (6.403225ms)
|
||||
✔ business without --business: the live bus host, else no-bus-host; no system config: not-configured (6.900914ms)
|
||||
✔ settings: release, board, loopback address, notifier binding name only (105.145946ms)
|
||||
✔ task fields: the committed table with no reads configured, GET only; a bad table refuses with no path (17.744641ms)
|
||||
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (647.676352ms)
|
||||
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (20660.09197ms)
|
||||
✔ the send box: held roles, the draft and caret across a refresh, each receipt, one POST per Send, and the trail link; the board Reply on a 4xx and a 5xx (2208.251741ms)
|
||||
✔ a sent receipt lists its replies as the page refreshes, oldest first and capped, and marks none delivered or read (11007.815608ms)
|
||||
✔ startServer takes send only as a function and only with the preview mode (5.189301ms)
|
||||
✔ the CLI refuses --send without the preview flags, and without a configured bus (359.49865ms)
|
||||
✔ the CLI with --send and a configured bus sends through the human transport and logs one line (113.151166ms)
|
||||
✔ without --send the route is read-only like every other write, and config says no send (6.759773ms)
|
||||
✔ with --send every other write is still 403 read-only, and nothing reaches the board or bus (5.071655ms)
|
||||
✔ config says send only on the public name with --send on (1.78012ms)
|
||||
✔ a send without the signed-in user is 401 and is neither sent nor logged, loopback included (3.559391ms)
|
||||
✔ each request check refuses before anything is sent, and logs the refusal without the body (11.613913ms)
|
||||
✔ a send passes exactly to, body and in_reply_to, answers the id, and logs it (2.570758ms)
|
||||
✔ a crafted role name cannot forge a log line (2.02274ms)
|
||||
✔ a bus refusal is not sent, with its status; an outcome the bus could not confirm is unknown and never retried (5.681448ms)
|
||||
✔ through the human transport the request is exactly the business, message.send and the keys (77.173892ms)
|
||||
✔ against a real broker: the message is written once as a human send, and its refusals map (20.236729ms)
|
||||
✔ loopback host and board origin fail closed (5.246404ms)
|
||||
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (69.838144ms)
|
||||
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (42.315831ms)
|
||||
✔ unreachable board reports URL; CLI rejects unsupported options (332.102951ms)
|
||||
✔ render prints the unit without the preview flags (9.272347ms)
|
||||
✔ render carries every serve flag, the preview set included (6.502983ms)
|
||||
✔ a partial preview set is refused (14.56595ms)
|
||||
✔ a value the unit cannot carry is refused, for every flag (242.972249ms)
|
||||
✔ the rendered unit names none of the human proof agent markers and sets no agent variable (17.62552ms)
|
||||
✔ install into --dir with --no-reload writes the file whole, then reports unchanged (48.821135ms)
|
||||
✔ install without --no-reload runs daemon-reload and nothing that starts the unit (21.577986ms)
|
||||
✔ uninstall refuses while the unit is running, with or without --no-reload, and removes it once it is not (110.182469ms)
|
||||
✔ status prints the unit state and GET /healthz on the installed port (164.447541ms)
|
||||
✔ usage: an unknown verb or flag, and start or enable, exit 4 (58.464963ms)
|
||||
✔ without --send, render is the template with its placeholders filled, byte for byte (26.673604ms)
|
||||
✔ render --send with the preview set ends ExecStart with --send and changes nothing else (41.870801ms)
|
||||
✔ --send without the whole preview set is refused and writes nothing (110.503764ms)
|
||||
✔ install --send into --dir with --no-reload writes the sending unit, and status says whether it sends (201.485496ms)
|
||||
✔ uninstall and status take no --send (28.847597ms)
|
||||
✔ install refuses while the unit is running, in any state but inactive or failed, and changes nothing (223.121538ms)
|
||||
✔ when the state read fails, install and uninstall refuse with one line and change nothing (57.604689ms)
|
||||
✔ install needs --copy naming a copy that exists, and refuses outside the canonical checkout without --allow-worktree (51.365616ms)
|
||||
✔ install refuses unless the bus unit runs from the same copy, naming both paths, and changes nothing (191.916287ms)
|
||||
✔ render --copy runs the copy and reads the queue in the checkout; without --copy the unit is unchanged (15.388319ms)
|
||||
✔ the uid header takes only an Authentik uid; the username header still takes a username (267.548182ms)
|
||||
✔ a preview value cannot start with - or . (27.603281ms)
|
||||
✔ status names the copy and whether refactor has moved past it, and says when the unit runs from no copy (358.426375ms)
|
||||
✔ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (1030.434112ms)
|
||||
2026-10-15T00:59:00.978Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (17.472909ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (7.450798ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (5.021258ms)
|
||||
✔ tokens.css and icons.svg are byte copies of docs/design (0.910911ms)
|
||||
✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.658346ms)
|
||||
✔ shipped strings are unchanged, and the web keeps its write boundary (1.964043ms)
|
||||
✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5348.433255ms)
|
||||
✔ five states on Board, Inbox, Tasks, Agents and Trail (2332.278823ms)
|
||||
✔ Queue, Business and Settings in their five states, with no move button (3046.878524ms)
|
||||
✔ seeded secrets, Discord ids and paths reach no response and no page; business refusals in the module's words (1162.057997ms)
|
||||
✔ the server log names no config path when the system config refuses (314.389845ms)
|
||||
ℹ tests 112
|
||||
ℹ suites 0
|
||||
ℹ pass 112
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 133703.305166
|
||||
@@ -0,0 +1,239 @@
|
||||
[
|
||||
{
|
||||
"suite": "pkg-seat",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/seat/tests/checkout.test.mjs",
|
||||
"packages/seat/tests/sandbox.test.mjs",
|
||||
"packages/seat/tests/seat.test.mjs",
|
||||
"packages/seat/tests/session.test.mjs",
|
||||
"packages/seat/tests/working.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-harness",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/harness/tests/bundle.test.mjs",
|
||||
"packages/harness/tests/claude-gate.test.mjs",
|
||||
"packages/harness/tests/claude-session.test.mjs",
|
||||
"packages/harness/tests/gate.test.mjs",
|
||||
"packages/harness/tests/git-tools.test.mjs",
|
||||
"packages/harness/tests/mcp-server.test.mjs",
|
||||
"packages/harness/tests/pi-session.test.mjs",
|
||||
"packages/harness/tests/runner.test.mjs",
|
||||
"packages/harness/tests/tools.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-webui",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/webui/tests/board-held.test.mjs",
|
||||
"packages/webui/tests/browser-edge.test.mjs",
|
||||
"packages/webui/tests/browser.test.mjs",
|
||||
"packages/webui/tests/bus-browser.test.mjs",
|
||||
"packages/webui/tests/bus.test.mjs",
|
||||
"packages/webui/tests/conversation.test.mjs",
|
||||
"packages/webui/tests/discord.test.mjs",
|
||||
"packages/webui/tests/history-return-flow.test.mjs",
|
||||
"packages/webui/tests/messages.test.mjs",
|
||||
"packages/webui/tests/pinned-copy.test.mjs",
|
||||
"packages/webui/tests/preview.test.mjs",
|
||||
"packages/webui/tests/reads.test.mjs",
|
||||
"packages/webui/tests/relaunch.test.mjs",
|
||||
"packages/webui/tests/return-flow.test.mjs",
|
||||
"packages/webui/tests/send-browser.test.mjs",
|
||||
"packages/webui/tests/send.test.mjs",
|
||||
"packages/webui/tests/serve.test.mjs",
|
||||
"packages/webui/tests/service.test.mjs",
|
||||
"packages/webui/tests/settings-form.test.mjs",
|
||||
"packages/webui/tests/settings-write.test.mjs",
|
||||
"packages/webui/tests/shell.test.mjs",
|
||||
"packages/webui/tests/views.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-control-board",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/control-board/tests/attention-flow.test.mjs",
|
||||
"packages/control-board/tests/attention.test.mjs",
|
||||
"packages/control-board/tests/discord.test.mjs",
|
||||
"packages/control-board/tests/relaunch.test.mjs",
|
||||
"packages/control-board/tests/scan.test.mjs",
|
||||
"packages/control-board/tests/serve.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-conversation",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/conversation/tests/claim.test.mjs",
|
||||
"packages/conversation/tests/cohort.test.mjs",
|
||||
"packages/conversation/tests/flows.test.mjs",
|
||||
"packages/conversation/tests/races.test.mjs",
|
||||
"packages/conversation/tests/reader.test.mjs",
|
||||
"packages/conversation/tests/smoke.test.mjs",
|
||||
"packages/conversation/tests/turns.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-ledger",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/ledger/tests/gitea-helper-raw.test.mjs",
|
||||
"packages/ledger/tests/gitea-helper.test.mjs",
|
||||
"packages/ledger/tests/ledger.test.mjs",
|
||||
"packages/ledger/tests/queue-checks.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-tasks",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/tasks/tests/adapter.test.mjs",
|
||||
"packages/tasks/tests/deploy.test.mjs",
|
||||
"packages/tasks/tests/fields.test.mjs",
|
||||
"packages/tasks/tests/requirements.test.mjs",
|
||||
"packages/tasks/tests/shapes.test.mjs",
|
||||
"packages/tasks/tests/startup.test.mjs",
|
||||
"packages/tasks/tests/sync.test.mjs",
|
||||
"packages/tasks/tests/tree.test.mjs",
|
||||
"packages/tasks/tests/verbs.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "script-queue",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"bash",
|
||||
"scripts/test-queue.sh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "script-discord",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"bash",
|
||||
"scripts/test-discord.sh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "script-task",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"bash",
|
||||
"scripts/test-task.sh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-business",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/business/tests/business.test.mjs",
|
||||
"packages/business/tests/chief-of-staff.test.mjs",
|
||||
"packages/business/tests/cli.test.mjs",
|
||||
"packages/business/tests/credentials.test.mjs",
|
||||
"packages/business/tests/launch-settings.test.mjs",
|
||||
"packages/business/tests/project.test.mjs",
|
||||
"packages/business/tests/resolve.test.mjs",
|
||||
"packages/business/tests/role.test.mjs",
|
||||
"packages/business/tests/vars.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-bus",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/bus/tests/agents.test.mjs",
|
||||
"packages/bus/tests/broker.test.mjs",
|
||||
"packages/bus/tests/business.test.mjs",
|
||||
"packages/bus/tests/credential-status.test.mjs",
|
||||
"packages/bus/tests/credentials.test.mjs",
|
||||
"packages/bus/tests/decision-close.test.mjs",
|
||||
"packages/bus/tests/decisions.test.mjs",
|
||||
"packages/bus/tests/end-launch.test.mjs",
|
||||
"packages/bus/tests/human.test.mjs",
|
||||
"packages/bus/tests/limits.test.mjs",
|
||||
"packages/bus/tests/message-citation.test.mjs",
|
||||
"packages/bus/tests/messages.test.mjs",
|
||||
"packages/bus/tests/process.test.mjs",
|
||||
"packages/bus/tests/replies.test.mjs",
|
||||
"packages/bus/tests/requirements.test.mjs",
|
||||
"packages/bus/tests/review.test.mjs",
|
||||
"packages/bus/tests/schema.test.mjs",
|
||||
"packages/bus/tests/single-use.test.mjs",
|
||||
"packages/bus/tests/state.test.mjs",
|
||||
"packages/bus/tests/store.test.mjs",
|
||||
"packages/bus/tests/task-page.test.mjs",
|
||||
"packages/bus/tests/task-read.test.mjs",
|
||||
"packages/bus/tests/tasks.test.mjs",
|
||||
"packages/bus/tests/tester.test.mjs",
|
||||
"packages/bus/tests/transport.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-cli",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/cli/tests/app.test.mjs",
|
||||
"packages/cli/tests/cli.test.mjs",
|
||||
"packages/cli/tests/config.test.mjs",
|
||||
"packages/cli/tests/follow.test.mjs",
|
||||
"packages/cli/tests/format.test.mjs",
|
||||
"packages/cli/tests/git-socket.test.mjs",
|
||||
"packages/cli/tests/host.test.mjs",
|
||||
"packages/cli/tests/launch-limits.test.mjs",
|
||||
"packages/cli/tests/launcher.test.mjs",
|
||||
"packages/cli/tests/limits.test.mjs",
|
||||
"packages/cli/tests/notifier.test.mjs",
|
||||
"packages/cli/tests/other-tree.test.mjs",
|
||||
"packages/cli/tests/stack-copy.test.mjs",
|
||||
"packages/cli/tests/tester.test.mjs",
|
||||
"packages/cli/tests/trackers-boot.test.mjs",
|
||||
"packages/cli/tests/transport.test.mjs",
|
||||
"packages/cli/tests/verbs.test.mjs"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,82 @@
|
||||
toolchain: node v26.8.1
|
||||
|
||||
OK syntax: packages/discord/src/approvals.mjs
|
||||
OK syntax: packages/discord/src/authorize.mjs
|
||||
OK syntax: packages/discord/src/binding.mjs
|
||||
OK syntax: packages/discord/src/cli.mjs
|
||||
OK syntax: packages/discord/src/connector.mjs
|
||||
OK syntax: packages/discord/src/context.mjs
|
||||
OK syntax: packages/discord/src/engine-pi.mjs
|
||||
OK syntax: packages/discord/src/errors.mjs
|
||||
OK syntax: packages/discord/src/gateway.mjs
|
||||
OK syntax: packages/discord/src/git.mjs
|
||||
OK syntax: packages/discord/src/journal.mjs
|
||||
OK syntax: packages/discord/src/notify.mjs
|
||||
OK syntax: packages/discord/src/rest.mjs
|
||||
OK syntax: packages/discord/src/setspark.mjs
|
||||
OK syntax: packages/discord/src/tools.mjs
|
||||
OK syntax: packages/discord/src/web.mjs
|
||||
OK syntax: packages/discord/bin/git-credential.mjs
|
||||
OK syntax: packages/discord/extension/tools.mjs
|
||||
OK syntax: packages/discord/tests/approvals.test.mjs
|
||||
OK syntax: packages/discord/tests/authorize.test.mjs
|
||||
OK syntax: packages/discord/tests/binding.test.mjs
|
||||
OK syntax: packages/discord/tests/connector.test.mjs
|
||||
OK syntax: packages/discord/tests/context.test.mjs
|
||||
OK syntax: packages/discord/tests/copy-service.test.mjs
|
||||
OK syntax: packages/discord/tests/engine.test.mjs
|
||||
OK syntax: packages/discord/tests/fake-pi.mjs
|
||||
OK syntax: packages/discord/tests/gateway.test.mjs
|
||||
OK syntax: packages/discord/tests/git.test.mjs
|
||||
OK syntax: packages/discord/tests/helpers.mjs
|
||||
OK syntax: packages/discord/tests/journal.test.mjs
|
||||
OK syntax: packages/discord/tests/notify.test.mjs
|
||||
OK syntax: packages/discord/tests/offline-check.test.mjs
|
||||
OK syntax: packages/discord/tests/recover.test.mjs
|
||||
OK syntax: packages/discord/tests/rest.test.mjs
|
||||
OK syntax: packages/discord/tests/setspark.test.mjs
|
||||
OK syntax: packages/discord/tests/tools.test.mjs
|
||||
OK syntax: packages/discord/tests/web.test.mjs
|
||||
OK syntax: packages/discord/fixtures/claim-worker.mjs
|
||||
OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs
|
||||
OK syntax: scripts/discord.sh
|
||||
OK syntax: scripts/discord-service.sh
|
||||
OK packages/discord declares no dependencies
|
||||
OK no bot-token-shaped string in packages/discord
|
||||
OK fixture binding uses placeholder ids only
|
||||
OK fixture binding validates
|
||||
OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool
|
||||
OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start
|
||||
OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root
|
||||
OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token
|
||||
OK real pi with protocol vault adds reserve_id to the git verbs
|
||||
OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key
|
||||
OK real pi refuses a git key on a read-only root (fail closed)
|
||||
OK real pi with the pilot flags (--no-tools) exposes no tool at all
|
||||
OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed)
|
||||
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||
OK node --test packages/discord/tests/ (ℹ pass 183)
|
||||
OK scripts/discord.sh --help exits 0
|
||||
OK scripts/discord.sh check without a binding exits 4
|
||||
OK scripts/discord.sh recover without a binding exits 4
|
||||
OK scripts/discord.sh reload without a binding exits 4
|
||||
OK scripts/discord-service.sh without a command exits 4
|
||||
OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP
|
||||
OK service install writes the rendered unit (0644) and leaves no temp file
|
||||
OK service install a second time reports unchanged
|
||||
OK systemd-analyze verify accepts the rendered unit
|
||||
OK service uninstall removes the unit file
|
||||
OK service install with an unknown flag exits 4
|
||||
OK service install with USER unset finishes and names the account for lingering
|
||||
OK pinned render runs copy CLI with copy cwd/repo and no checkout executable
|
||||
OK pinned install writes the rendered unit in a temporary unit directory
|
||||
OK pinned install refuses short prerequisite and writes no unit
|
||||
OK pinned install refuses missing prerequisite and writes no unit
|
||||
OK pinned install refuses cli prerequisite and writes no unit
|
||||
OK pinned install refuses pi prerequisite and writes no unit
|
||||
OK status names the copy from fake systemctl effective cwd
|
||||
OK checkout install explicitly recommends --copy
|
||||
OK wrapper check --offline passes local fixture and makes no network call
|
||||
OK wrapper run --offline refuses usage
|
||||
|
||||
discord suite: 78 passed, 0 failed
|
||||
@@ -0,0 +1,36 @@
|
||||
toolchain: node v26.8.1, git version 2.55.0
|
||||
|
||||
OK syntax: packages/queue/src/cli.mjs
|
||||
OK syntax: packages/queue/src/errors.mjs
|
||||
OK syntax: packages/queue/src/io.mjs
|
||||
OK syntax: packages/queue/src/lock.mjs
|
||||
OK syntax: packages/queue/src/queue.mjs
|
||||
OK syntax: packages/queue/src/review.mjs
|
||||
OK syntax: packages/queue/src/store.mjs
|
||||
OK syntax: packages/queue/tests/commit.test.mjs
|
||||
OK syntax: packages/queue/tests/data.test.mjs
|
||||
OK syntax: packages/queue/tests/dispatch.test.mjs
|
||||
OK syntax: packages/queue/tests/gate-owner.test.mjs
|
||||
OK syntax: packages/queue/tests/helpers.mjs
|
||||
OK syntax: packages/queue/tests/lock.test.mjs
|
||||
OK syntax: packages/queue/tests/migration.test.mjs
|
||||
OK syntax: packages/queue/tests/review.test.mjs
|
||||
OK syntax: packages/queue/tests/store.test.mjs
|
||||
OK syntax: packages/queue/tests/write.test.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/kill-at.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/lock-child.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh
|
||||
OK syntax: scripts/queue-commit.sh
|
||||
OK syntax: scripts/git-hooks/pre-commit
|
||||
OK syntax: scripts/mosaic
|
||||
OK queue-commit.sh, the guard and scripts/mosaic are executable
|
||||
OK packages/queue declares no dependencies
|
||||
ℹ tests 156
|
||||
ℹ pass 156
|
||||
ℹ fail 0
|
||||
OK node --test packages/queue/tests/
|
||||
OK scripts/mosaic queue help
|
||||
skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-122) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||
|
||||
queue suite: 28 passed, 0 failed
|
||||
@@ -0,0 +1,101 @@
|
||||
OK valid task validates (exit 0)
|
||||
OK unknown task key exits 2 (exit 2)
|
||||
OK unsupported taskVersion exits 2 (exit 2)
|
||||
OK invalid task id exits 2 (exit 2)
|
||||
OK empty prompt exits 2 (exit 2)
|
||||
OK NUL in expectExact exits 2 (exit 2)
|
||||
OK out-of-range timeout exits 2 (exit 2)
|
||||
OK missing mission file exits 4 (exit 4)
|
||||
OK task with valid mission validates (exit 0)
|
||||
OK invalid mission exits 2 (exit 2)
|
||||
OK validate missing task exits 4 (exit 4)
|
||||
OK validation does not modify the task file
|
||||
OK prune dry-run exits 0 (exit 0)
|
||||
OK dry-run deleted nothing
|
||||
OK prune --keep=2 --yes removes oldest (exit 0)
|
||||
OK kept exactly 2 newest runs
|
||||
OK newest run kept, oldest pruned
|
||||
OK append-only receipt written (3 entries)
|
||||
OK sessions/workspaces untouched by prune
|
||||
OK prune with invalid keep exits 4 (exit 4)
|
||||
OK mock adapter: gate passes on matching mock response (exit 0)
|
||||
OK mock adapter: expect-mismatch recorded (exit 1)
|
||||
OK mismatch reason recorded
|
||||
OK unknown adapter fails closed (exit 1)
|
||||
OK mission task runs via mock adapter (exit 0)
|
||||
OK mission section injected into generated prompt
|
||||
OK retry of mission run succeeds (exit 0)
|
||||
OK retriedFrom lineage recorded
|
||||
OK mission section present after retry (relative path resolved)
|
||||
OK retry of missing run exits 4 (exit 4)
|
||||
OK skill install bundled ms-tools (exit 0)
|
||||
OK installed to skills-available
|
||||
OK double install refuses (exit 1)
|
||||
OK activate enables skill (exit 0)
|
||||
OK enabled dir populated
|
||||
OK uninstall while enabled refuses (exit 1)
|
||||
OK deactivate moves back to available (exit 0)
|
||||
OK uninstall removes from available (exit 0)
|
||||
OK seat with enabled skill launches
|
||||
OK skill path delivered to adapter
|
||||
OK shipped researcher contract resolves (ceiling + network)
|
||||
OK resolve-role refuses a non-role document (conductor policy) (exit 2)
|
||||
OK resolve-role refuses name/filename mismatch (exit 2)
|
||||
OK resolve-role refuses unknown network declaration (exit 2)
|
||||
OK resolve-role refuses duplicate role tool (exit 2)
|
||||
OK resolve-role refuses unsupported tool (exit 2)
|
||||
OK resolve-role refuses missing contract file (exit 4)
|
||||
OK version 1 role prints no contract line
|
||||
OK shipped version 2 roles resolve with their contracts (pm, cto, coder, reviewer)
|
||||
OK resolve-role accepts a minimal version 2 role (exit 0)
|
||||
OK resolve-role refuses an action outside the vocabulary (exit 2)
|
||||
OK resolve-role refuses a gated-only action in a role file (exit 2)
|
||||
OK resolve-role refuses a Vikunja verb no role may hold (exit 2)
|
||||
OK resolve-role refuses a version 2 role whose contract is missing (exit 2)
|
||||
OK resolve-role refuses a contract that is a symbolic link (exit 2)
|
||||
OK seat launches under role ceiling
|
||||
OK role ceiling narrows seat tools (read,write,bash -> read,bash)
|
||||
OK narrowing recorded loudly
|
||||
OK missing role contract refuses launch (exit 2)
|
||||
OK missing-contract refusal names the role
|
||||
OK empty ceiling intersection -> tool-free seat
|
||||
OK tool-free outcome recorded loudly
|
||||
OK overridden agents dir without seat definition refuses (exit 4)
|
||||
OK seat-resolution refusal names the seat
|
||||
OK policy: mission only -> mission tools
|
||||
OK policy: task only -> task tools
|
||||
OK policy: both -> intersection (task narrowed)
|
||||
OK policy: empty intersection -> tool-free
|
||||
OK invalid mission capabilities rejected (exit 2)
|
||||
mosaic-task: unsupported mission tool: "sudo" (supported: read, write, edit, bash, grep, find, ls)
|
||||
OK task run with user layer present (exit 0)
|
||||
OK user context dispatched into generated prompt
|
||||
OK workspace+tools task runs via mock (exit 0)
|
||||
OK workspace path + tools delivered to adapter
|
||||
OK persistent workspace created on host
|
||||
OK plain task still runs (no workspace/tools) (exit 0)
|
||||
OK workspace var present but empty when absent
|
||||
OK tools empty when absent
|
||||
OK unknown tool exits 2 (exit 2)
|
||||
OK workspace traversal exits 2 (exit 2)
|
||||
OK live hello task succeeds with exact marker
|
||||
OK result.json written in run dir
|
||||
OK result.json contents are correct
|
||||
OK wrong expectExact fails with exit 1 (reason: expect-mismatch)
|
||||
OK each run gets a distinct run dir (no clobber)
|
||||
OK list shows both runs
|
||||
OK fork base: teach succeeds (exit 0)
|
||||
OK fork child recalls ancestor context (exit 0)
|
||||
OK forked child recalled ancestor code word
|
||||
OK ancestor session untouched by fork
|
||||
OK child session dir has its own branch file
|
||||
OK onboard without name exits 4 (non-interactive) (exit 4)
|
||||
OK onboard --name renders profile (exit 0)
|
||||
OK profile written
|
||||
OK canon structure: required filled, optional placeholdered
|
||||
OK canon sections present
|
||||
OK user recall run succeeds
|
||||
OK recalled user name (response: Jason)
|
||||
OK no agent identity on headless run
|
||||
|
||||
selftest: 98 passed, 0 failed
|
||||
@@ -0,0 +1,52 @@
|
||||
[
|
||||
{
|
||||
"op": "remove",
|
||||
"path": "/launch/max"
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/launch/models",
|
||||
"value": {
|
||||
"opus": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-opus-5-5"
|
||||
},
|
||||
"sonnet": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-5-5"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/launch/limits",
|
||||
"value": {
|
||||
"models": {
|
||||
"anthropic": {
|
||||
"claude-opus-5-5": 4,
|
||||
"claude-sonnet-5-5": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/roles/pm/vars/model",
|
||||
"value": "opus"
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/roles/cto/vars/model",
|
||||
"value": "opus"
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/roles/coder/vars/model",
|
||||
"value": "sonnet"
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/roles/reviewer/vars/model",
|
||||
"value": "opus"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
docs/TOOLS.md: OK
|
||||
packages/bus/src/broker.mjs: OK
|
||||
packages/bus/src/runtime.mjs: OK
|
||||
packages/bus/tests/limits.test.mjs: OK
|
||||
packages/business/README.md: OK
|
||||
packages/business/examples/mosaic-stack.example.json: OK
|
||||
packages/business/src/business.mjs: OK
|
||||
packages/business/src/index.mjs: OK
|
||||
packages/business/src/launch-settings.mjs: OK
|
||||
packages/business/src/launch.mjs: OK
|
||||
packages/business/src/migrate-launch.mjs: OK
|
||||
packages/business/src/organization.mjs: OK
|
||||
packages/business/src/vocabulary.mjs: OK
|
||||
packages/business/tests/business.test.mjs: OK
|
||||
packages/business/tests/chief-of-staff.test.mjs: OK
|
||||
packages/business/tests/helpers.mjs: OK
|
||||
packages/business/tests/launch-settings.test.mjs: OK
|
||||
packages/business/tests/resolve.test.mjs: OK
|
||||
packages/cli/README.md: OK
|
||||
packages/cli/src/cli.mjs: OK
|
||||
packages/cli/src/config.mjs: OK
|
||||
packages/cli/src/launcher.mjs: OK
|
||||
packages/cli/src/limits.mjs: OK
|
||||
packages/cli/tests/launch-limits.test.mjs: OK
|
||||
packages/cli/tests/launcher.test.mjs: OK
|
||||
packages/cli/tests/limits.test.mjs: OK
|
||||
packages/harness/src/bundle.mjs: OK
|
||||
packages/harness/tests/pi-session.test.mjs: OK
|
||||
packages/harness/tests/runner.test.mjs: OK
|
||||
packages/seat/src/session.mjs: OK
|
||||
packages/seat/tests/session.test.mjs: OK
|
||||
packages/webui/src/bus.mjs: OK
|
||||
packages/webui/src/cli.mjs: OK
|
||||
packages/webui/src/public/bus.js: OK
|
||||
packages/webui/src/reads.mjs: OK
|
||||
packages/webui/src/serve.mjs: OK
|
||||
packages/webui/tests/reads-fixture.mjs: OK
|
||||
packages/webui/tests/reads.test.mjs: OK
|
||||
packages/webui/tests/settings-form.test.mjs: OK
|
||||
packages/webui/tests/settings-write.test.mjs: OK
|
||||
packages/webui/tests/shell.test.mjs: OK
|
||||
packages/webui/tests/views.test.mjs: OK
|
||||
scripts/mosaic: OK
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"models": {
|
||||
"opus": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-opus-5-5"
|
||||
},
|
||||
"sonnet": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-5-5"
|
||||
}
|
||||
},
|
||||
"families": {
|
||||
"opus": "opus",
|
||||
"sonnet": "sonnet"
|
||||
},
|
||||
"instances": {
|
||||
"pm": "opus",
|
||||
"cto": "opus",
|
||||
"coder": "sonnet",
|
||||
"reviewer": "opus"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
01-whole-document-validation KILLED 1
|
||||
02-atomic-publication KILLED 1
|
||||
03-previous-version KILLED 1
|
||||
04-authenticated-actor KILLED 1
|
||||
05-old-new-receipt KILLED 1
|
||||
06-stale-revision KILLED 1
|
||||
07-uncertain-recovery KILLED 1
|
||||
08-total-limit KILLED 1
|
||||
09-provider-limit KILLED 1
|
||||
10-model-limit KILLED 1
|
||||
11-at-limit KILLED 1
|
||||
12-unset-unlimited KILLED 1
|
||||
13-nonnegative-counts KILLED 1
|
||||
14-no-policy-ceiling KILLED 1
|
||||
15-exact-provider-count KILLED 1
|
||||
16-provider-routing KILLED 1
|
||||
17-reread-every-launch KILLED 1
|
||||
18-refusal-hit-logged KILLED 1
|
||||
19-migration-preserve-counts KILLED 1
|
||||
20-migration-ambiguity KILLED 1
|
||||
21-print-only-migration KILLED 1
|
||||
22-human-only-settings KILLED 1
|
||||
23-settings-origin KILLED 1
|
||||
24-settings-fetch-metadata KILLED 1
|
||||
25-settings-send-mode KILLED 1
|
||||
26-settings-strict-keys KILLED 1
|
||||
27-form-instances KILLED 1
|
||||
28-form-limit-payload KILLED 1
|
||||
29-migration-idempotent KILLED 1
|
||||
30-zero-stops-new KILLED 1
|
||||
31-instance-model-edit KILLED 1
|
||||
32-model-table-edit KILLED 1
|
||||
33-runtime-writer-wiring KILLED 1
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
"""One fault per acceptance check. Sequential process groups; whole-group timeout cleanup."""
|
||||
import json,os,pathlib,signal,subprocess,sys,time
|
||||
ROOT=pathlib.Path(sys.argv[1] if len(sys.argv)>1 else '/mnt/storage/src/mosaic-stack-rocko-122')
|
||||
OUT=pathlib.Path(__file__).resolve().parent/'mutants';OUT.mkdir(exist_ok=True)
|
||||
B='packages/business/tests/launch-settings.test.mjs';C='packages/cli/tests/limits.test.mjs';L='packages/cli/tests/launch-limits.test.mjs';H='packages/bus/tests/limits.test.mjs';W='packages/webui/tests/settings-write.test.mjs';F='packages/webui/tests/settings-form.test.mjs'
|
||||
cases=[]
|
||||
def add(id,path,old,new,test):cases.append(dict(id=id,path=path,old=old,new=new,test=test))
|
||||
p='packages/business/src/organization.mjs'
|
||||
add('01-whole-document-validation',p,'validateBusinessDocument(document,file,{rolesDir});\n const old','/* missing validation */\n const old',B)
|
||||
add('02-atomic-publication',p,'renameSync(candidate,file);','/* never publish candidate */',B)
|
||||
add('03-previous-version',p,'durable(previous,oldBytes);',"durable(previous,'{}');",B)
|
||||
add('04-authenticated-actor',p,'const event={transaction,actor,business:id',"const event={transaction,actor:'anonymous',business:id",B)
|
||||
add('05-old-new-receipt',p,'changes:changes(old,document)','changes:[]',B)
|
||||
add('06-stale-revision',p,'if(revision!==before)', 'if(false)',B)
|
||||
add('07-uncertain-recovery',p,"if(hash!==e.before&&hash!==e.after)","if(false)",B)
|
||||
p='packages/business/src/launch.mjs'
|
||||
add('08-total-limit',p,"['total',limits.total,usage.total]","['total',undefined,usage.total]",B)
|
||||
add('09-provider-limit',p,'Object.hasOwn(limits.providers??{},provider)?limits.providers[provider]:undefined','undefined',B)
|
||||
add('10-model-limit',p,'own(own(limits.models,provider),model)','undefined',B)
|
||||
add('11-at-limit',p,'running>=limit','running>limit',B)
|
||||
add('12-unset-unlimited',p,"['total',limits.total,usage.total]","['total',limits.total??0,usage.total]",B)
|
||||
add('13-nonnegative-counts',p,'!Number.isSafeInteger(v)||v<0','!Number.isSafeInteger(v)',B)
|
||||
add('14-no-policy-ceiling',p,'!Number.isSafeInteger(v)||v<0','!Number.isSafeInteger(v)||v<0||v>4',B)
|
||||
add('15-exact-provider-count',p,'s.provider!==' , 's.provider!==',B) # replaced below with an effective fault
|
||||
cases[-1].update(old='pc.set(s.provider,(pc.get(s.provider)??0)+1)',new="pc.set('anthropic',(pc.get('anthropic')??0)+1)")
|
||||
p='packages/harness/src/bundle.mjs'
|
||||
add('16-provider-routing',p,'provider:entry.provider',"provider:'anthropic'",B)
|
||||
p='packages/cli/src/launcher.mjs'
|
||||
add('17-reread-every-launch',p,'b=loadBusiness(host.business,{dir:configDir(env),rolesDir:rolesDir(env)});','/* cached policy */',L)
|
||||
add('18-refusal-hit-logged',p,'...(e.limit?{limit:e.limit}:{})','/* no hit details */',L)
|
||||
p='packages/business/src/migrate-launch.mjs'
|
||||
add('19-migration-preserve-counts',p,'limits.models[entry.provider][entry.model]=count','limits.models[entry.provider][entry.model]=0',C)
|
||||
add('20-migration-ambiguity',p,'if(used.has(tuple))','if(false)',B)
|
||||
p='packages/cli/src/limits.mjs'
|
||||
add('21-print-only-migration',p,'io.stdout.write(JSON.stringify(migrateLaunch(raw,mapping,file,{rolesDir}),null,2)',"io.stdout.write(JSON.stringify((await import('node:fs')).writeFileSync(file,JSON.stringify(raw))??migrateLaunch(raw,mapping,file,{rolesDir}),null,2)",C)
|
||||
p='packages/bus/src/broker.mjs'
|
||||
add('22-human-only-settings',p,"if(!s.human)fail('human-required');if(!this.#organization)","if(false)fail('human-required');if(!this.#organization)",H)
|
||||
p='packages/webui/src/serve.mjs'
|
||||
add('23-settings-origin',p,"if(one(req,'origin')!==`https://${preview.host}`)return refuse(403,'cross-origin request refused','settings need the Console origin');","/* origin omitted */",W)
|
||||
add('24-settings-fetch-metadata',p,"if(one(req,'sec-fetch-site')!=='same-origin')return refuse(403,'cross-site request refused','settings need same-origin Fetch Metadata');","/* fetch metadata omitted */",W)
|
||||
add('25-settings-send-mode',p,'if(!send||!settingsWrite||!named)', 'if(!settingsWrite||!named)',W)
|
||||
add('26-settings-strict-keys',p,"Object.keys(value).some(k=>!['revision','limits','models','instances'].includes(k))",'false',W)
|
||||
p='packages/webui/src/public/bus.js'
|
||||
add('27-form-instances',p,'Object.entries(v.instances||{})','Object.entries({})',F)
|
||||
add('28-form-limit-payload',p,"if(kind==='total')limits.total=n;","if(kind==='total')limits.total=1;",F)
|
||||
add('29-migration-idempotent','packages/business/src/migrate-launch.mjs','if(!out.launch?.max)','if(false)',C)
|
||||
add('30-zero-stops-new','packages/business/src/launch.mjs','limit!==undefined&&running>=limit','limit!==undefined&&limit>0&&running>=limit',B)
|
||||
add('31-instance-model-edit','packages/business/src/launch-settings.mjs',"if(Object.hasOwn(args,'instances'))",'if(false)',B)
|
||||
add('32-model-table-edit','packages/business/src/launch-settings.mjs',"if(Object.hasOwn(args,'models'))next.launch.models=args.models;",'/* ignored model table update */',B)
|
||||
add('33-runtime-writer-wiring','packages/bus/src/runtime.mjs',"organization:settings?(id,verb,args,actor)=>verb==='limits'?settings.read(id):settings.set(id,args,actor):null,",'organization:null,',H)
|
||||
# Apply all matching copies for repeated logging sites. Every fault must change source.
|
||||
results=[]
|
||||
for c in cases:
|
||||
file=ROOT/c['path'];before=file.read_text();matches=before.count(c['old'])
|
||||
if not matches:raise RuntimeError('missing mutation site '+c['id'])
|
||||
file.write_text(before.replace(c['old'],c['new']))
|
||||
try:
|
||||
env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'}
|
||||
with (OUT/(c['id']+'.log')).open('w') as log:
|
||||
p=subprocess.Popen(['node','--test',c['test']],cwd=ROOT,env=env,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try:rc=p.wait(timeout=120)
|
||||
except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait();rc='timeout'
|
||||
verdict='KILLED' if isinstance(rc,int) and rc!=0 else 'SURVIVED' if rc==0 else 'TIMEOUT'
|
||||
row={k:c[k] for k in ['id','path','test']};row.update(result=verdict,exit=rc,sites=matches);results.append(row);print(c['id'],verdict,rc,flush=True)
|
||||
finally:file.write_text(before)
|
||||
(OUT/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
sys.exit(0 if all(r['result']=='KILLED' for r in results) else 1)
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.290703ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.635748ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (14.181009ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (12.918603ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.045938ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.851781ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.824986ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.428471ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 124.073952
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (14.181009ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:29:167)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.680904ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.699656ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.985758ms)
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.041343ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.451991ms)
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (9.561879ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.911811ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (7.653004ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 5
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 116.612936
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.985758ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
undefined !== 99
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:27:9)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: 99,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:31:1
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.041343ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
undefined !== 7
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:35:244)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: 7,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:43:1
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (9.561879ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
undefined !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:45:118)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.426161ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.695339ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.823989ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.991203ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.974418ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.183376ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.973498ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.449268ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 121.582613
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.823989ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ '{}'
|
||||
- '{\n' +
|
||||
- ' "businessVersion": 1,\n' +
|
||||
- ' "id": "acme",\n' +
|
||||
- ' "human": "jason",\n' +
|
||||
- ' "arbiters": {\n' +
|
||||
- ' "delivery": "pm",\n' +
|
||||
- ' "technical": "cto"\n' +
|
||||
- ' },\n' +
|
||||
- ' "projects": {\n' +
|
||||
- ' "stack": {\n' +
|
||||
- ' "root": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/project"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "tracker.baseUrl": "http://127.0.0.1:3456",\n' +
|
||||
- ' "gitea.baseUrl": "https://git.example",\n' +
|
||||
- ' "tracker.pollSeconds": 60\n' +
|
||||
- ' },\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "sync": {\n' +
|
||||
- ' "bot": "bot-acme-sync",\n' +
|
||||
- ' "botId": 9,\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/sync-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "labels": {}\n' +
|
||||
- ' },\n' +
|
||||
- ' "roles": {\n' +
|
||||
- ' "pm": {\n' +
|
||||
- ' "definition": "pm",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-pm",\n' +
|
||||
- ' "botId": 3\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/pm-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/pm-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "holder": "sage",\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "pi",\n' +
|
||||
- ' "model": "opus"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "cto": {\n' +
|
||||
- ' "definition": "cto",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-cto",\n' +
|
||||
- ' "botId": 4\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/cto-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/cto-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "holder": "darkwing",\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "claude-code",\n' +
|
||||
- ' "model": "sonnet"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "coder": {\n' +
|
||||
- ' "definition": "coder",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-coder",\n' +
|
||||
- ' "botId": 5\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/coder-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/coder-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "pi",\n' +
|
||||
- ' "limits.network": "none",\n' +
|
||||
- ' "model": "sonnet"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "reviewer": {\n' +
|
||||
- ' "definition": "reviewer",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-reviewer",\n' +
|
||||
- ' "botId": 6\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/reviewer-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/reviewer-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "model": "sonnet"\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "launch": {\n' +
|
||||
- ' "by": "pm",\n' +
|
||||
- ' "instances": [\n' +
|
||||
- ' "coder",\n' +
|
||||
- ' "reviewer"\n' +
|
||||
- ' ],\n' +
|
||||
- ' "models": {\n' +
|
||||
- ' "opus": {\n' +
|
||||
- ' "provider": "anthropic",\n' +
|
||||
- ' "model": "claude-opus-5-5"\n' +
|
||||
- ' },\n' +
|
||||
- ' "sonnet": {\n' +
|
||||
- ' "provider": "anthropic",\n' +
|
||||
- ' "model": "claude-sonnet-5-5"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "limits": {\n' +
|
||||
- ' "models": {\n' +
|
||||
- ' "anthropic": {\n' +
|
||||
- ' "claude-opus-5-5": 4,\n' +
|
||||
- ' "claude-sonnet-5-5": 4\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- '}\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:27:131)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '{}',
|
||||
expected: '{\n "businessVersion": 1,\n "id": "acme",\n "human": "jason",\n "arbiters": {\n "delivery": "pm",\n "technical": "cto"\n },\n "projects": {\n "stack": {\n "root": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/project"\n }\n },\n "vars": {\n "tracker.baseUrl": "http://127.0.0.1:3456",\n "gitea.baseUrl": "https://git.example",\n "tracker.pollSeconds": 60\n },\n "tracker": {\n "sync": {\n "bot": "bot-acme-sync",\n "botId": 9,\n "credentials": {\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/sync-vikunja.token",\n "expires": "2099-01-01"\n }\n }\n },\n "labels": {}\n },\n "roles": {\n "pm": {\n "definition": "pm",\n "tracker": {\n "bot": "bot-acme-pm",\n "botId": 3\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/pm-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/pm-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "holder": "sage",\n "vars": {\n "harness": "pi",\n "model": "opus"\n }\n },\n "cto": {\n "definition": "cto",\n "tracker": {\n "bot": "bot-acme-cto",\n "botId": 4\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/cto-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/cto-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "holder": "darkwing",\n "vars": {\n "harness": "claude-code",\n "model": "sonnet"\n }\n },\n "coder": {\n "definition": "coder",\n "tracker": {\n "bot": "bot-acme-coder",\n "botId": 5\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/coder-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/coder-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "vars": {\n "harness": "pi",\n "limits.network": "none",\n "model": "sonnet"\n }\n },\n "reviewer": {\n "definition": "reviewer",\n "tracker": {\n "bot": "bot-acme-reviewer",\n "botId": 6\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/reviewer-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-business-QVai8O/secrets/reviewer-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "vars": {\n "model": "sonnet"\n }\n }\n },\n "launch": {\n "by": "pm",\n "instances": [\n "coder",\n "reviewer"\n ],\n "models": {\n "opus": {\n "provider": "anthropic",\n "model": "claude-opus-5-5"\n },\n "sonnet": {\n "provider": "anthropic",\n "model": "claude-sonnet-5-5"\n }\n },\n "limits": {\n "models": {\n "anthropic": {\n "claude-opus-5-5": 4,\n "claude-sonnet-5-5": 4\n }\n }\n }\n }\n}\n',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.384409ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.649649ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.602478ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.18508ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.055677ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.582783ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.997196ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.833552ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 120.665278
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (9.602478ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ 'anonymous'
|
||||
- 'jason'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:28:118)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'anonymous',
|
||||
expected: 'jason',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.341907ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.74047ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (11.384864ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.009624ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.839767ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.328724ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.755914ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.498586ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 125.442959
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (11.384864ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(e.changes.some(c=>c.path==='launch.limits.total'&&c.new===99))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:28:182)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.355789ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.693529ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (13.065261ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.036724ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.09433ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.810001ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.777943ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (9.190811ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 124.281661
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (13.065261ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:29:49)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /revision/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.162371ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.67039ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.381795ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.864892ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.098891ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.985304ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.114869ms)
|
||||
✖ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.304235ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 131.254644
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:53:1
|
||||
✖ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.304235ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:55:331)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /match prepared/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.884664ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.432981ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (16.902993ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (16.422889ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.160294ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (17.281125ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.176617ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (9.037775ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 149.05054
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.432981ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(limitHit(sessions,'acme',limits,{provider:'anthropic',model:'opus-exact'}))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:106)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (8.992545ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.448411ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.708566ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (12.643076ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.98341ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.613014ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.868454ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (7.754013ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 125.468251
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.448411ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(limitHit(sessions,'acme',limits,{provider:'anthropic',model:'opus-exact'}))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:106)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.868454ms)
|
||||
TypeError: Cannot read properties of null (reading 'scope')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:50:357)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.311025ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.487825ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (17.216306ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.249108ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.966547ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.967335ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.766365ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.121591ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 128.59403
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.487825ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(limitHit(sessions,'acme',limits,{provider:'anthropic',model:'opus-exact'}))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:106)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.766365ms)
|
||||
TypeError: Cannot read properties of null (reading 'scope')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:50:468)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.36572ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.317877ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.706826ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (12.965224ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.88238ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.714514ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.82258ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.670838ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 131.697313
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.317877ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(limitHit(sessions,'acme',limits,{provider:'anthropic',model:'opus-exact'}))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:106)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.82258ms)
|
||||
TypeError: Cannot read properties of null (reading 'scope')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:50:357)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,64 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.221271ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (1.277662ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.347754ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.219557ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.035014ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (19.243366ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.077478ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.265283ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 125.845443
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (1.277662ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ {
|
||||
+ limit: 0,
|
||||
+ running: 1,
|
||||
+ scope: 'total'
|
||||
+ }
|
||||
- null
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:192)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { scope: 'total', limit: 0, running: 1 },
|
||||
expected: null,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.077478ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ {
|
||||
+ limit: 0,
|
||||
+ running: 1,
|
||||
+ scope: 'total'
|
||||
+ }
|
||||
- null
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:50:86)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { scope: 'total', limit: 0, running: 1 },
|
||||
expected: null,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (7.384622ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.699265ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.515455ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.861961ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.901932ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.747433ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.739389ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.511594ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 122.571785
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:10:1
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (7.384622ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:13:104)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.515455ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:29:167)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (6.740972ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.712646ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (5.325904ms)
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (4.817162ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.267214ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (16.930805ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.818123ms)
|
||||
✖ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (4.314223ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 4
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 100.049078
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:10:1
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (6.740972ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-business-7xoQNX/businesses/acme.json launch.limits.total must be a whole number of 0 or more
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at count (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs:5:60)
|
||||
at checkLimits (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs:12:44)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:131:16)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at check (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:11:29)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:12:257)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:24:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (5.325904ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-business-wST5Ql/businesses/acme.json launch.limits.total must be a whole number of 0 or more
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at count (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs:5:60)
|
||||
at checkLimits (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs:12:44)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:131:16)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs:30:191
|
||||
at withLock (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs:21:14)
|
||||
at Object.write (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs:29:82)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:26:77)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:31:1
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (4.817162ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:34:9)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /recovery/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:53:1
|
||||
✖ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (4.314223ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:55:331)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /match prepared/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.591005ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.671667ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (14.861051ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (12.757394ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.083978ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.584768ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.877899ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.135097ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 122.400084
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.877899ms)
|
||||
TypeError: Cannot read properties of null (reading 'scope')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:50:357)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,37 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.203608ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.650834ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (14.954179ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.327727ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.318633ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.906537ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.419251ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.06199ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 124.166306
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.419251ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ 'anthropic'
|
||||
- 'proxy-next'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:49:153)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'anthropic',
|
||||
expected: 'proxy-next',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
✖ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (10.935974ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 72.387691
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/launch-limits.test.mjs:10:1
|
||||
✖ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (10.935974ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
+ error: 'fixture-policy',
|
||||
- error: 'capacity-full',
|
||||
ok: false
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/tests/launch-limits.test.mjs:16:157)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { ok: false, error: 'fixture-policy' },
|
||||
expected: { ok: false, error: 'capacity-full' },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
✖ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (10.943146ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 72.374966
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/launch-limits.test.mjs:10:1
|
||||
✖ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (10.943146ms)
|
||||
TypeError: Cannot read properties of undefined (reading 'scope')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/tests/launch-limits.test.mjs:16:380)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3)
|
||||
@@ -0,0 +1,39 @@
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (7.139922ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.459022ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 98.476338
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/limits.test.mjs:11:1
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (7.139922ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
models: {
|
||||
anthropic: {
|
||||
+ 'claude-opus-5-5': 0,
|
||||
+ 'claude-sonnet-5-5': 0
|
||||
- 'claude-opus-5-5': 4,
|
||||
- 'claude-sonnet-5-5': 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/tests/limits.test.mjs:17:60)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { models: { anthropic: [Object] } },
|
||||
expected: { models: { anthropic: [Object] } },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.096879ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.668043ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (15.959188ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (14.288691ms)
|
||||
✖ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (5.975697ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (18.6972ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.126869ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (9.520592ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 134.249462
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:38:1
|
||||
✖ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (5.975697ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:41:729)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /ambiguous/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (9.520892ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.606131ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 110.51898
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/limits.test.mjs:11:1
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (9.520892ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ '{"businessVersion":1,"id":"acme","human":"jason","arbiters":{"delivery":"pm","technical":"cto"},"projects":{"stack":{"root":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/project"}},"vars":{"tracker.baseUrl":"http://127.0.0.1:3456","gitea.baseUrl":"https://git.example","tracker.pollSeconds":60},"tracker":{"sync":{"bot":"bot-acme-sync","botId":9,"credentials":{"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/sync-vikunja.token","expires":"2099-01-01"}}},"labels":{}},"roles":{"pm":{"definition":"pm","tracker":{"bot":"bot-acme-pm","botId":3},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-vikunja.token","expires":"2099-01-01"}},"holder":"sage","vars":{"harness":"pi","model":"claude-opus-5-5"}},"cto":{"definition":"cto","tracker":{"bot":"bot-acme-cto","botId":4},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-vikunja.token","expires":"2099-01-01"}},"holder":"darkwing","vars":{"harness":"claude-code","model":"claude-opus-5-5"}},"coder":{"definition":"coder","tracker":{"bot":"bot-acme-coder","botId":5},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-vikunja.token","expires":"2099-01-01"}},"vars":{"harness":"pi","limits.network":"none","model":"claude-sonnet-5-5"}},"reviewer":{"definition":"reviewer","tracker":{"bot":"bot-acme-reviewer","botId":6},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-vikunja.token","expires":"2099-01-01"}},"vars":{"model":"claude-opus-5-5"}}},"launch":{"by":"pm","instances":["coder","reviewer"],"max":{"opus":4,"sonnet":4}}}'
|
||||
- '{\n' +
|
||||
- ' "businessVersion": 1,\n' +
|
||||
- ' "id": "acme",\n' +
|
||||
- ' "human": "jason",\n' +
|
||||
- ' "arbiters": {\n' +
|
||||
- ' "delivery": "pm",\n' +
|
||||
- ' "technical": "cto"\n' +
|
||||
- ' },\n' +
|
||||
- ' "projects": {\n' +
|
||||
- ' "stack": {\n' +
|
||||
- ' "root": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/project"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "tracker.baseUrl": "http://127.0.0.1:3456",\n' +
|
||||
- ' "gitea.baseUrl": "https://git.example",\n' +
|
||||
- ' "tracker.pollSeconds": 60\n' +
|
||||
- ' },\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "sync": {\n' +
|
||||
- ' "bot": "bot-acme-sync",\n' +
|
||||
- ' "botId": 9,\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/sync-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "labels": {}\n' +
|
||||
- ' },\n' +
|
||||
- ' "roles": {\n' +
|
||||
- ' "pm": {\n' +
|
||||
- ' "definition": "pm",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-pm",\n' +
|
||||
- ' "botId": 3\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "holder": "sage",\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "pi",\n' +
|
||||
- ' "model": "claude-opus-5-5"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "cto": {\n' +
|
||||
- ' "definition": "cto",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-cto",\n' +
|
||||
- ' "botId": 4\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "holder": "darkwing",\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "claude-code",\n' +
|
||||
- ' "model": "claude-opus-5-5"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "coder": {\n' +
|
||||
- ' "definition": "coder",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-coder",\n' +
|
||||
- ' "botId": 5\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "harness": "pi",\n' +
|
||||
- ' "limits.network": "none",\n' +
|
||||
- ' "model": "claude-sonnet-5-5"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "reviewer": {\n' +
|
||||
- ' "definition": "reviewer",\n' +
|
||||
- ' "tracker": {\n' +
|
||||
- ' "bot": "bot-acme-reviewer",\n' +
|
||||
- ' "botId": 6\n' +
|
||||
- ' },\n' +
|
||||
- ' "credentials": {\n' +
|
||||
- ' "gitea": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-gitea.token",\n' +
|
||||
- ' "rotateBy": "2099-01-01"\n' +
|
||||
- ' },\n' +
|
||||
- ' "vikunja": {\n' +
|
||||
- ' "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-vikunja.token",\n' +
|
||||
- ' "expires": "2099-01-01"\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "vars": {\n' +
|
||||
- ' "model": "claude-opus-5-5"\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- ' },\n' +
|
||||
- ' "launch": {\n' +
|
||||
- ' "by": "pm",\n' +
|
||||
- ' "instances": [\n' +
|
||||
- ' "coder",\n' +
|
||||
- ' "reviewer"\n' +
|
||||
- ' ],\n' +
|
||||
- ' "max": {\n' +
|
||||
- ' "opus": 4,\n' +
|
||||
- ' "sonnet": 4\n' +
|
||||
- ' }\n' +
|
||||
- ' }\n' +
|
||||
- '}\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/tests/limits.test.mjs:17:216)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '{"businessVersion":1,"id":"acme","human":"jason","arbiters":{"delivery":"pm","technical":"cto"},"projects":{"stack":{"root":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/project"}},"vars":{"tracker.baseUrl":"http://127.0.0.1:3456","gitea.baseUrl":"https://git.example","tracker.pollSeconds":60},"tracker":{"sync":{"bot":"bot-acme-sync","botId":9,"credentials":{"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/sync-vikunja.token","expires":"2099-01-01"}}},"labels":{}},"roles":{"pm":{"definition":"pm","tracker":{"bot":"bot-acme-pm","botId":3},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-vikunja.token","expires":"2099-01-01"}},"holder":"sage","vars":{"harness":"pi","model":"claude-opus-5-5"}},"cto":{"definition":"cto","tracker":{"bot":"bot-acme-cto","botId":4},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-vikunja.token","expires":"2099-01-01"}},"holder":"darkwing","vars":{"harness":"claude-code","model":"claude-opus-5-5"}},"coder":{"definition":"coder","tracker":{"bot":"bot-acme-coder","botId":5},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-vikunja.token","expires":"2099-01-01"}},"vars":{"harness":"pi","limits.network":"none","model":"claude-sonnet-5-5"}},"reviewer":{"definition":"reviewer","tracker":{"bot":"bot-acme-reviewer","botId":6},"credentials":{"gitea":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-gitea.token","rotateBy":"2099-01-01"},"vikunja":{"file":"/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-vikunja.token","expires":"2099-01-01"}},"vars":{"model":"claude-opus-5-5"}}},"launch":{"by":"pm","instances":["coder","reviewer"],"max":{"opus":4,"sonnet":4}}}',
|
||||
expected: '{\n "businessVersion": 1,\n "id": "acme",\n "human": "jason",\n "arbiters": {\n "delivery": "pm",\n "technical": "cto"\n },\n "projects": {\n "stack": {\n "root": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/project"\n }\n },\n "vars": {\n "tracker.baseUrl": "http://127.0.0.1:3456",\n "gitea.baseUrl": "https://git.example",\n "tracker.pollSeconds": 60\n },\n "tracker": {\n "sync": {\n "bot": "bot-acme-sync",\n "botId": 9,\n "credentials": {\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/sync-vikunja.token",\n "expires": "2099-01-01"\n }\n }\n },\n "labels": {}\n },\n "roles": {\n "pm": {\n "definition": "pm",\n "tracker": {\n "bot": "bot-acme-pm",\n "botId": 3\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/pm-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "holder": "sage",\n "vars": {\n "harness": "pi",\n "model": "claude-opus-5-5"\n }\n },\n "cto": {\n "definition": "cto",\n "tracker": {\n "bot": "bot-acme-cto",\n "botId": 4\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/cto-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "holder": "darkwing",\n "vars": {\n "harness": "claude-code",\n "model": "claude-opus-5-5"\n }\n },\n "coder": {\n "definition": "coder",\n "tracker": {\n "bot": "bot-acme-coder",\n "botId": 5\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/coder-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "vars": {\n "harness": "pi",\n "limits.network": "none",\n "model": "claude-sonnet-5-5"\n }\n },\n "reviewer": {\n "definition": "reviewer",\n "tracker": {\n "bot": "bot-acme-reviewer",\n "botId": 6\n },\n "credentials": {\n "gitea": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-gitea.token",\n "rotateBy": "2099-01-01"\n },\n "vikunja": {\n "file": "/mnt/storage/scratch/tmp/mosaic-cli-8UsXUg/secrets/reviewer-vikunja.token",\n "expires": "2099-01-01"\n }\n },\n "vars": {\n "model": "claude-opus-5-5"\n }\n }\n },\n "launch": {\n "by": "pm",\n "instances": [\n "coder",\n "reviewer"\n ],\n "max": {\n "opus": 4,\n "sonnet": 4\n }\n }\n}\n',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ limits binds actor from human proof and rejects role, reader, tester and forged actor (10.289673ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (30.832045ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 90.307525
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/limits.test.mjs:9:1
|
||||
✖ limits binds actor from human proof and rejects role, reader, tester and forged actor (10.289673ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/bus/tests/limits.test.mjs:13:89)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /human-required/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
2026-10-15T01:03:58.803Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (17.035029ms)
|
||||
2026-10-15T01:03:58.813Z settings user="jason" changed
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (7.685464ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (7.21557ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 126.801032
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:12:1
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (7.685464ms)
|
||||
AssertionError [ERR_ASSERTION]: origin
|
||||
|
||||
200 !== 403
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:14:361)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 200,
|
||||
expected: 403,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
2026-10-15T01:03:58.968Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (17.478842ms)
|
||||
2026-10-15T01:03:58.977Z settings user="jason" changed
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (6.461883ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (6.073723ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 121.943876
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:12:1
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (6.461883ms)
|
||||
AssertionError [ERR_ASSERTION]: sec-fetch-site
|
||||
|
||||
200 !== 403
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:14:361)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 200,
|
||||
expected: 403,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
2026-10-15T01:03:59.126Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (15.007364ms)
|
||||
2026-10-15T01:03:59.131Z settings user="jason" changed
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (3.015053ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (6.258677ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 113.43808
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:12:1
|
||||
✖ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (3.015053ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
200 !== 403
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:13:40)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 200,
|
||||
expected: 403,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
2026-10-15T01:03:59.297Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (16.974911ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (7.155105ms)
|
||||
2026-10-15T01:03:59.309Z settings user="jason" changed
|
||||
✖ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (2.556465ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 120.011625
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:16:1
|
||||
✖ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (2.556465ms)
|
||||
AssertionError [ERR_ASSERTION]: [object Object]
|
||||
|
||||
200 !== 400
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:17:124)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 200,
|
||||
expected: 400,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
✖ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (485.108511ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 580.318499
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-form.test.mjs:8:1
|
||||
✖ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (485.108511ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 4
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-form.test.mjs:15:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 4,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
✖ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (675.168813ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 781.59553
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-form.test.mjs:8:1
|
||||
✖ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (675.168813ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
1 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-form.test.mjs:19:279)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (8.135325ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.228645ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 102.242229
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/limits.test.mjs:11:1
|
||||
✖ migration needs no bus/config, prints whole converted document, is idempotent and never writes (8.135325ms)
|
||||
Error [CliError]: old launch.max must be a JSON object
|
||||
at limitsCommand (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/src/limits.mjs:20:51)
|
||||
at main (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/src/cli.mjs:384:33)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/cli/tests/limits.test.mjs:19:175)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
exitCode: 2
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.278537ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.467213ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (17.028977ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.265697ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.916609ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.596687ms)
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.883872ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.325958ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 127.56547
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (3.467213ms)
|
||||
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||
|
||||
assert.ok(limitHit(sessions,'acme',JSON.parse(JSON.stringify(limits).replaceAll(':1',':0')),{provider:'anthropic',model:'opus-exact'}))
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:19:336)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:47:1
|
||||
✖ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.883872ms)
|
||||
TypeError: Cannot read properties of null (reading 'running')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:51:104)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,35 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.145634ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.638626ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (17.96131ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.305164ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.095582ms)
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (9.995205ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.786146ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.182564ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 123.244628
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:43:1
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (9.995205ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
'sonnet' !== 'opus'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:45:154)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'sonnet',
|
||||
expected: 'opus',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (9.394723ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.710015ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (16.148881ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (13.225129ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (3.199033ms)
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.869312ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.829359ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (8.674257ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 125.721441
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:43:1
|
||||
✖ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (15.869312ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ 'anthropic'
|
||||
- 'proxy'
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:45:357)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'anthropic',
|
||||
expected: 'proxy',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (15.12507ms)
|
||||
✖ runtime wires verified human settings to the actual shared file writer and actor receipt (20.360184ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 87.995927
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/limits.test.mjs:17:1
|
||||
✖ runtime wires verified human settings to the actual shared file writer and actor receipt (20.360184ms)
|
||||
Error: not-configured
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/bus/src/broker.mjs:76:9)
|
||||
at Broker.request (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/bus/src/broker.mjs:672:67)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/bus/tests/limits.test.mjs:22:24)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
code: 'not-configured'
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
[
|
||||
{
|
||||
"id": "01-whole-document-validation",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "02-atomic-publication",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "03-previous-version",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "04-authenticated-actor",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "05-old-new-receipt",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "06-stale-revision",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "07-uncertain-recovery",
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "08-total-limit",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "09-provider-limit",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "10-model-limit",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "11-at-limit",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "12-unset-unlimited",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "13-nonnegative-counts",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "14-no-policy-ceiling",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "15-exact-provider-count",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "16-provider-routing",
|
||||
"path": "packages/harness/src/bundle.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "17-reread-every-launch",
|
||||
"path": "packages/cli/src/launcher.mjs",
|
||||
"test": "packages/cli/tests/launch-limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "18-refusal-hit-logged",
|
||||
"path": "packages/cli/src/launcher.mjs",
|
||||
"test": "packages/cli/tests/launch-limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 3
|
||||
},
|
||||
{
|
||||
"id": "19-migration-preserve-counts",
|
||||
"path": "packages/business/src/migrate-launch.mjs",
|
||||
"test": "packages/cli/tests/limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "20-migration-ambiguity",
|
||||
"path": "packages/business/src/migrate-launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "21-print-only-migration",
|
||||
"path": "packages/cli/src/limits.mjs",
|
||||
"test": "packages/cli/tests/limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "22-human-only-settings",
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"test": "packages/bus/tests/limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "23-settings-origin",
|
||||
"path": "packages/webui/src/serve.mjs",
|
||||
"test": "packages/webui/tests/settings-write.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "24-settings-fetch-metadata",
|
||||
"path": "packages/webui/src/serve.mjs",
|
||||
"test": "packages/webui/tests/settings-write.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "25-settings-send-mode",
|
||||
"path": "packages/webui/src/serve.mjs",
|
||||
"test": "packages/webui/tests/settings-write.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "26-settings-strict-keys",
|
||||
"path": "packages/webui/src/serve.mjs",
|
||||
"test": "packages/webui/tests/settings-write.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "27-form-instances",
|
||||
"path": "packages/webui/src/public/bus.js",
|
||||
"test": "packages/webui/tests/settings-form.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "28-form-limit-payload",
|
||||
"path": "packages/webui/src/public/bus.js",
|
||||
"test": "packages/webui/tests/settings-form.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "29-migration-idempotent",
|
||||
"path": "packages/business/src/migrate-launch.mjs",
|
||||
"test": "packages/cli/tests/limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "30-zero-stops-new",
|
||||
"path": "packages/business/src/launch.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "31-instance-model-edit",
|
||||
"path": "packages/business/src/launch-settings.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "32-model-table-edit",
|
||||
"path": "packages/business/src/launch-settings.mjs",
|
||||
"test": "packages/business/tests/launch-settings.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "33-runtime-writer-wiring",
|
||||
"path": "packages/bus/src/runtime.mjs",
|
||||
"test": "packages/bus/tests/limits.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"network": "mosaic-stack-rocko-122_default",
|
||||
"present": true,
|
||||
"removeExit": 0
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
✔ config directory and file path follow MOSAIC_CONFIG (1.096295ms)
|
||||
✔ the fixture business validates and comes back frozen (3.476817ms)
|
||||
✔ two instances may share a definition (1.106543ms)
|
||||
✔ top-level refusals (3.164339ms)
|
||||
✔ arbiters and projects (4.729453ms)
|
||||
✔ role instances (2.15204ms)
|
||||
✔ Vikunja bots (5.100335ms)
|
||||
✔ a role without Vikunja takes no tracker block (1.899838ms)
|
||||
✔ credential references match the definition's services (2.139965ms)
|
||||
✔ launch (6.298037ms)
|
||||
✔ loadBusiness: file checks (1.513672ms)
|
||||
✔ loadBusiness: not a regular file (39.322942ms)
|
||||
✔ loading writes nothing (1.211783ms)
|
||||
✔ names that are Object.prototype properties don't count as declared (2.819482ms)
|
||||
✖ the shipped example refuses as written and validates once filled in (0.670781ms)
|
||||
ℹ tests 15
|
||||
ℹ suites 0
|
||||
ℹ pass 14
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 131.337894
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/business.test.mjs:206:1
|
||||
✖ the shipped example refuses as written and validates once filled in (0.670781ms)
|
||||
Error [BusinessError]: /mnt/storage/scratch/tmp/mosaic-business-AmTlus/businesses/mosaic-stack.json launch.max needs migration: mosaic limits migrate --file FILE --models FILE
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:117:36)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:181:57)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/business.test.mjs:216:20)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
exitCode: 2
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (14.859099ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.740574ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (14.238045ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (18.865075ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 132.870063
|
||||
@@ -0,0 +1,81 @@
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (5.393935ms)
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.584145ms)
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (0.386899ms)
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (0.327761ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 4
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 96.06669
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:10:1
|
||||
✖ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (5.393935ms)
|
||||
Error [BusinessError]: unsupported /mnt/storage/scratch/tmp/mosaic-business-UQTbUT/businesses/acme.json launch key: "models"
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/errors.mjs:12:9)
|
||||
at rejectUnknownKeys (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/util.mjs:17:33)
|
||||
at checkLaunch (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:117:3)
|
||||
at validateBusinessDocument (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/business.mjs:186:57)
|
||||
at check (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:11:29)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs:12:257)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:17:1
|
||||
✖ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.584145ms)
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs' imported from /mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at node:internal/modules/esm/loader:639:32
|
||||
at TracingChannel.tracePromise (node:diagnostics_channel:547:22) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/launch.mjs'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:23:1
|
||||
✖ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (0.386899ms)
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs' imported from /mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at node:internal/modules/esm/loader:639:32
|
||||
at TracingChannel.tracePromise (node:diagnostics_channel:547:22) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs'
|
||||
}
|
||||
|
||||
test at packages/business/tests/launch-settings.test.mjs:30:1
|
||||
✖ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (0.327761ms)
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs' imported from /mnt/storage/src/mosaic-stack-rocko-122/packages/business/tests/launch-settings.test.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at node:internal/modules/esm/loader:639:32
|
||||
at TracingChannel.tracePromise (node:diagnostics_channel:547:22) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///mnt/storage/src/mosaic-stack-rocko-122/packages/business/src/organization.mjs'
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
✖ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (15.228773ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (7.031981ms)
|
||||
✖ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (2.026028ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 114.550473
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:11:1
|
||||
✖ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (15.228773ms)
|
||||
AssertionError [ERR_ASSERTION]: {"error":"read-only","message":"the Console preview is read-only"}
|
||||
|
||||
403 !== 200
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:11:153)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 403,
|
||||
expected: 200,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/webui/tests/settings-write.test.mjs:16:1
|
||||
✖ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (2.026028ms)
|
||||
AssertionError [ERR_ASSERTION]: [object Object]
|
||||
|
||||
403 !== 400
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-122/packages/webui/tests/settings-write.test.mjs:17:124)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 403,
|
||||
expected: 400,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
c7a236c2734261e332f51e0850c179f401d9a156d91c20279ad967af85025f60 agents/rocko/work/queue-122/r1/BUILD.md
|
||||
2603c2e0a6a56c305a3418032b5b0298d203f9f13da4823e71a6bc9c5f5fd002 agents/rocko/work/queue-122/r1/MIGRATION.md
|
||||
1c7bd1ed91530d042579db8b34b9e37c82f5f40a4db0efe74fe9f043a9e49f94 agents/rocko/work/queue-122/r1/MUTANTS.md
|
||||
3287b9dba2ac897922a412741cd307f8b78ceb5376d9a2da3fd380cecf8db28b agents/rocko/work/queue-122/r1/base-drift.json
|
||||
46bad0bea556403fab5df8949314a931fae804c8b3d095047fd3d9a5f58ffc66 agents/rocko/work/queue-122/r1/base.txt
|
||||
26edcd30e09e60d0ce44293577ab6da8a90479148168e002b8131cc3472fb276 agents/rocko/work/queue-122/r1/build.patch
|
||||
667441df2411db4c085ec6981d8c9c5f55578debc02a389a2f4df9283df775ae agents/rocko/work/queue-122/r1/candidate-manifest.sha256
|
||||
5e349186a0356f0892e8e349b2c310d796419d07778352d287497bcb3a522f8e agents/rocko/work/queue-122/r1/gate/pkg-bus.log
|
||||
e566227494fe9ea1645424dd75067450f4435f3d7cfcc219d209e8a67f76cecd agents/rocko/work/queue-122/r1/gate/pkg-business.log
|
||||
735c675ee50f3ce293bee42dfd136b4cb062b7e4e4c980417b672b453472de09 agents/rocko/work/queue-122/r1/gate/pkg-cli.log
|
||||
0dbc6d3fe9e5220c47312f58f5ffd07fb84bd437c273e72ca36b205c626c83cb agents/rocko/work/queue-122/r1/gate/pkg-control-board.log
|
||||
b48553197fff19ecc891d92bb585b31e39f0c4621659d3e5547b4bb6b80c874a agents/rocko/work/queue-122/r1/gate/pkg-conversation.log
|
||||
10f8515d3ac53576306b960b04c1724b81c60aa94dae2c3364503312b4f277d5 agents/rocko/work/queue-122/r1/gate/pkg-harness-before-fixture-update.log
|
||||
9483ccf7cedd55575800de326d375144e037320f1059b23e8947262a69e4a926 agents/rocko/work/queue-122/r1/gate/pkg-harness.log
|
||||
7d2602fe6c400456afbbcf4ec742ac5d0886c807040e1a89588f2ed0211f12e0 agents/rocko/work/queue-122/r1/gate/pkg-ledger.log
|
||||
ac7aec341cd452d8a867031c4db59fd77937bb4ffe6ed26f60f2f873faaf3432 agents/rocko/work/queue-122/r1/gate/pkg-seat.log
|
||||
d08a035739d5d2b5811c9547d5ef724054aaab1a8aa8515e8310328b09c59dba agents/rocko/work/queue-122/r1/gate/pkg-tasks.log
|
||||
702a1bb22c2d86ff604b4fa72be2cb3a7d81a915d26b89c02ded734bc7f1af02 agents/rocko/work/queue-122/r1/gate/pkg-webui-before-boundary-update.log
|
||||
4495f5400a503737aa429f539781f9c32358062a9e346a0726618928ee1eeed8 agents/rocko/work/queue-122/r1/gate/pkg-webui.log
|
||||
38d8ff697b2a7dbe883fe2f6e4d60ab1508ad10692e873cf6b7060a52b1da2a8 agents/rocko/work/queue-122/r1/gate/results.json
|
||||
87d2e24ce0be7586e31ea1f2c9ce5618b3127515b3c3cd3893f2a0ed899d5822 agents/rocko/work/queue-122/r1/gate/script-discord.log
|
||||
82f49634c4d027fb10d8810f8cdeaac678e44cca7f57c827ca3534eeb82ee0c7 agents/rocko/work/queue-122/r1/gate/script-queue.log
|
||||
ccea37f4ffde1f160dcd1a1864988083a645d974e892065c956b338d0f8c853a agents/rocko/work/queue-122/r1/gate/script-task.log
|
||||
e43c5310975f427894818343ef3f5a4f4eed5d4408a45150920f01bf8798dfa8 agents/rocko/work/queue-122/r1/gate-followup.log
|
||||
4c8b5d1f6d7efeb7056e3cc181060d67969f2450828e51a301d88c156739ac0a agents/rocko/work/queue-122/r1/gate-run-final.log
|
||||
1847ca64119a13f1b0483e0f8e1043ef808ec3faf92e9c311bc0951e453fd8a3 agents/rocko/work/queue-122/r1/gate-run.log
|
||||
04c7ea2380342f9c348285fb518dba420a19a1f611a36ff621f12187add2d774 agents/rocko/work/queue-122/r1/gate.py
|
||||
31ee5b38cc165f33957b08b15fcccfdcf685f66a6007b97a8e6dae0742f000e6 agents/rocko/work/queue-122/r1/jason-migration.patch.json
|
||||
3ed49e2ac8439020b27c2c7495ea0c60c19c4a7424701cbe56b5ca77586a0160 agents/rocko/work/queue-122/r1/manifest-check.txt
|
||||
4f82fd79d4d10d973a1aaed8fb4a3fd58eaa67f9a364c86c60029eaea11a1d23 agents/rocko/work/queue-122/r1/migration-map.json
|
||||
915c248891939bd4185331b3197358c2b0dfc38b8915497a7ac95ae04776f252 agents/rocko/work/queue-122/r1/mutants/01-whole-document-validation.log
|
||||
5ed4877a6f503bea39f2669b271b2214e1a0ae0cd4fd9d5df741646aa519e202 agents/rocko/work/queue-122/r1/mutants/02-atomic-publication.log
|
||||
cf84453811491e78356f904653abd9341c86381c32a8432a5007b4a3f0997a71 agents/rocko/work/queue-122/r1/mutants/03-previous-version.log
|
||||
20afffba98ba69cfc5e8b6468883636d903de9c46d20e5ae7b34981dfc4c5157 agents/rocko/work/queue-122/r1/mutants/04-authenticated-actor.log
|
||||
ada69cff34e1991679bb12aebf4796bc13d4c350742c568c087fc1244e1ff612 agents/rocko/work/queue-122/r1/mutants/05-old-new-receipt.log
|
||||
0ad442c14f505d04423b109edefd5f6d81e5cc0c9f0e56365a17a6ff40b24b40 agents/rocko/work/queue-122/r1/mutants/06-stale-revision.log
|
||||
24c8d3c5bf846cdfeea8abe159ad04da39c102b1659d633647a7f1fad8183725 agents/rocko/work/queue-122/r1/mutants/07-uncertain-recovery.log
|
||||
38afcf200c63f6958ce637ea8675d58e86ca8089b16def96465020b94ddb54dc agents/rocko/work/queue-122/r1/mutants/08-total-limit.log
|
||||
776ddc795d903c915d28b05a69c0f317fc80ce0f10cbe1a97f63936bea8ba314 agents/rocko/work/queue-122/r1/mutants/09-provider-limit.log
|
||||
5302cd97a145d9fb0cbe99a64d2bea236c7c7578bd56f0cd74e664761cbb3950 agents/rocko/work/queue-122/r1/mutants/10-model-limit.log
|
||||
e91f29b5a255503dda9480c6c00cf8139e12d0e93903f06bd7e6aeab14614895 agents/rocko/work/queue-122/r1/mutants/11-at-limit.log
|
||||
f213a1541bf1694ea3070906b8cb53dc1b90d3ff2aa08fb88022a44bfa749daa agents/rocko/work/queue-122/r1/mutants/12-unset-unlimited.log
|
||||
a4abb65b43827ae987a4908b72f0a796b57d0edd1f5cdefd112f2759b9e45065 agents/rocko/work/queue-122/r1/mutants/13-nonnegative-counts.log
|
||||
5c145126061ae32b0e15106b5cfd83c5d10c356498a72235a5aca22c92b34a24 agents/rocko/work/queue-122/r1/mutants/14-no-policy-ceiling.log
|
||||
ea331eef2d8add73199d6e7b727134fed51fbb10b2e0955b51d71f8701173230 agents/rocko/work/queue-122/r1/mutants/15-exact-provider-count.log
|
||||
46425b451f542bd02ceeb4e77b189892957ad73ef582ac62684083f7ef2439b1 agents/rocko/work/queue-122/r1/mutants/16-provider-routing.log
|
||||
48f6b305ef1bb8621e699e037ec0d34485698a20ce1a1c4dce70324f9bf4a653 agents/rocko/work/queue-122/r1/mutants/17-reread-every-launch.log
|
||||
1aba11ec1610a01f36a346a9b16af2df1f4b99fc3ecdffc7e159f2e1ba806302 agents/rocko/work/queue-122/r1/mutants/18-refusal-hit-logged.log
|
||||
336bea88d6e32ea527941c82124a7aad0ec14e6c80f765c8be57f106ca852afe agents/rocko/work/queue-122/r1/mutants/19-migration-preserve-counts.log
|
||||
020ff9fc8248abca9c722a892b3308ebdacb1375ab0186966690d5451090b203 agents/rocko/work/queue-122/r1/mutants/20-migration-ambiguity.log
|
||||
37224d0a22f6e19b607149aa82fb66c87a09f54c622cfbeccf188b170a13fb20 agents/rocko/work/queue-122/r1/mutants/21-print-only-migration.log
|
||||
51d37658221ff699a35434b9d2e21cf8ae7c27fba5a5eb58e5b66db4eefade6d agents/rocko/work/queue-122/r1/mutants/22-human-only-settings.log
|
||||
7b705b36dc158b72de50063a7d2b742089f5044c9aa4f7f76cf3690063bac157 agents/rocko/work/queue-122/r1/mutants/23-settings-origin.log
|
||||
c20d931c5496c9ed3e535cd10d0d1d00570d309c649e1faeef7da4ec66602e0f agents/rocko/work/queue-122/r1/mutants/24-settings-fetch-metadata.log
|
||||
4a1ad0006668c77cc6eb1bc2bc388b3b60ab38ce894b2399b86c73ea9a9f3ce6 agents/rocko/work/queue-122/r1/mutants/25-settings-send-mode.log
|
||||
fd1db6f7901762dbb5ded8c1241b288f5b2be34a6ffd1ed0f08b60b44f540a50 agents/rocko/work/queue-122/r1/mutants/26-settings-strict-keys.log
|
||||
c08ea093c50d95e1282cc1592b8e5d00d0feed74d8cf1d434f8a0aa8dab0cd22 agents/rocko/work/queue-122/r1/mutants/27-form-instances.log
|
||||
2062afc08db15bacd0728f0fe08237053199dce47ff2fe516c90a1954efd1212 agents/rocko/work/queue-122/r1/mutants/28-form-limit-payload.log
|
||||
c6bb573f3c8dc21dd68b97bafeff531ee5428ec9bef7d94d75da708ae974e4f4 agents/rocko/work/queue-122/r1/mutants/29-migration-idempotent.log
|
||||
d3991dc610029dd2c74f448bb4638445b40494ddaf31995a47884915a58e81e3 agents/rocko/work/queue-122/r1/mutants/30-zero-stops-new.log
|
||||
85b23ad9cb83dc55ae3ef66f2f60039203cae8810982b63a51375c6494f10499 agents/rocko/work/queue-122/r1/mutants/31-instance-model-edit.log
|
||||
69a011e8a2237f9242c3470a44aa14018076360519de1a7e474d8f2a2d1ef65a agents/rocko/work/queue-122/r1/mutants/32-model-table-edit.log
|
||||
4f472113774ece5109ca061807e87faf6584f468f930cae6e6d45447e6ec6ee3 agents/rocko/work/queue-122/r1/mutants/33-runtime-writer-wiring.log
|
||||
2a71db9c81a7cfc5bca19906d1c6f42356c2af231db4e4c41eac8fe0928d211f agents/rocko/work/queue-122/r1/mutants/results.json
|
||||
b2bbc0e9ee66790b767b6d08793acb43be7d02f34f3285ddf46d88fb2f457a9b agents/rocko/work/queue-122/r1/mutants-run.log
|
||||
69e301cde4278e0c2e9a21db6ce75b6a69caae634ac6c661147bbd168be907c9 agents/rocko/work/queue-122/r1/mutants.py
|
||||
2c3eaff1c2f2bcb500f945836754565af52290a4bd579907b42186212bc7c95f agents/rocko/work/queue-122/r1/network-cleanup.json
|
||||
9142f61b031c002426c68c78b7f6cf81aaae3ba9de7894b993660976e2b61a19 agents/rocko/work/queue-122/r1/out/business-compat.txt
|
||||
c52dfa99bf1b5f6b12078c60dd07a09af66c767f4c240b9db015e1aaf8bc33ab agents/rocko/work/queue-122/r1/out/green-business-first.txt
|
||||
3df05fa0a8086c043c0a48a090030d0a779dd2e9c36227a90fd34e037a53aad3 agents/rocko/work/queue-122/r1/out/red-business.txt
|
||||
22674326f5f3231df9dea449b606783928ba726ab88c7cf1fd7b90b6d78915e0 agents/rocko/work/queue-122/r1/out/red-settings-route.txt
|
||||
2c370725fcb24d3faf6d7bee1efe7fb76967dc25cd62ba07b7fd377d8a9328a2 agents/rocko/work/queue-122/r1/shell-readers.txt
|
||||
a32bd57c705e63ae1f55596a67bc8a62431addb75f347dc0f1995bad4bce0318 agents/rocko/work/queue-122/r1/sweep.log
|
||||
970dcdfe0fb05e487b9696eae36b385e015867cf18fa1e06f0ab6b763484a7cb agents/rocko/work/queue-122/r1/sweep.py
|
||||
@@ -0,0 +1,43 @@
|
||||
2:# Suite for packages/queue (issue #1508). Every test runs in scratch
|
||||
11:# `scripts/mosaic queue`. Each takes the queue lock for a moment and writes
|
||||
14:# `scripts/mosaic queue help` still runs, reading no queue file and taking no
|
||||
36:for f in packages/queue/src/*.mjs packages/queue/tests/*.mjs packages/queue/tests/fixtures/*.mjs packages/queue/tests/fixtures/*.sh scripts/queue-commit.sh scripts/git-hooks/pre-commit scripts/mosaic; do
|
||||
38: *.sh|scripts/mosaic) bash -n "$f" >/dev/null 2>&1 ;;
|
||||
44:[ -x scripts/queue-commit.sh ] && [ -x scripts/git-hooks/pre-commit ] && [ -x scripts/mosaic ]
|
||||
45:check "queue-commit.sh, the guard and scripts/mosaic are executable" $?
|
||||
46:node -e 'const p=require("./packages/queue/package.json"); process.exit(p.dependencies||p.devDependencies?1:0)' >/dev/null 2>&1
|
||||
47:check "packages/queue declares no dependencies" $?
|
||||
50:env -u NODE_TEST_CONTEXT node --test --test-reporter=spec packages/queue/tests/ > "$SANDBOX/tests.log" 2>&1
|
||||
54:check "node --test packages/queue/tests/" "$rc"
|
||||
57:scripts/mosaic queue help > "$SANDBOX/help.out" 2>&1 && grep -q '^usage: queue list' "$SANDBOX/help.out"
|
||||
58:check "scripts/mosaic queue help" $?
|
||||
71: scripts/mosaic queue verify
|
||||
72: check "scripts/mosaic queue verify (live queue)" $?
|
||||
73: scripts/mosaic queue render --check
|
||||
74: check "scripts/mosaic queue render --check (live queue)" $?
|
||||
scripts/mosaic-task.mjs:37:import { BusinessError, validateRoleDocument } from "../packages/business/src/index.mjs";
|
||||
scripts/mosaic-task.mjs:629: if (!target) fail(4, "usage: mosaic-task.mjs validate <taskFile>");
|
||||
scripts/mosaic-task.mjs:637: if (!target) fail(4, "usage: mosaic-task.mjs run <taskFile>");
|
||||
scripts/mosaic-task.mjs:641: if (!target) fail(4, "usage: mosaic-task.mjs show <runId>");
|
||||
scripts/mosaic-task.mjs:651: if (!target) fail(4, "usage: mosaic-task.mjs resolve-role <roleFile>");
|
||||
scripts/mosaic-task.mjs:659: if (!target) fail(4, "usage: mosaic-task.mjs retry <runId>");
|
||||
scripts/test-task.sh:53:TASK="node scripts/mosaic-task.mjs"
|
||||
scripts/test-task.sh:119:expect_exit "prune dry-run exits 0" 0 -- env MOSAIC_CONFIG="$SANDBOX/prune-config.json" node scripts/mosaic-task.mjs prune
|
||||
scripts/test-task.sh:123:expect_exit "prune --keep=2 --yes removes oldest" 0 -- env MOSAIC_CONFIG="$SANDBOX/prune-config.json" node scripts/mosaic-task.mjs prune --keep=2 --yes
|
||||
scripts/test-task.sh:136:expect_exit "prune with invalid keep exits 4" 4 -- env MOSAIC_CONFIG="$SANDBOX/prune-config.json" node scripts/mosaic-task.mjs prune --keep=0 --yes
|
||||
scripts/test-task.sh:182: node scripts/mosaic-task.mjs retry "$(ls -dt "$SANDBOX/data/runs"/r-* | head -1 | xargs basename)"
|
||||
scripts/test-task.sh:192: env MOSAIC_CONFIG="$SANDBOX/mock-adapters.json" node scripts/mosaic-task.mjs retry r-missing
|
||||
scripts/test-task.sh:243: ROLE_OUT="$(node scripts/mosaic-task.mjs resolve-role roles/researcher.json 2>/dev/null)" \
|
||||
scripts/test-task.sh:248: node scripts/mosaic-task.mjs resolve-role roles/conductor-policy.json
|
||||
scripts/test-task.sh:252: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/mismatch.json"
|
||||
scripts/test-task.sh:255: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/badnet.json"
|
||||
scripts/test-task.sh:258: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/dupe.json"
|
||||
scripts/test-task.sh:261: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/aliens.json"
|
||||
scripts/test-task.sh:263: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/absent.json"
|
||||
scripts/test-task.sh:269: V2_OUT="$(node scripts/mosaic-task.mjs resolve-role "roles/$r.json" 2>/dev/null)" \
|
||||
scripts/test-task.sh:281: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2ok.json"
|
||||
scripts/test-task.sh:284: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2unknown.json"
|
||||
scripts/test-task.sh:287: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2gated.json"
|
||||
scripts/test-task.sh:290: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2scope.json"
|
||||
scripts/test-task.sh:293: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2nocontract.json"
|
||||
scripts/test-task.sh:297: node scripts/mosaic-task.mjs resolve-role "$SANDBOX/roles/v2link.json"
|
||||
@@ -0,0 +1,2 @@
|
||||
{"before": []}
|
||||
{"after": []}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Sweep only Rocko122 node/chromium processes. Never match another seat/live copy."""
|
||||
import os,pathlib,signal,time,json,sys
|
||||
root='/mnt/storage/src/mosaic-stack-rocko-122'
|
||||
def owned():
|
||||
found=[]
|
||||
for p in pathlib.Path('/proc').glob('[0-9]*'):
|
||||
try:
|
||||
argv=(p/'cmdline').read_bytes().split(b'\0');exe=pathlib.Path(argv[0].decode()).name;cwd=os.readlink(p/'cwd')
|
||||
if exe not in ['node','chromium','chrome','chrome_crashpad_handler']:continue
|
||||
if cwd==root or cwd.startswith(root+'/') or any(root.encode() in a for a in argv):found.append({'pid':int(p.name),'exe':exe,'cwd':cwd})
|
||||
except (OSError,UnicodeError):continue
|
||||
return found
|
||||
before=owned();print(json.dumps({'before':before}))
|
||||
for row in before:
|
||||
try:os.kill(row['pid'],signal.SIGTERM)
|
||||
except ProcessLookupError:pass
|
||||
if before:time.sleep(1)
|
||||
for row in owned():
|
||||
try:os.kill(row['pid'],signal.SIGKILL)
|
||||
except ProcessLookupError:pass
|
||||
if before:time.sleep(.2)
|
||||
after=owned();print(json.dumps({'after':after}));sys.exit(bool(after))
|
||||
Reference in New Issue
Block a user