#!/bin/sh
# savi-note-gate savi-task-link:  two checks on an agent's commit message.
# The markers on the first comment line are how both installers recognise this
# hook as their own:  scripts/install_deploy_guard.sh puts it in the broker's
# repository, and services/git_hooks.py puts it, beside prepare-commit-msg, in
# every agent workspace that is a repository and every repository the
# installation knows its agents' work lands in.
#
# 1.  The task link (2026-10-26).  A commit that finishes a task closes it only
# when it carries "Closes: <task id>" (services/task_closes.py), and almost no
# agent commit did, so finished work landed while its task stayed open and the
# buyer had to ask whether it was done.  An agent commit now names at least one
# open task from that agent's queue in a Closes: or Refs: line (Refs: for
# partial work, which closes nothing).  The rule and its exemptions (a merge,
# a revert, a fixup or squash, a release cut, a rules release) live in
# services/commit_task_link.py, reached through `comms commit-check`.
#
# THIS CHECK FAILS OPEN.  Only the exit commit_task_link.REFUSED_EXIT (10)
# refuses.  No comms on PATH, an old comms with no such command, an unreadable
# queue, or any crash allows the commit with a warning on stderr, because a
# broken check must never stop anybody committing.
#
# 2.  The release note (2026-10-22).  128 commits landed on main after Release
# 2026.10.33 and not one carried a Whats-New or Roadmap trailer, so
# scripts/cut_release.py had nothing to cut and the version stood still for
# three days.  Every agent commit in the broker's repository carries one of
# three trailers, read by services/release_notes.py, the one classifier the
# push gate and the release cut read too:
#
#   Whats-New: <one sentence a buyer reads>
#   Roadmap: <roadmap item id this commit finishes>
#   Internal: <a sentence saying why a buyer never sees the change>
#
# A person's commit (no Agent trailer and no agent identity in the environment,
# read the way prepare-commit-msg reads it) is left alone by both checks.
#
# The owner's orders to commit without a check are
# SAVI_COMMS_TASK_LINK_OVERRIDE=1 and SAVI_COMMS_RELEASE_NOTE_OVERRIDE=1.
# Reverting this is deleting this file and its install lines.
msg_file="$1"
[ -n "$msg_file" ] && [ -f "$msg_file" ] || exit 0

# Who is committing:  an Agent trailer in the message, or an agent identity in
# the environment.  A person has neither, and nothing below runs for them.
agent_commit=""
grep -qi '^Agent:[[:space:]]' "$msg_file" && agent_commit=1
[ -n "$SAVI_AGENT_NAME" ] && agent_commit=1
if [ -z "$SAVI_COMMIT_AS_PERSON" ]; then
    [ -n "$SAVI_COMMS_TOKEN" ] && agent_commit=1
    [ -n "$CLAUDECODE" ] && agent_commit=1
fi

# ---- 1.  The task link -------------------------------------------------------
if [ -n "$agent_commit" ]; then
    if command -v comms >/dev/null 2>&1; then
        comms commit-check "$msg_file"
        rc=$?
        case "$rc" in
            0) ;;
            10) exit 1 ;;
            *) echo "task link:  warning:  comms commit-check could not run (exit $rc), so this commit was not checked for a task link.  It is allowed." >&2 ;;
        esac
    else
        echo "task link:  warning:  comms is not on PATH, so this commit was not checked for a task link.  It is allowed." >&2
    fi
fi

# ---- 2.  The release note (the broker's repository only) ---------------------
root=$(git rev-parse --show-toplevel 2>/dev/null)
mod="$root/services/release_notes.py"
if [ ! -f "$mod" ]; then
    # Not the broker repository:  there is no release-note rule to apply.  An
    # agent is told its commit is unchecked for one;  a person hears nothing.
    [ -n "$agent_commit" ] && echo "note gate:  $mod is not here, so this repository's commits are not checked for release notes" >&2
    exit 0
fi
if ! command -v python3 >/dev/null 2>&1; then
    [ -n "$SAVI_COMMS_RELEASE_NOTE_OVERRIDE" ] && exit 0
    echo "REFUSED:  python3 is not on PATH, so the release-note check cannot run and the commit is not checked.  Install python3, or set SAVI_COMMS_RELEASE_NOTE_OVERRIDE=1 to commit without the check." >&2
    exit 1
fi
python3 "$mod" "$msg_file" || exit $?
exit 0
