chore: baseline container POC and atomic foundation plan
- Containerized Pi hello-world proof (image mosaic-poc-agent:0.84.4, non-root) - Four immutable contract fixtures loaded into a generated system prompt - build/hello/verify/reset scripts with exact-match gating and reset safety - Documented Pi discovery (v0.84.4, -p mode, --system-prompt, container auth) - Append-only BUILD-LOG with corrections; deferred layers in LAYERS.md - Architecture plan: docs/plans/2026-09-02_atomic-mosaic-foundation.md
This commit is contained in:
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the mosaic-agent container image using Docker Compose.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
# shellcheck source=common.sh
|
||||
source scripts/common.sh
|
||||
|
||||
bootstrap_runtime_dir
|
||||
|
||||
docker compose build
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
# Shared helpers for the POC host scripts. Not a documented entry point.
|
||||
|
||||
MOSAIC_DEV_DIR="/home/jwoltje/.mosaic-dev"
|
||||
POC_ROOT_MARKER=".mosaic-poc-root"
|
||||
|
||||
# Ensure the runtime state directory exists and carries this project's
|
||||
# ownership marker. The marker is what scripts/reset.sh requires before
|
||||
# it will delete anything.
|
||||
bootstrap_runtime_dir() {
|
||||
if [ ! -d "$MOSAIC_DEV_DIR" ]; then
|
||||
mkdir -p "$MOSAIC_DEV_DIR"
|
||||
echo "bootstrap: created $MOSAIC_DEV_DIR"
|
||||
fi
|
||||
touch "$MOSAIC_DEV_DIR/$POC_ROOT_MARKER"
|
||||
}
|
||||
Executable
+113
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Repository-local Git credential helper for git.mosaicstack.dev.
|
||||
*
|
||||
* Git invokes this helper with "get", "store", or "erase" and consumes its
|
||||
* stdout directly. Never invoke it manually, enable shell tracing around it,
|
||||
* or add credential values to logs.
|
||||
*
|
||||
* The credential file is intentionally not part of Git and must remain mode
|
||||
* 0600. Override its location with MOSAIC_GITEA_CREDENTIAL_FILE if needed.
|
||||
*/
|
||||
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
const operation = process.argv[2] ?? "";
|
||||
|
||||
// Git may offer credentials back through stdin for store/erase. This helper is
|
||||
// read-only: ignore those operations and never persist or print their input.
|
||||
if (operation !== "get") {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const defaultCredentialFile = path.join(
|
||||
os.homedir(),
|
||||
"secrets",
|
||||
"mosaic.gitea.json",
|
||||
);
|
||||
const credentialFile =
|
||||
process.env.MOSAIC_GITEA_CREDENTIAL_FILE ?? defaultCredentialFile;
|
||||
|
||||
function fail(message) {
|
||||
process.stderr.write(`git-credential-mosaic: ${message}\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let stat;
|
||||
try {
|
||||
stat = fs.lstatSync(credentialFile);
|
||||
} catch {
|
||||
fail("credential file is unavailable");
|
||||
}
|
||||
|
||||
if (!stat.isFile() || stat.isSymbolicLink()) {
|
||||
fail("credential path must be a regular, non-symbolic-link file");
|
||||
}
|
||||
if ((stat.mode & 0o077) !== 0) {
|
||||
fail("credential file permissions must be 0600 or stricter");
|
||||
}
|
||||
if (typeof process.getuid === "function" && stat.uid !== process.getuid()) {
|
||||
fail("credential file must be owned by the current user");
|
||||
}
|
||||
|
||||
let document;
|
||||
try {
|
||||
document = JSON.parse(fs.readFileSync(credentialFile, "utf8"));
|
||||
} catch {
|
||||
fail("credential file is not valid JSON");
|
||||
}
|
||||
|
||||
const entry = document?.mosaicstack;
|
||||
const configuredUrl = entry?.url;
|
||||
const username = entry?.user;
|
||||
const token = entry?.api_token;
|
||||
|
||||
if (
|
||||
typeof configuredUrl !== "string" ||
|
||||
typeof username !== "string" ||
|
||||
typeof token !== "string" ||
|
||||
username.length === 0 ||
|
||||
token.length === 0 ||
|
||||
/[\r\n]/.test(username) ||
|
||||
/[\r\n]/.test(token)
|
||||
) {
|
||||
fail("credential file is missing valid mosaicstack url/user/api_token fields");
|
||||
}
|
||||
|
||||
let credentialUrl;
|
||||
try {
|
||||
credentialUrl = new URL(configuredUrl);
|
||||
} catch {
|
||||
fail("configured credential URL is invalid");
|
||||
}
|
||||
|
||||
if (
|
||||
credentialUrl.protocol !== "https:" ||
|
||||
credentialUrl.hostname !== "git.mosaicstack.dev"
|
||||
) {
|
||||
fail("credential URL is not the approved HTTPS Gitea host");
|
||||
}
|
||||
|
||||
const request = {};
|
||||
for (const line of fs.readFileSync(0, "utf8").split("\n")) {
|
||||
const separator = line.indexOf("=");
|
||||
if (separator > 0) {
|
||||
request[line.slice(0, separator)] = line.slice(separator + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Fail closed: emit credentials only for the approved HTTPS host. A host may
|
||||
// include an explicit port; it must match the configured URL exactly.
|
||||
if (
|
||||
request.protocol !== "https" ||
|
||||
request.host !== credentialUrl.host
|
||||
) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// stdout is the Git credential-helper protocol channel, consumed directly by
|
||||
// Git. Do not add status messages here.
|
||||
process.stdout.write(`username=${username}\npassword=${token}\n`);
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run the mosaic-agent service as a one-shot container and print the
|
||||
# model response for the exact startup verification request.
|
||||
#
|
||||
# The request deliberately does NOT contain the expected marker
|
||||
# MOSAIC_HELLO_OK. Only the model response is printed to stdout; no
|
||||
# credentials or unrelated runtime data are printed.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
# shellcheck source=common.sh
|
||||
source scripts/common.sh
|
||||
|
||||
bootstrap_runtime_dir
|
||||
|
||||
# -T: no pseudo-TTY, so stdout is clean model output.
|
||||
# Errors, if any, go to stderr for diagnostics.
|
||||
docker compose run --rm -T mosaic-agent
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# Delete the generated POC runtime state at /home/jwoltje/.mosaic-dev,
|
||||
# but ONLY when every safety check passes:
|
||||
# 1. The resolved path is exactly /home/jwoltje/.mosaic-dev.
|
||||
# 2. The path is not a symbolic link.
|
||||
# 3. The directory contains the .mosaic-poc-root ownership marker
|
||||
# created by this project.
|
||||
# Any failed check aborts with nothing deleted.
|
||||
set -euo pipefail
|
||||
|
||||
TARGET="/home/jwoltje/.mosaic-dev"
|
||||
MARKER=".mosaic-poc-root"
|
||||
|
||||
fail() {
|
||||
echo "reset: refusing to delete: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Nothing to do when the directory does not exist.
|
||||
if [ ! -e "$TARGET" ]; then
|
||||
echo "reset: $TARGET does not exist; nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check 2 (before resolution): the path itself must not be a symlink.
|
||||
if [ -L "$TARGET" ]; then
|
||||
fail "$TARGET is a symbolic link"
|
||||
fi
|
||||
|
||||
# Check 1: resolved path must be exactly the POC runtime directory.
|
||||
RESOLVED="$(realpath "$TARGET")"
|
||||
if [ "$RESOLVED" != "$TARGET" ]; then
|
||||
fail "resolved path $RESOLVED is not $TARGET"
|
||||
fi
|
||||
|
||||
# Check 3: ownership marker created by this project must be present.
|
||||
if [ ! -f "$TARGET/$MARKER" ]; then
|
||||
fail "missing $MARKER ownership marker in $TARGET"
|
||||
fi
|
||||
|
||||
rm -rf -- "$TARGET"
|
||||
echo "reset: removed $TARGET"
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# Complete verification test:
|
||||
# 1. Build or confirm the image is built.
|
||||
# 2. Run the agent request.
|
||||
# 3. Remove surrounding whitespace from the response.
|
||||
# 4. Compare with the expected marker (default MOSAIC_HELLO_OK).
|
||||
# 5. Exit 0 only on exact match; nonzero otherwise.
|
||||
#
|
||||
# EXPECTED_MARKER may be overridden to prove the failure path
|
||||
# (acceptance criterion 9), e.g.:
|
||||
# EXPECTED_MARKER=MOSAIC_NOT_OK scripts/verify.sh
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
# shellcheck source=common.sh
|
||||
source scripts/common.sh
|
||||
|
||||
IMAGE="mosaic-poc-agent:0.84.4"
|
||||
EXPECTED="${EXPECTED_MARKER:-MOSAIC_HELLO_OK}"
|
||||
|
||||
# 1. Build the image only if it is not already present.
|
||||
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
||||
echo "verify: image $IMAGE not found, building..." >&2
|
||||
bootstrap_runtime_dir
|
||||
docker compose build
|
||||
fi
|
||||
|
||||
# 2. Run the agent request (stdout only = model response).
|
||||
set +e
|
||||
RESPONSE="$(docker compose run --rm -T mosaic-agent 2>/tmp/mosaic-poc-stderr.$$)"
|
||||
RC=$?
|
||||
set -e
|
||||
STDERR_FILE="/tmp/mosaic-poc-stderr.$$"
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "verify: agent run failed (exit $RC):" >&2
|
||||
cat "$STDERR_FILE" >&2
|
||||
rm -f "$STDERR_FILE"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$STDERR_FILE"
|
||||
|
||||
# 3. Remove surrounding whitespace.
|
||||
TRIMMED="$(printf '%s' "$RESPONSE" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||
|
||||
# 4-6. Exact comparison gate.
|
||||
if [ "$TRIMMED" = "$EXPECTED" ]; then
|
||||
echo "PASS: response matches expected marker"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "FAIL: response does not match expected marker" >&2
|
||||
printf 'expected: %s\n' "$EXPECTED" >&2
|
||||
printf 'actual : %s\n' "$TRIMMED" >&2
|
||||
exit 1
|
||||
Reference in New Issue
Block a user