Compare commits
1 Commits
release/mo
...
fix/framew
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a88ff8e232 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -15,10 +15,3 @@ infra/step-ca/dev-password
|
|||||||
|
|
||||||
# Scratch dirs created by the framework git-wrapper shell test harnesses
|
# Scratch dirs created by the framework git-wrapper shell test harnesses
|
||||||
.mosaic-test-work/
|
.mosaic-test-work/
|
||||||
|
|
||||||
# Transient config files vite/vitest/esbuild write next to a *.config.ts while
|
|
||||||
# loading it, then unlink. They are untracked but were not ignored, so turbo's
|
|
||||||
# package traversal hashed them and intermittently failed CI with "Package
|
|
||||||
# traversal error: ... .timestamp-*.mjs: No such file or directory" when the
|
|
||||||
# file vanished mid-scan. Ignoring them removes the race.
|
|
||||||
*.timestamp-*.mjs
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export default tseslint.config(
|
|||||||
'apps/web/e2e/helpers/*.ts',
|
'apps/web/e2e/helpers/*.ts',
|
||||||
'apps/web/playwright.config.ts',
|
'apps/web/playwright.config.ts',
|
||||||
'apps/gateway/vitest.config.ts',
|
'apps/gateway/vitest.config.ts',
|
||||||
'packages/db/vitest.config.ts',
|
|
||||||
'packages/storage/vitest.config.ts',
|
'packages/storage/vitest.config.ts',
|
||||||
'packages/mosaic/__tests__/*.ts',
|
'packages/mosaic/__tests__/*.ts',
|
||||||
'tools/federation-harness/*.ts',
|
'tools/federation-harness/*.ts',
|
||||||
|
|||||||
@@ -4,22 +4,5 @@ export default defineConfig({
|
|||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'node',
|
environment: 'node',
|
||||||
// The migration suite spins up a real PGlite (WASM Postgres) instance per
|
|
||||||
// test and applies the full drizzle migration set. Each case legitimately
|
|
||||||
// takes ~5s locally and considerably longer on CI, where turbo runs many
|
|
||||||
// packages' test suites concurrently. The 5s vitest default then expires
|
|
||||||
// mid-migration and the run fails as a phantom "Test timed out in 5000ms"
|
|
||||||
// (often surfacing the underlying WASM `memory access out of bounds` when
|
|
||||||
// the heap is starved). Give migrations real headroom.
|
|
||||||
testTimeout: 120_000,
|
|
||||||
hookTimeout: 120_000,
|
|
||||||
// Each PGlite instance carries a multi-hundred-MB WASM heap. Running test
|
|
||||||
// files in parallel forks multiplies that peak and is what tips the CI
|
|
||||||
// runner into the WASM OOM. A single fork keeps only one instance resident
|
|
||||||
// at a time — slightly slower, but deterministic.
|
|
||||||
pool: 'forks',
|
|
||||||
poolOptions: {
|
|
||||||
forks: { singleFork: true },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -122,85 +122,6 @@ fi
|
|||||||
|
|
||||||
mkdir -p "$MOSAIC_AGENT_WORKDIR"
|
mkdir -p "$MOSAIC_AGENT_WORKDIR"
|
||||||
|
|
||||||
# ── Pre-trust the workdir for the Claude runtime ─────────────────────────────
|
|
||||||
# Claude Code shows a one-time "Is this a project you trust?" folder-trust gate
|
|
||||||
# the first time it opens a directory. A fleet-launched agent has no human to
|
|
||||||
# answer it, so the pane stalls forever at the prompt while its heartbeat keeps
|
|
||||||
# reporting "healthy" (the pane process IS alive — it's just blocked).
|
|
||||||
#
|
|
||||||
# IMPORTANT: --dangerously-skip-permissions does NOT bypass this gate, and
|
|
||||||
# neither does `trustedProjectDirectories` in settings.json (verified empirically
|
|
||||||
# 2026-06-24). The ONLY thing the gate honors is the per-project record in
|
|
||||||
# ~/.claude.json: projects["<dir>"].hasTrustDialogAccepted == true (exactly what
|
|
||||||
# answering the prompt writes). So we pre-seed that record here.
|
|
||||||
#
|
|
||||||
# Idempotent, atomic, best-effort: any failure is non-fatal (the agent still
|
|
||||||
# launches — worst case it stalls on the gate, i.e. the pre-fix status quo).
|
|
||||||
# Only the claude runtime needs this; codex/pi have no such gate.
|
|
||||||
_ensure_claude_workdir_trusted() {
|
|
||||||
local workdir="$1"
|
|
||||||
# The path claude keys on is the resolved cwd it is launched in.
|
|
||||||
local rp
|
|
||||||
rp=$(cd "$workdir" 2>/dev/null && pwd -P) || rp="$workdir"
|
|
||||||
# ~/.claude.json lives next to the claude config dir; honor CLAUDE_CONFIG_DIR.
|
|
||||||
local claude_json="${MOSAIC_CLAUDE_JSON:-${CLAUDE_CONFIG_DIR:+$CLAUDE_CONFIG_DIR/.claude.json}}"
|
|
||||||
claude_json="${claude_json:-$HOME/.claude.json}"
|
|
||||||
|
|
||||||
if ! command -v python3 >/dev/null 2>&1; then
|
|
||||||
echo "WARNING: python3 not found; cannot pre-trust '$rp' for claude (agent may stall on the folder-trust gate)" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Serialize concurrent agent launches that share ~/.claude.json (flock if available).
|
|
||||||
local lock="${claude_json}.mosaic-lock"
|
|
||||||
_seed() {
|
|
||||||
MOSAIC_CJ="$claude_json" MOSAIC_TRUST_DIR="$rp" python3 - <<'PY'
|
|
||||||
import json, os, sys, tempfile
|
|
||||||
cj = os.environ["MOSAIC_CJ"]
|
|
||||||
d = os.environ["MOSAIC_TRUST_DIR"]
|
|
||||||
try:
|
|
||||||
data = json.load(open(cj)) if os.path.exists(cj) else {}
|
|
||||||
if not isinstance(data, dict):
|
|
||||||
data = {}
|
|
||||||
except Exception:
|
|
||||||
# Never corrupt an unreadable/partial file — bail without writing.
|
|
||||||
sys.exit(2)
|
|
||||||
projects = data.setdefault("projects", {})
|
|
||||||
entry = projects.get(d)
|
|
||||||
if not isinstance(entry, dict):
|
|
||||||
entry = {}
|
|
||||||
projects[d] = entry
|
|
||||||
if entry.get("hasTrustDialogAccepted") is True:
|
|
||||||
sys.exit(0) # already trusted — nothing to do
|
|
||||||
entry["hasTrustDialogAccepted"] = True
|
|
||||||
tmp_dir = os.path.dirname(cj) or "."
|
|
||||||
fd, tmp = tempfile.mkstemp(dir=tmp_dir, prefix=".claude.json.mosaic.")
|
|
||||||
try:
|
|
||||||
with os.fdopen(fd, "w") as f:
|
|
||||||
json.dump(data, f, indent=2)
|
|
||||||
os.replace(tmp, cj) # atomic
|
|
||||||
except Exception:
|
|
||||||
try:
|
|
||||||
os.unlink(tmp)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
sys.exit(3)
|
|
||||||
PY
|
|
||||||
}
|
|
||||||
if command -v flock >/dev/null 2>&1; then
|
|
||||||
( flock 9; _seed ) 9>"$lock" 2>/dev/null || _seed
|
|
||||||
else
|
|
||||||
_seed
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$MOSAIC_AGENT_RUNTIME" in
|
|
||||||
claude)
|
|
||||||
_ensure_claude_workdir_trusted "$MOSAIC_AGENT_WORKDIR" \
|
|
||||||
|| echo "WARNING: could not pre-trust workdir for claude agent $AGENT_NAME" >&2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# ── Launch the tmux session (no exec — we continue to wire the heartbeat) ────
|
# ── Launch the tmux session (no exec — we continue to wire the heartbeat) ────
|
||||||
_tmux new-session -d -s "$AGENT_NAME" -c "$MOSAIC_AGENT_WORKDIR" \
|
_tmux new-session -d -s "$AGENT_NAME" -c "$MOSAIC_AGENT_WORKDIR" \
|
||||||
bash -c "$PANE_SHELL_SNIPPET"
|
bash -c "$PANE_SHELL_SNIPPET"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mosaicstack/mosaic",
|
"name": "@mosaicstack/mosaic",
|
||||||
"version": "0.0.42",
|
"version": "0.0.41",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.mosaicstack.dev/mosaicstack/stack.git",
|
"url": "https://git.mosaicstack.dev/mosaicstack/stack.git",
|
||||||
|
|||||||
Reference in New Issue
Block a user