mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
5d61bf8a3f
Fixes the three gremlins observed 2026-07-18 (bead age-gate-scripts-worktree-gitdir-p62wo): 1. **Gate scripts broke under hook env from linked worktrees** (#919 regression): new scripts/lib/repo-root.sh (GIT_*-scrubbed resolution, BASH_SOURCE anchor, worktree-correct) swept across 32 scripts. Proof: this PR's own push ran the pre-push gates from a linked worktree and passed. 2. **core.bare=true recurrence**: mechanism proven (leaked GIT_DIR + no-arg git init --bare rewrites the SHARED config); writer traced with high confidence to a live Gas City city process (concrete suspect: gascity cmd_rig_test.go runGitInTest, unscrubbed env + no-arg init --bare — fork-side fix filed separately). Defense: new always.git-config-hygiene gate fails fast on core.bare/test identities with the repair command inline (--self-test proves fail-closed). 3. **Test/test@test.com identity leak**: writer convicted — our own pre-push chain leaked GIT_DIR into go test, whose helpers wrote the shared config via git -C (mechanism proven). Cut at both ends: validate-go-fast scrubs env for children; every test git-helper set-site scrubs; check-test-isolation gains a WARN-ratchet rule (baseline 3 → FAIL at 0). Gates: shellcheck rc=0 across 36 scripts; go build/vet clean; 655+379+149 tests; hygiene self-test; both originally-failing validators pass under the repro env.
114 lines
3.8 KiB
Bash
Executable File
114 lines
3.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# export-evidence.sh — promote a .agents/ artifact to docs/evidence/<bead-id>/
|
|
# so public docs can cite it (.agents/ is gitignored; public claims cannot
|
|
# rely on it). See docs/contracts/pmf-evidence.md.
|
|
#
|
|
# Provenance footer is appended to the promoted file: source path, SHA-256,
|
|
# UTC promotion date, bead-id. The footer makes "is this still the same
|
|
# evidence?" mechanically checkable.
|
|
#
|
|
# Usage:
|
|
# scripts/export-evidence.sh <bead-id> <source-path> [<dest-name>]
|
|
# scripts/export-evidence.sh soc-vuu6.33 .agents/research/ablation.md
|
|
# scripts/export-evidence.sh soc-vuu6.33 .agents/research/ablation.md headline.md
|
|
#
|
|
# Exit codes:
|
|
# 0 — promoted (or already up-to-date)
|
|
# 1 — drift: a docs/evidence/<bead-id>/<dest> already exists with a
|
|
# different source hash (manual review required)
|
|
# 2 — usage error
|
|
# 3 — source missing or unreadable
|
|
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'
|
|
exit "${1:-0}"
|
|
}
|
|
|
|
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
|
|
echo "export-evidence: bad arg count" >&2
|
|
usage 2
|
|
fi
|
|
|
|
BEAD_ID="$1"
|
|
SRC="$2"
|
|
DEST_NAME="${3:-$(basename "$SRC")}"
|
|
|
|
# Validate bead id shape (soc-xyz123 or soc-xyz.1.2 etc).
|
|
if ! printf '%s' "$BEAD_ID" | grep -qE '^[a-z]{2,6}-[0-9a-z.]+$'; then
|
|
echo "export-evidence: bead id '$BEAD_ID' does not match ^[a-z]{2,6}-[0-9a-z.]+$" >&2
|
|
exit 2
|
|
fi
|
|
|
|
if [ ! -r "$SRC" ]; then
|
|
echo "export-evidence: source not readable: $SRC" >&2
|
|
exit 3
|
|
fi
|
|
|
|
# shellcheck disable=SC1007,SC1091
|
|
. "$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/repo-root.sh"
|
|
ROOT="$(resolve_repo_root)"
|
|
DEST_DIR="$ROOT/docs/evidence/$BEAD_ID"
|
|
DEST_PATH="$DEST_DIR/$DEST_NAME"
|
|
mkdir -p "$DEST_DIR"
|
|
|
|
# Compute source SHA-256 (portable: sha256sum on linux, shasum -a 256 on mac).
|
|
src_hash() {
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
sha256sum "$1" | awk '{print $1}'
|
|
else
|
|
shasum -a 256 "$1" | awk '{print $1}'
|
|
fi
|
|
}
|
|
|
|
SRC_HASH="$(src_hash "$SRC")"
|
|
|
|
# If the destination already exists, check for drift before overwriting. We
|
|
# treat the destination's existing provenance footer (or its absence) as the
|
|
# baseline and refuse to silently replace evidence that came from a different
|
|
# source hash. Operator must remove the file and re-promote intentionally.
|
|
if [ -f "$DEST_PATH" ]; then
|
|
existing_hash="$(grep -oE 'source-sha256: [0-9a-f]{64}' "$DEST_PATH" | awk '{print $2}' | head -1 || true)"
|
|
if [ -n "$existing_hash" ] && [ "$existing_hash" != "$SRC_HASH" ]; then
|
|
echo "export-evidence: DRIFT — $DEST_PATH was promoted from a different source." >&2
|
|
echo " existing source-sha256: $existing_hash" >&2
|
|
echo " current source-sha256: $SRC_HASH" >&2
|
|
echo " Remove the file and re-run to confirm the new evidence is intentional." >&2
|
|
exit 1
|
|
fi
|
|
if [ -n "$existing_hash" ] && [ "$existing_hash" = "$SRC_HASH" ]; then
|
|
echo "export-evidence: $DEST_PATH already up-to-date"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Copy the source verbatim, then append the provenance footer. We use cp
|
|
# (preserves nothing extra) and then atomic-write via mv so partial files
|
|
# don't leave a half-promoted artifact.
|
|
TMP="$(mktemp)"
|
|
trap 'rm -f "$TMP"' EXIT
|
|
cp "$SRC" "$TMP"
|
|
{
|
|
# Newlines + horizontal rule + provenance comment. `printf '%s\n' '---'`
|
|
# avoids printf treating '---' as a flag, which happens when '---' appears
|
|
# at the start of a format string (e.g. `printf '\n---\n'`).
|
|
printf '\n\n'
|
|
printf '%s\n' '---'
|
|
printf '\n%s\n' '<!--'
|
|
printf 'provenance:\n'
|
|
printf ' source-path: %s\n' "$SRC"
|
|
printf ' source-sha256: %s\n' "$SRC_HASH"
|
|
printf ' promoted-at: %s\n' "$(date -u +%FT%TZ)"
|
|
printf ' bead-id: %s\n' "$BEAD_ID"
|
|
printf ' promoter: scripts/export-evidence.sh\n'
|
|
printf '%s\n' '-->'
|
|
} >> "$TMP"
|
|
mv "$TMP" "$DEST_PATH"
|
|
trap - EXIT
|
|
|
|
echo "export-evidence: wrote $DEST_PATH"
|
|
echo " source: $SRC"
|
|
echo " bead: $BEAD_ID"
|
|
echo " sha256: $SRC_HASH"
|