chore(harness): make repository agent-ready

Add concise routed context, task-aware agent roles, focused skills, and structured learning promotion.\n\nUnify local development and workspace tooling, add layered test and E2E verification, harden MCP authentication, and gate deployment behind verification and explicit production promotion.
This commit is contained in:
jjbrunton committed 2026-08-27 20:58:48 +01:00
1 parent 5a69bbc1a5
commit 01bb8225ae
125 files changed
+5078 -24529

No files matched your search

+151
View File
@@ -0,0 +1,151 @@
#!/usr/bin/env bash
set -euo pipefail
SESSION="sauci-dev"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SERVERS=(
"functions|npx supabase functions serve --workdir apps"
"web|scripts/with-local-supabase-env.sh web npm run dev -w @sauci/web -- --port 3000"
"admin|scripts/with-local-supabase-env.sh admin npm run dev -w @sauci/admin -- --host 127.0.0.1 --port 3001"
"mcp|scripts/with-local-supabase-env.sh mcp npm run dev -w sauci-mcp-server"
"mobile|scripts/with-local-supabase-env.sh mobile npm run dev -w @sauci/mobile -- --port 8081 --localhost"
)
PORTS=(
"supabase-api:54321"
"postgres:54322"
"studio:54323"
"web:3000"
"admin:3001"
"mcp:3002"
"metro:8081"
)
c_reset=$'\033[0m'; c_dim=$'\033[2m'; c_grn=$'\033[32m'; c_ylw=$'\033[33m'; c_red=$'\033[31m'; c_cyn=$'\033[36m'
info() { printf "${c_cyn}▸ %s${c_reset}\n" "$*"; }
ok() { printf "${c_grn}✓ %s${c_reset}\n" "$*"; }
warn() { printf "${c_ylw}! %s${c_reset}\n" "$*"; }
die() { printf "${c_red}✗ %s${c_reset}\n" "$*" >&2; exit 1; }
port_up() { lsof -ti :"$1" -sTCP:LISTEN >/dev/null 2>&1; }
preflight() {
command -v tmux >/dev/null 2>&1 || die "tmux not found. Install: brew install tmux"
command -v npm >/dev/null 2>&1 || die "npm not found. Install Node $(cat "$ROOT/.nvmrc")."
command -v docker >/dev/null 2>&1 || die "Docker-compatible CLI not found."
docker info >/dev/null 2>&1 || die "Container runtime is not running."
[ -d "$ROOT/node_modules" ] || die "Dependencies missing. Run: npm ci"
local node_major
node_major="$(node -p 'process.versions.node.split(`.`)[0]')"
[ "$node_major" = "20" ] || die "Node 20 is required. Activate .nvmrc before starting the stack."
}
ensure_infra() {
if (cd "$ROOT" && npx supabase status --workdir apps >/dev/null 2>&1); then
ok "Local Supabase already running"
else
info "Starting local Supabase"
(cd "$ROOT" && GOOGLE_CLIENT_ID=local APPLE_CLIENT_ID=local \
GOOGLE_CLIENT_SECRET=local APPLE_CLIENT_SECRET=local \
npx supabase start --workdir apps)
fi
}
start_window() {
local name="$1" cmd="$2"
if tmux list-windows -t "$SESSION" -F '#{window_name}' 2>/dev/null | grep -qx "$name"; then
warn "window '$name' already exists"
return
fi
tmux new-window -t "$SESSION" -n "$name" -c "$ROOT"
tmux send-keys -t "$SESSION:$name" "$cmd" C-m
}
port_check() {
printf " Port status (${c_dim}· = stopped or starting${c_reset}):\n"
local entry name port
for entry in "${PORTS[@]}"; do
name="${entry%%:*}"; port="${entry##*:}"
if port_up "$port"; then printf " ${c_grn}●${c_reset} %-14s :%s\n" "$name" "$port"
else printf " ${c_dim}·${c_reset} %-14s :%s\n" "$name" "$port"; fi
done
}
cmd_up() {
preflight
ensure_infra
tmux has-session -t "$SESSION" 2>/dev/null || tmux new-session -d -s "$SESSION" -n _bootstrap -c "$ROOT"
local service
for service in "${SERVERS[@]}"; do start_window "${service%%|*}" "${service#*|}"; done
tmux kill-window -t "$SESSION:_bootstrap" 2>/dev/null || true
ok "Stack starting in tmux session '$SESSION'"
port_check
printf "\n Web: http://127.0.0.1:3000\n Admin: http://127.0.0.1:3001\n MCP: http://127.0.0.1:3002/health\n Studio:http://127.0.0.1:54323\n"
}
cmd_status() {
if tmux has-session -t "$SESSION" 2>/dev/null; then
info "tmux '$SESSION' windows"
tmux list-windows -t "$SESSION" -F ' #{window_index}: #{window_name}'
else
warn "session '$SESSION' not running"
fi
port_check
}
cmd_logs() {
tmux has-session -t "$SESSION" 2>/dev/null || die "session not running"
tmux capture-pane -p -S -400 -t "$SESSION:${1:?usage: logs <service>}"
}
cmd_restart() {
tmux has-session -t "$SESSION" 2>/dev/null || die "session not running"
local name="${1:?usage: restart <service>}" service
tmux kill-window -t "$SESSION:$name" 2>/dev/null || true
for service in "${SERVERS[@]}"; do
if [ "${service%%|*}" = "$name" ]; then
start_window "$name" "${service#*|}"
ok "restarted $name"
return
fi
done
die "unknown service '$name'"
}
cmd_down() {
tmux kill-session -t "$SESSION" 2>/dev/null && ok "application services stopped" || warn "no session '$SESSION'"
if [ "${1:-}" = "--all" ]; then
(cd "$ROOT" && npx supabase stop --workdir apps)
ok "local Supabase stopped"
fi
}
cmd_reset() {
preflight
ensure_infra
(cd "$ROOT" && npx supabase db reset --workdir apps)
(cd "$ROOT" && scripts/with-local-supabase-env.sh tests node scripts/seed-e2e.mjs)
ok "Local database reset and deterministic fixtures created"
}
cmd_native() {
local platform="$1"
preflight
ensure_infra
(cd "$ROOT" && scripts/with-local-supabase-env.sh mobile npm run "$platform" -w @sauci/mobile)
}
case "${1:-up}" in
up) cmd_up ;;
down) cmd_down "${2:-}" ;;
status) cmd_status ;;
logs) cmd_logs "${2:-}" ;;
restart) cmd_restart "${2:-}" ;;
attach) tmux attach -t "$SESSION" ;;
reset|seed) cmd_reset ;;
ios|android) cmd_native "$1" ;;
help|-h|--help)
echo "usage: scripts/dev-local.sh up|down [--all]|status|logs <service>|restart <service>|attach|reset|ios|android"
;;
*) die "unknown command '$1'" ;;
esac
+86
View File
@@ -0,0 +1,86 @@
import { access, readFile, readdir } from 'node:fs/promises';
import path from 'node:path';
const root = path.resolve(new URL('..', import.meta.url).pathname);
const errors = [];
const scoped = process.argv.includes('--scope');
async function exists(file) {
try { await access(file); return true; } catch { return false; }
}
async function walk(directory, files = []) {
for (const entry of await readdir(directory, { withFileTypes: true })) {
if (['.git', 'node_modules', '.next', 'dist', 'build', 'coverage', 'evidence', '.ralph'].includes(entry.name)) continue;
const target = path.join(directory, entry.name);
if (entry.isDirectory()) await walk(target, files);
else files.push(target);
}
return files;
}
function fail(file, message, fix) {
errors.push(`${path.relative(root, file)}: ${message}\n Fix: ${fix}`);
}
const allFiles = await walk(root);
for (const file of allFiles) {
if (path.basename(file) === 'agents.md') {
fail(file, 'lowercase agent context is not discoverable consistently', 'rename it to AGENTS.md or move maintained detail under docs/');
}
if (!/\.(md|sql)$/.test(file)) continue;
const source = await readFile(file, 'utf8');
if (/^\s*[-*]\s*Use\s+.*apply_migration/im.test(source)) {
fail(file, 'instruction authorizes untracked remote migrations', 'create a local apps/supabase/migrations file instead');
}
}
if (!scoped) {
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
for (const app of (await readdir(path.join(root, 'apps'), { withFileTypes: true })).filter((entry) => entry.isDirectory())) {
const packageFile = path.join(root, 'apps', app.name, 'package.json');
if (!(await exists(packageFile))) continue;
if (!packageJson.workspaces.includes(`apps/${app.name}`)) {
fail(packageFile, 'application is outside the root workspace', `add apps/${app.name} to package.json workspaces`);
}
}
const claude = await readFile(path.join(root, 'CLAUDE.md'), 'utf8');
if (claude.split('\n').length > 20 || !claude.includes('AGENTS.md')) {
fail(path.join(root, 'CLAUDE.md'), 'runtime-specific context has drifted from the universal map', 'keep CLAUDE.md as a short pointer to AGENTS.md');
}
const duplicateMigrations = path.join(root, 'supabase', 'migrations');
if (await exists(duplicateMigrations)) {
const entries = await readdir(duplicateMigrations);
if (entries.length) fail(duplicateMigrations, 'second migration tree can bypass deployment', 'move migrations to apps/supabase/migrations and remove the duplicate');
}
const cutoff = '20260201100806';
const migrationDir = path.join(root, 'apps', 'supabase', 'migrations');
for (const name of await readdir(migrationDir)) {
if (name.slice(0, 14) <= cutoff) continue;
const file = path.join(migrationDir, name);
const source = await readFile(file, 'utf8');
if (/https:\/\/[a-z0-9-]+\.supabase\.co/i.test(source)) {
fail(file, 'new migration hardcodes a remote Supabase project', 'resolve the function URL from environment-specific app_config');
}
}
const docsIndex = await readFile(path.join(root, 'docs', 'index.md'), 'utf8');
for (const match of docsIndex.matchAll(/\[[^\]]+\]\(([^)]+\.md)\)/g)) {
const target = path.resolve(root, 'docs', match[1]);
if (!(await exists(target))) fail(path.join(root, 'docs', 'index.md'), `broken documentation link ${match[1]}`, 'correct the link or restore the maintained document');
}
const mcpAuth = await readFile(path.join(root, 'apps', 'mcp', 'src', 'lib', 'auth.ts'), 'utf8');
if (/allowing all requests|query\(['"]apiKey/i.test(mcpAuth)) {
fail(path.join(root, 'apps', 'mcp', 'src', 'lib', 'auth.ts'), 'MCP authentication can leak or fail open', 'require a configured Bearer token and fail closed');
}
}
if (errors.length) {
console.error(`Harness invariant failures (${errors.length}):\n\n${errors.join('\n\n')}`);
process.exit(1);
}
console.log('Harness invariants passed');
+80
View File
@@ -0,0 +1,80 @@
import { mkdir, writeFile } from 'node:fs/promises';
import { createClient } from '@supabase/supabase-js';
const url = process.env.SUPABASE_URL;
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
if (!url || !serviceKey) throw new Error('Local Supabase environment is required');
const host = new URL(url).hostname;
if (host !== '127.0.0.1' && host !== 'localhost') {
throw new Error(`Refusing to seed non-local Supabase host: ${host}`);
}
const client = createClient(url, serviceKey, {
auth: { autoRefreshToken: false, persistSession: false },
});
const password = 'Sauci-e2e-only-2026!';
const emails = ['e2e.alex@example.test', 'e2e.sam@example.test'];
const { data: listed, error: listError } = await client.auth.admin.listUsers({ perPage: 1000 });
if (listError) throw listError;
for (const user of listed.users.filter((candidate) => emails.includes(candidate.email ?? ''))) {
const { error } = await client.auth.admin.deleteUser(user.id);
if (error) throw error;
}
const users = [];
for (const email of emails) {
const { data, error } = await client.auth.admin.createUser({
email,
password,
email_confirm: true,
user_metadata: { display_name: email.includes('alex') ? 'Alex E2E' : 'Sam E2E' },
});
if (error || !data.user) throw error ?? new Error(`Could not create ${email}`);
users.push(data.user);
}
const coupleId = 'e2e00000-0000-4000-8000-000000000001';
const packId = 'e2e00000-0000-4000-8000-000000000002';
const questionId = 'e2e00000-0000-4000-8000-000000000003';
await client.from('couples').delete().eq('id', coupleId);
let result = await client.from('couples').insert({ id: coupleId, invite_code: 'E2E2026A' });
if (result.error) throw result.error;
result = await client.from('profiles').update({ couple_id: coupleId }).in('id', users.map((user) => user.id));
if (result.error) throw result.error;
result = await client.from('question_packs').upsert({
id: packId,
name: 'E2E Connection Pack',
description: 'Deterministic local verification content',
is_premium: false,
is_public: true,
sort_order: 999,
});
if (result.error) throw result.error;
result = await client.from('questions').upsert({
id: questionId,
pack_id: packId,
text: 'Plan a technology-free evening together',
intensity: 1,
});
if (result.error) throw result.error;
result = await client.from('redemption_codes').upsert({
code: 'SAUCI-E2E-2026',
max_uses: 100,
current_uses: 0,
is_active: true,
expires_at: '2099-01-01T00:00:00.000Z',
});
if (result.error) throw result.error;
await mkdir(new URL('../e2e/.auth/', import.meta.url), { recursive: true });
await writeFile(new URL('../e2e/.auth/fixtures.json', import.meta.url), JSON.stringify({
users: emails.map((email, index) => ({ email, password, id: users[index].id })),
coupleId,
inviteCode: 'E2E2026A',
packId,
questionId,
redemptionCode: 'SAUCI-E2E-2026',
}, null, 2));
console.log('Created deterministic local E2E fixtures');
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
command -v deno >/dev/null 2>&1 || {
echo "Deno is required for Supabase function tests: https://docs.deno.com/runtime/getting_started/installation/" >&2
exit 1
}
if ! (cd "$ROOT" && npx supabase status --workdir apps >/dev/null 2>&1); then
echo "Local Supabase is not running. Start it with scripts/dev-local.sh up." >&2
exit 1
fi
cd "$ROOT/apps/supabase/tests"
"$ROOT/scripts/with-local-supabase-env.sh" tests deno task test
+34
View File
@@ -0,0 +1,34 @@
import { readFile, readdir } from 'node:fs/promises';
import path from 'node:path';
const root = path.resolve(new URL('..', import.meta.url).pathname);
const base = path.join(root, '.agents', 'learnings');
const requiredSections = ['## Symptom', '## Reproduction', '## Cause', '## Remediation', '## Evidence'];
const failures = [];
for (const state of ['inbox', 'promoted']) {
const directory = path.join(base, state);
for (const name of await readdir(directory)) {
if (!name.endsWith('.md')) continue;
const file = path.join(directory, name);
const source = await readFile(file, 'utf8');
const frontmatter = source.match(/^---\n([\s\S]*?)\n---/);
if (!frontmatter) { failures.push(`${file}: missing YAML frontmatter`); continue; }
const fields = Object.fromEntries(frontmatter[1].split('\n').map((line) => {
const index = line.indexOf(':');
return index === -1 ? [line, ''] : [line.slice(0, index).trim(), line.slice(index + 1).trim()];
}));
for (const key of ['id', 'date', 'status', 'scope', 'evidence', 'review_after']) {
if (!fields[key]) failures.push(`${file}: missing ${key}`);
}
if (fields.status !== state) failures.push(`${file}: status must be ${state}`);
if (state === 'promoted' && !fields.destination) failures.push(`${file}: promoted lesson needs destination`);
for (const section of requiredSections) if (!source.includes(section)) failures.push(`${file}: missing ${section}`);
}
}
if (failures.length) {
console.error(`Learning record failures:\n${failures.join('\n')}`);
process.exit(1);
}
console.log('Learning records are valid');
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROFILE="${1:?usage: with-local-supabase-env.sh <web|admin|mobile|mcp|tests> <command...>}"
shift
[ "$#" -gt 0 ] || { echo "command is required" >&2; exit 2; }
STATUS_ENV="$(cd "$ROOT" && npx supabase status --workdir apps -o env 2>/dev/null)" || {
echo "Local Supabase is not running. Run scripts/dev-local.sh up." >&2
exit 1
}
eval "$STATUS_ENV"
case "${API_URL:-}" in
http://127.0.0.1:*|http://localhost:*) ;;
*) echo "Refusing non-local Supabase URL: ${API_URL:-unset}" >&2; exit 1 ;;
esac
case "$PROFILE" in
web)
exec env NEXT_PUBLIC_SUPABASE_URL="$API_URL" "$@"
;;
admin)
exec env VITE_SUPABASE_URL="$API_URL" VITE_SUPABASE_ANON_KEY="$ANON_KEY" "$@"
;;
mobile)
exec env EXPO_PUBLIC_SUPABASE_URL="$API_URL" EXPO_PUBLIC_SUPABASE_ANON_KEY="$ANON_KEY" "$@"
;;
mcp)
exec env PORT=3002 SUPABASE_URL="$API_URL" \
SUPABASE_SERVICE_ROLE_KEY="$SERVICE_ROLE_KEY" \
SAUCI_MCP_API_KEY="local-sauci-mcp-only" "$@"
;;
tests)
exec env SUPABASE_URL="$API_URL" SUPABASE_ANON_KEY="$ANON_KEY" \
SUPABASE_SERVICE_ROLE_KEY="$SERVICE_ROLE_KEY" "$@"
;;
*) echo "unknown profile: $PROFILE" >&2; exit 2 ;;
esac