feat: casan chat optz

This commit is contained in:
thanhnv
2026-07-19 12:14:12 +07:00
parent 709b6cccd6
commit f462079435
16 changed files with 486 additions and 90 deletions
@@ -27,6 +27,19 @@ set -uo pipefail
# 4 opt-out refused (prod) · 2 usage error.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PYTHON_BIN="${CASAN_PYTHON_BIN:-}"
if [[ -z "$PYTHON_BIN" ]]; then
for candidate in /usr/bin/python3 python3 python; do
if command -v "$candidate" >/dev/null 2>&1 && "$candidate" --version >/dev/null 2>&1; then
PYTHON_BIN="$candidate"
break
fi
done
fi
if [[ -z "$PYTHON_BIN" ]]; then
echo "LOOP_RUNTIME_UNAVAILABLE: working Python 3 interpreter not found" >&2
exit 69
fi
GATE="$SCRIPT_DIR/loop-gate.py"
GOV="$SCRIPT_DIR/loop-governor.py"
CONV="$SCRIPT_DIR/loop-convergence.py"
@@ -76,7 +89,7 @@ if [[ "$GOVERNANCE" == "off" ]]; then
exit 4
fi
# An allowed opt-out is always audited (never silent).
PYTHONPATH="$SCRIPT_DIR" python3 - "$RUN_ID" "${CASAN_LOOP_OPTOUT_REASON:-dev-optout}" <<'PY'
PYTHONPATH="$SCRIPT_DIR" "$PYTHON_BIN" - "$RUN_ID" "${CASAN_LOOP_OPTOUT_REASON:-dev-optout}" <<'PY'
import sys, loop_common as lc
lc.append_audit({"kind": "loop_governance_optout", "run_id": sys.argv[1], "reason": sys.argv[2]})
PY
@@ -90,13 +103,13 @@ COST_ACC="0"
for (( step=1; step<=MAX_STEPS; step++ )); do
CUM_TOKENS=$(( CUM_TOKENS + TOKENS_PER_STEP ))
COST_ACC="$(python3 -c "print(round($COST_ACC + $COST_PER_STEP, 6))")"
COST_ACC="$("$PYTHON_BIN" -c "print(round($COST_ACC + $COST_PER_STEP, 6))")"
DECISION="CONTINUE"; VERDICT=""; PROGRESS="0"
if [[ "$GOVERNANCE" == "on" ]]; then
# 1) Governor: cumulative budget check (loop-breaker) BEFORE more work.
set +e
python3 "$GOV" check --run-id "$RUN_ID" --step "$step" \
"$PYTHON_BIN" "$GOV" check --run-id "$RUN_ID" --step "$step" \
--tokens "$CUM_TOKENS" --cost "$COST_ACC" "${prof_args[@]}" >/dev/null 2>&1
grc=$?
set -e 2>/dev/null || true
@@ -106,7 +119,7 @@ for (( step=1; step<=MAX_STEPS; step++ )); do
if [[ "$DECISION" == "CONTINUE" ]]; then
# 2) Gate: per-iteration verify contract.
set +e
GATE_OUT="$(python3 "$GATE" verify --run-id "$RUN_ID" --step "$step" \
GATE_OUT="$("$PYTHON_BIN" "$GATE" verify --run-id "$RUN_ID" --step "$step" \
--artifact "$ARTIFACT" ${CRIT:+--success-criteria "$CRIT"} "${prof_args[@]}" 2>/dev/null)"
set -e 2>/dev/null || true
VERDICT="$(printf '%s' "$GATE_OUT" | json_field verdict)"
@@ -121,10 +134,10 @@ for (( step=1; step<=MAX_STEPS; step++ )); do
# 3) Convergence: observe + verdict (no-progress / oscillation breaker).
if [[ "$DECISION" == "CONTINUE" ]]; then
AH="$(sha_of "$ARTIFACT")"; AH="${AH:0:16}"
python3 "$CONV" observe --run-id "$RUN_ID" --step "$step" \
"$PYTHON_BIN" "$CONV" observe --run-id "$RUN_ID" --step "$step" \
--action-hash "$AH" --progress "$PROGRESS" >/dev/null 2>&1
set +e
python3 "$CONV" verdict --run-id "$RUN_ID" "${prof_args[@]}" >/dev/null 2>&1
"$PYTHON_BIN" "$CONV" verdict --run-id "$RUN_ID" "${prof_args[@]}" >/dev/null 2>&1
cvrc=$?
set -e 2>/dev/null || true
if [[ "$cvrc" -eq 3 ]]; then FINAL="HALT"; DECISION="HALT"; RC=3; fi
@@ -136,7 +149,7 @@ for (( step=1; step<=MAX_STEPS; step++ )); do
fi
# 4) Trace: append the immutable iteration record.
python3 "$TRACE" record --run-id "$RUN_ID" --step "$step" \
"$PYTHON_BIN" "$TRACE" record --run-id "$RUN_ID" --step "$step" \
--intent "turn-$step" --action verify --tool loop-run \
${VERDICT:+--gate-verdict "$VERDICT"} --decision "$DECISION" --progress "$PROGRESS" \
--artifact "$ARTIFACT" ${CRIT:+--success-criteria "$CRIT"} \
@@ -144,7 +157,7 @@ for (( step=1; step<=MAX_STEPS; step++ )); do
# 5) Between-turn context compaction (17.21).
if [[ -n "$CONTEXT" && -f "$CONTEXT" ]]; then
python3 "$COMPRESS" --mode structural --input "$CONTEXT" \
"$PYTHON_BIN" "$COMPRESS" --mode structural --input "$CONTEXT" \
> "$(dirname "$ARTIFACT")/.loop-context-compacted.txt" 2>/dev/null || true
fi