Commit 4bc7e872 authored by xuwang's avatar xuwang
Browse files

fix(agentic): make agents creates .agentic-logs and records loop launches



`make agents` (agent-start.sh) now mkdir -p's $OTICA_DIR/.agentic-logs (override
OTICA_LOG_DIR) and writes each role's launch record + any startup error to
<role>.log instead of /dev/null — same dir the cron tick path uses, already
gitignored. The live per-tick transcript of a --bg loop still lives in
`claude agents` (--bg detaches; no flag tees it to a file), so the file holds
launch records, not the full transcript — documented as such.

Also fixes stale docs that pointed log paths at ~/.otica: the runbook tail
command and the OTICA_LOG_DIR config row now read $OTICA_DIR/.agentic-logs, and
the supervised-mode section documents where logs land.

Changelog: fixed

Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parent cc222943
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -231,6 +231,11 @@ make agents # start the 3 loops in the background
make agents-view     # monitor (= claude agents); Ctrl+X stops a session
make agents-stop     # stop this repo's agent sessions
```
**Logs:** the live per-tick transcript of each background loop is in `claude agents`
(`make agents-view`). `make agents` also creates `$OTICA_DIR/.agentic-logs/` and
records each loop's **launch** (and any startup error) to `<role>.log` there — the
same dir the cron tick path writes to. `.agentic-logs/` is gitignored.

**Identity:** with bots provisioned (`make agentic-bots ARGS="provision-all"`) each
role is a distinct GitLab user → review + merge work. Without bots all run as
`~/.otica-token` (single identity: handles others' MRs; your own wait for a human).
@@ -270,7 +275,9 @@ The script handles cron's minimal `PATH` (it adds the newest `~/.nvm` node bin s
`claude` resolves — if your Node/claude lives elsewhere, set `OTICA_PATH`),
per-role identity, the maintainer handle, repo auto-detection, overlap locking
(PID-stamped, stale-reclaimed after `OTICA_LOCK_STALE_MIN`), a token pre-flight,
label-ensure, and per-role logs. Watch one with `tail -f ~/.otica/.agentic-logs/<role>.log`.
label-ensure, and per-role logs. Logs land in `$OTICA_DIR/.agentic-logs/` (the
clone you run from, **not** `~/.otica` — override with `OTICA_LOG_DIR`); watch one
with `tail -f "$OTICA_DIR/.agentic-logs/<role>.log"`.

The **reporter is intentionally not cron'd** — it's the human/external entry point.
Invoke a headless issue on demand (e.g. from a script, webhook, or alert handler):
@@ -399,7 +406,7 @@ override behavior; all are optional.
| `OTICA_AGENTIC_SETTINGS` | `agentic-<role>.settings.json` | cron tick | permission preset file |
| `OTICA_DIR` | `~/.otica` | tick, view | framework checkout location |
| `OTICA_TOKENS_DIR` | `~/.otica-tokens` | cron tick | per-role token directory |
| `OTICA_LOG_DIR` | `~/.otica/.agentic-logs` | cron tick | per-role log files |
| `OTICA_LOG_DIR` | `$OTICA_DIR/.agentic-logs` | tick + `make agents` | per-role log files (gitignored) |
| `OTICA_LOCK_DIR` | `$TMPDIR/otica-agentic` | tick, view | overlap lock directory |
| `OTICA_LOCK_STALE_MIN` | `120` | cron tick | minutes before a held lock is reclaimed |
| `OTICA_PATH` | newest nvm bin + std dirs | cron tick | `PATH` for cron (so `claude` resolves) |
+14 −4
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@ THIS_DIR=$(cd "$(dirname "$0")" && pwd)
OTICA_DIR="${OTICA_DIR:-$(cd "$THIS_DIR/.." && pwd)}"
TOKENS_DIR="${OTICA_TOKENS_DIR:-$HOME/.otica-tokens}"
SETTINGS_DIR="$OTICA_DIR/agent-instructions"
# Per-role logs live in the clone we run from (same convention as agent-tick.sh,
# override with OTICA_LOG_DIR). gitignored. `make agents` records each loop's
# launch here; the live per-tick transcript is in `claude agents` (make agents-view).
LOG_DIR="${OTICA_LOG_DIR:-$OTICA_DIR/.agentic-logs}"
mkdir -p "$LOG_DIR"
cd "$OTICA_DIR"

command -v claude >/dev/null 2>&1 || { echo "claude not on PATH" >&2; exit 1; }
@@ -38,23 +43,27 @@ fi
role_interval() { case "$1" in resolver) echo 15m;; reviewer) echo 20m;; integrator) echo 25m;; *) echo 20m;; esac; }

start_role() {
    local role="$1" iv settings tokfile idlabel
    local role="$1" iv settings tokfile idlabel log
    iv=$(role_interval "$role")
    settings="$SETTINGS_DIR/agentic-$role.settings.json"; [ -f "$settings" ] || settings="$SETTINGS_DIR/agentic.settings.json"
    tokfile="$TOKENS_DIR/$role.token"
    idlabel="default identity (~/.otica-token)"; [ -f "$tokfile" ] && idlabel="bot ($role.token)"
    log="$LOG_DIR/$role.log"
    # A looped background worker has no human to approve tool calls, so an allowlist
    # only ever DENIES (no prompt) and the agent stalls. We bypass the allowlist and
    # rely on the per-role `deny` list as the guardrail — `deny` is still enforced
    # under --dangerously-skip-permissions (settings files still apply).
    echo "$(date '+%F %T') [$role] make agents: launching /loop $iv (id=$idlabel, settings=$(basename "$settings"), bypass+deny)" >> "$log"
    (   # subshell so the per-role token export doesn't leak to the next role
        [ -f "$tokfile" ] && export OTICA_SERVER_TOKEN_FILE="$tokfile"
        # Capture the launch line + any startup error to the role log (not /dev/null).
        # The detached session's live transcript lives in `claude agents`, not here.
        claude --bg --name "agent-$role" \
            --dangerously-skip-permissions \
            --settings "$settings" \
            "/loop $iv /agent-$role" >/dev/null
            "/loop $iv /agent-$role" >> "$log" 2>&1
    )
    echo "  ✓ agent-$role — every $iv, $idlabel, bypass+deny"
    echo "  ✓ agent-$role — every $iv, $idlabel, bypass+deny (log: $log)"
}

# Warn if review/merge bots are missing (they'd then run as your default identity
@@ -68,7 +77,8 @@ for role in resolver reviewer integrator; do start_role "$role"; done
cat <<EOF

Three agents are now running in the background.
  Monitor:  make agents-view     (or: claude agents)
  Monitor:  make agents-view     (or: claude agents)   ← live per-tick transcript
  Logs:     $LOG_DIR/<role>.log   ← launch records (gitignored)
  Stop all: make agents-stop
Heads-up: the resolver does \`git switch\` in this checkout each fix — don't do
manual git work in $OTICA_DIR while they run (or start them from a dedicated clone).