feat(adapters): sanctioned mission directives injection (#17)
- load-contracts.sh: MOSAIC_MISSION_FILE (readable) appends a MISSION (runtime) section — objective + directives — after the immutable contracts; unreadable path is a hard error, absent env changes nothing - mosaic-task.mjs: exports MOSAIC_MISSION_FILE as the run snapshot's container path (/var/lib/mosaic/runs/<id>/mission.json), with an outside-dataRoot guard; also exports the configured adapter Verified: contract-only prompt has no mission section; mission-bearing run shows objective + directives in the generated prompt, snapshot recorded, real provider returns exactly MOSAIC_HELLO_OK. Closes #17
This commit is contained in:
+14
-1
@@ -210,12 +210,25 @@ function runTask(taskFile) {
|
|||||||
|
|
||||||
const startedAt = new Date();
|
const startedAt = new Date();
|
||||||
const stderrFile = path.join(runDir, "stderr.txt");
|
const stderrFile = path.join(runDir, "stderr.txt");
|
||||||
|
|
||||||
|
// Sanctioned mission injection: point the container at the run snapshot's
|
||||||
|
// CONTAINER path (dataRoot maps to /var/lib/mosaic in the image).
|
||||||
|
const spawnEnv = { ...process.env };
|
||||||
|
spawnEnv.MOSAIC_ADAPTER = resolved.execution.adapter;
|
||||||
|
if (task.missionSnapshot) {
|
||||||
|
const relative = path.relative(resolved.dataRoot, runDir);
|
||||||
|
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
||||||
|
fail(4, `run directory is outside the configured dataRoot: ${runDir}`);
|
||||||
|
}
|
||||||
|
spawnEnv.MOSAIC_MISSION_FILE = `/var/lib/mosaic/${relative.split(path.sep).join("/")}/mission.json`;
|
||||||
|
}
|
||||||
|
|
||||||
const proc = spawnSync(
|
const proc = spawnSync(
|
||||||
"docker",
|
"docker",
|
||||||
["compose", "run", "--rm", "-T", "mosaic-agent", task.prompt],
|
["compose", "run", "--rm", "-T", "mosaic-agent", task.prompt],
|
||||||
{
|
{
|
||||||
cwd: PROJECT_ROOT,
|
cwd: PROJECT_ROOT,
|
||||||
env: process.env, // MOSAIC_DATA_ROOT / MOSAIC_PROVIDER / MOSAIC_MODEL resolved by run-task.sh
|
env: spawnEnv,
|
||||||
input: "", // stdin detached: print mode must never wait on a terminal (see issue #5)
|
input: "", // stdin detached: print mode must never wait on a terminal (see issue #5)
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
maxBuffer: 16 * 1024 * 1024,
|
maxBuffer: 16 * 1024 * 1024,
|
||||||
|
|||||||
@@ -40,6 +40,20 @@ cfg() { printf '%s' "$2" > "$SANDBOX/$1"; }
|
|||||||
|
|
||||||
DATA_ROOT="$SANDBOX/data"
|
DATA_ROOT="$SANDBOX/data"
|
||||||
|
|
||||||
|
# --- adapter selection (M4) ---
|
||||||
|
cfg default-adapter.json '{"configVersion":1,"environment":"development","dataRoot":"'$DATA_ROOT'","execution":{"backend":"docker","provider":"zai","model":"m"}}'
|
||||||
|
MOSAIC_CONFIG="$SANDBOX/default-adapter.json" $CONFIG_OP validate | grep -q '"adapter": "pi"'
|
||||||
|
check "absent adapter defaults to pi" $?
|
||||||
|
|
||||||
|
cfg mock-adapter.json '{"configVersion":1,"environment":"development","dataRoot":"'$DATA_ROOT'","execution":{"backend":"docker","provider":"zai","model":"m","adapter":"mock"}}'
|
||||||
|
expect_exit "adapter mock validates" 0 -- env MOSAIC_CONFIG="$SANDBOX/mock-adapter.json" $CONFIG_OP validate
|
||||||
|
|
||||||
|
cfg bad-adapter.json '{"configVersion":1,"environment":"development","dataRoot":"'$DATA_ROOT'","execution":{"backend":"docker","provider":"zai","model":"m","adapter":"claude"}}'
|
||||||
|
expect_exit "unsupported adapter exits 2" 2 -- env MOSAIC_CONFIG="$SANDBOX/bad-adapter.json" $CONFIG_OP validate
|
||||||
|
|
||||||
|
MOSAIC_CONFIG="$SANDBOX/mock-adapter.json" $CONFIG_OP env | grep -q "MOSAIC_ADAPTER='mock'"
|
||||||
|
check "env exports adapter" $?
|
||||||
|
|
||||||
# --- bootstrap ---
|
# --- bootstrap ---
|
||||||
rm -f "$SANDBOX/config.json"
|
rm -f "$SANDBOX/config.json"
|
||||||
expect_exit "bootstrap creates default when absent" 0 -- \
|
expect_exit "bootstrap creates default when absent" 0 -- \
|
||||||
|
|||||||
Reference in New Issue
Block a user