- live hello failure dumps latest run result.json + stderr tail before
sandbox cleanup destroys them
- wrong-expectExact case asserts reason == expect-mismatch (was: any
exit 1, which masked compose-level failures)
- repair dangling if/else from the docker-guard refactor
Closes#15
M3 made MOSAIC_IMAGE_TAG required in compose, but run-task.sh never
called load_release — direct task runs failed in compose before any
model call. release.sh paths masked it by exporting the tag to children.
Found by owner-run test-task.sh; failure receipts were in the run
records' stderr.txt.
Closes#14
14 cases: RELEASE validation (valid/invalid/missing), tag consistency,
status on empty state, fault-injected refusal with no pointer + single
valid refusal log line, healthy activation, pointer fields, repeat
activation append-only log, rollback-without-previous refusal.
Harness fix learned the hard way: restore RELEASE from backup inline
after the missing-file case (mv-back restored the mutated file); single
exit trap self-heals the repo state.
Closes#12
- activate: image-presence pre-check + M2 task-runner health gate
(tasks/hello-marker.json exact marker) before atomic pointer replace
(tmp+rename); every attempt appended to activation-log.jsonl
- --fault-injection flips the health expectation to prove the refusal path
- rollback: health-gated re-activation of the previous activated imageTag
from the log; refuses when the image is gone or no previous exists
- status: release, tag, pointer, recent log; safe on empty state
- state lives under <dataRoot>/state/ (config-independent, reset-scoped)
Verified: activate OK; fault-injected refuse with pointer unchanged;
rollback-without-previous refuse.
Closes#11
- RELEASE file: single source of release version (0.0.X until declared stable)
- common.sh load_release(): validates version, derives
MOSAIC_IMAGE_TAG=mosaic-poc-agent:<pi>-r<release> from the pinned pi dep
- compose.yaml: image tag is required env; build/hello/verify call load_release
- verify.sh derives the image name instead of hardcoding it
- package.json version aligned to the same 0.0.X line
Closes#10
- scripts/mosaic-task.mjs: validate | run | list
- Strict v1 schemas: unknown keys rejected; ids/prompt/expectExact/
timeoutSeconds bounds enforced; optional mission file resolved against
the task file and validated too
- run: executes through the config-driven container path with stdin
detached (issue #5 class), SIGKILL timeout (default 120s), trimmed
response capture
- Immutable run records under <dataRoot>/runs/r-<utcstamp>-<rand>/:
task.json + mission.json snapshots (write-once), stderr.txt, result.json
- expectExact gate: mismatch -> status failed, exit 1; result.json is
always written
- scripts/run-task.sh: load_config + bootstrap_runtime_dir before exec
- M2 scope: mission directives are snapshotted for provenance, not yet
injected into the runtime prompt (later policy layer)
Closes#6, closes#7
pi print mode reads piped stdin until EOF; an attached terminal stdin
blocked the one-shot run forever. Automated contexts (closed stdin)
never exposed it. Request text comes from the compose command.
Proven: tail -f /dev/null | scripts/hello.sh now returns MOSAIC_HELLO_OK
in ~4s (previously timed out at 30s); verify.sh remains green.
Closes#5
- verify.sh now calls bootstrap_runtime_dir after load_config; previously a
reset-then-verify flow let Docker auto-create a root-owned mount source
- common.sh: fail with clear guidance when data root exists but is not writable
- README: configuration section, bootstrap usage, selftest entry point
- BUILD-LOG: Phase 5 entries with corrections
E2E (clean slate): 20/20 selftests; bootstrap idempotent; config-driven
hello/verify MOSAIC_HELLO_OK; negative marker exit 1; reset + rerun green;
config checksum unchanged across the entire flow.
Closes#4