diff --git a/deploy/vm101/n8n-pi-wrap b/deploy/vm101/n8n-pi-wrap index 2f79cf1..84fccda 100755 --- a/deploy/vm101/n8n-pi-wrap +++ b/deploy/vm101/n8n-pi-wrap @@ -42,20 +42,25 @@ case "$cmd" in esac logger -t n8n-pi-wrap "ok: pi ingest ${genome} ${raw_path}" + + # Per-genome lock: serialize writes; never two concurrent ingests on the same genome. + exec 9>"/run/lock/kg-ingest-${genome}.lock" 2>/dev/null || exec 9>"/tmp/kg-ingest-${genome}.lock" + if ! flock -n 9; then + echo '{"status":"busy","reason":"another ingest is running for this genome","genome":"'"$genome"'"}' + exit 0 + fi + set -a; . "${HOME}/.config/knowledge-genome.env"; set +a cd "${GENOMES_ROOT}/${genome}" || { echo '{"status":"error","reason":"unknown genome"}'; exit 1; } # The raw file must actually exist under the genome's raw/ dir. [ -f "$raw_path" ] || { echo '{"status":"error","reason":"raw file not found"}'; exit 1; } - # Clean start on the configured base (develop), pinned to the remote. Destroys only - # vm101's scratch checkout (never a shared branch, never a force-push) — this is by design. - # `clean -fd` also removes leftover UNTRACKED files (e.g. wiki/sources/* or a stale - # .ingest-manifest.json from a half-finished previous run) that `reset --hard` won't touch. - git fetch -q origin \ - && git switch -q "${INGEST_BASE:-main}" 2>/dev/null \ - && git reset -q --hard "origin/${INGEST_BASE:-main}" \ - && git clean -q -fd + # Clean start on the configured base (single source of truth in lib/clean-start.sh). + : "${KG_LIB_DIR:=${HOME}/knowledge-genome-orchestrator/lib}" + source "${KG_LIB_DIR}/clean-start.sh" 2>/dev/null \ + || { echo '{"status":"error","reason":"clean-start.sh not found"}'; exit 1; } + clean_start || { echo '{"status":"error","reason":"clean-start failed"}'; exit 1; } # SEMANTIC step: dedicated script drives pi to WRITE wiki pages + manifest. # (NOT `pi -p "/skill:ingest ..."`, which makes the model reply in chat and write nothing.) diff --git a/skills/ingest/scripts/pending-raw.sh b/skills/ingest/scripts/pending-raw.sh index 0bd1a21..f82ce3d 100755 --- a/skills/ingest/scripts/pending-raw.sh +++ b/skills/ingest/scripts/pending-raw.sh @@ -12,11 +12,11 @@ genome="${1:?usage: pending-raw.sh }" base_dir="${GENOMES_ROOT:-${HOME}/genomes}" cd "${base_dir}/${genome}" 2>/dev/null || { echo '{"status":"error","reason":"unknown genome"}'; exit 1; } -# Clean start on the configured base (Step 3 will extract this to lib/clean-start.sh). -git fetch -q origin \ - && git switch -q "${INGEST_BASE:-main}" 2>/dev/null \ - && git reset -q --hard "origin/${INGEST_BASE:-main}" \ - && git clean -q -fd +# Clean start on the configured base (single source of truth in lib/clean-start.sh). +: "${KG_LIB_DIR:=${HOME}/knowledge-genome-orchestrator/lib}" +source "${KG_LIB_DIR}/clean-start.sh" 2>/dev/null \ + || { echo '{"status":"error","reason":"clean-start.sh not found"}'; exit 1; } +clean_start || { echo '{"status":"error","reason":"clean-start failed"}'; exit 1; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SLUG="${SCRIPT_DIR}/slug.sh" diff --git a/tests/pending-raw.bats b/tests/pending-raw.bats index f43237f..f0f8407 100644 --- a/tests/pending-raw.bats +++ b/tests/pending-raw.bats @@ -5,6 +5,7 @@ setup() { export PENDING="${SKILL_SCRIPTS}/pending-raw.sh" export GENOMES_ROOT="${BATS_TEST_TMPDIR}" export INGEST_BASE="main" + export KG_LIB_DIR="${LIB_DIR}" g_src="$(make_fixture_genome)" export g_name="fixture-genome"