Commit 2b261789 authored by xuwang's avatar xuwang
Browse files

feat(agentic): start agents via `claude --bg`; run from a dedicated clone; docs



- `make agents` now starts each loop as a background session (scripts/agent-start.sh,
  `claude --bg "/loop ..."`) — no TUI takeover, no manual dispatch. Replaces the
  agent-view launcher. Adds `make agents-view` (monitor) and `make agentic-bots-list`.
- Run from a DEDICATED clone, never ~/.otica (the shared install consumer projects
  check out per OTICA_VERSION): agent-start.sh refuses (confirm) and agent-tick.sh
  warns when launched there.
- De-hardwire ~/.otica: agent-tick.sh derives OTICA_DIR from the script's own clone;
  per-role settings use Read(/**) (project-root-relative) instead of Read(~/.otica/**).
- Docs: agentic workflow now documented in README.md and CLAUDE.md (were missing);
  runbook quickstart/supervised/cron updated for background sessions + dedicated clone.

Changelog: changed
Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parent 80de94d8
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -28,6 +28,13 @@ make release-preview # preview generated changelog (writes nothing)
make release-minor     # bump + cut a release (or release-patch/-major/ release VERSION=x.y.z)
```

Agentic workflow (see Agentic Workflow below, and agent-instructions/agentic-workflow.md):
```bash
make agentic-bots ARGS="provision-all"  # one-time: per-role GitLab bot identities
make agents            # start the resolver/reviewer/integrator loops (claude --bg)
make agents-view       # monitor (claude agents) ; make agents-stop to stop
```

## Architecture

### Makefile Modules (`makefiles/`)
@@ -76,6 +83,18 @@ The `MAKELEVEL` guard prevents re-running on recursive make calls. The checkout

`CHANGELOG.md` is generated from `Changelog:` git trailers (config in `.gitlab/changelog_config.yml`). Consumers pin a release via `OTICA_VERSION` and are nudged to upgrade by `otica-upgrade-check.sh` (release-tag-aware). See the [README](README.md) "Releases & Versioning" and [CONTRIBUTING.md](CONTRIBUTING.md).

### Agentic Workflow (developer)

A four-agent loop that drives the GitLab issue → fix → review → merge lifecycle, coordinating **only through GitLab scoped labels** (`kind::*`, `status::*`, `review::*`) — no shared state. Roles: **reporter** (file/classify issues), **resolver** (triage → claim → fix → MR, or answer & close how-to/question issues), **reviewer** (fan-out review → approve/changes), **integrator** (merge approved+green MRs to `main`). Each only acts on items in its inbound label state; claims are assign-then-reread (resolver via issue assignee, reviewer via MR reviewer) so multiple operators don't collide.

- **Roles** are slash commands in `.claude/commands/agent-{reporter,resolver,reviewer,integrator}.md`; helper subagents (`code-self-reviewer`, `mr-reviewer`) live in `.claude/agents/`.
- **Plumbing:** `scripts/gl-flow.sh` is the GitLab REST dispatcher (sources `gitlab.sh`); `agent-start.sh` (`make agents`) launches the loops as `claude --bg` background sessions; `agent-tick.sh` runs one headless tick (cron / `make agentic-tick`); `agent-stop.sh` (`make agents-stop`) stops them; `agent-bots.sh` (`make agentic-bots`) provisions per-role bot identities.
- **Identity:** authenticates with `OTICA_SERVER_TOKEN[_FILE]` (default `~/.otica-token`), the same knob as releases. GitLab forbids approving/merging your own MR, so reviewer/integrator need a **different** identity than the resolver — `make agentic-bots ARGS="provision-all"` creates per-role project-access-token bots in `~/.otica-tokens/<role>.token` (auto-selected by `agent-start.sh`/`agent-tick.sh`). Without bots everything runs as one identity (handles others' MRs; your own wait for a human).
- **Settings:** per-role least-privilege presets in `agent-instructions/agentic-*.settings.json` (passed via `--settings` for headless/background runs). `.claude/commands` and `.claude/agents` are tracked; `.claude/settings*.json` stay gitignored.
- **Run from a dedicated clone, NOT `~/.otica`.** `~/.otica` is the shared framework install that consumer projects check out to their pinned `OTICA_VERSION` on every build; the resolver's `git switch` there would corrupt that pinning. Clone OTICA elsewhere (e.g. `~/otica-agents`) and run `make agents` there — it refuses (asks to confirm) if launched from `~/.otica`, and `agent-tick.sh` logs a warning.

Full runbook: `agent-instructions/agentic-workflow.md`.

### Environment Config (`envs/`)

Template `env.mk` files for each cloud provider. Consumer projects copy the relevant one and populate values. Variables are exported to subshells via `export` in the consumer's top-level Makefile.
+11 −3
Original line number Diff line number Diff line
@@ -34,11 +34,15 @@ validate-scripts: ## detect *.sh referenced in recipes that don't exist in scrip
## Agentic workflow (operator) — see agent-instructions/agentic-workflow.md

.PHONY: agents
agents: ## supervise the agentic workflow loops in one terminal (claude agents)
	@scripts/agent-view.sh
agents: ## start the agent loops as background sessions (claude --bg), one per role
	@scripts/agent-start.sh

.PHONY: agents-view
agents-view: ## monitor the running background agents (claude agents)
	@claude agents

.PHONY: agents-stop
agents-stop: ## stop this repo's background agent sessions started by `claude agents`
agents-stop: ## stop this repo's background agent sessions
	@scripts/agent-stop.sh

.PHONY: agentic-tick
@@ -53,6 +57,10 @@ agentic-tick: ## run one headless workflow tick. make agentic-tick ROLE=<resolve
agentic-bots: ## manage per-role bot identities. make agentic-bots ARGS="provision-all|list|revoke-all|provision <role>|revoke <role>"
	@scripts/agent-bots.sh $(ARGS)

.PHONY: agentic-bots-list
agentic-bots-list: ## list provisioned per-role bot identities
	@scripts/agent-bots.sh list

# Labels self-heal: both `make agents` and each headless tick run gl-flow.sh
# labels-ensure. For a manual force re-create / re-sync use:
#   scripts/gl-flow.sh labels-init
+24 −0
Original line number Diff line number Diff line
@@ -1189,6 +1189,30 @@ full-deploy: az-login tf-render tf-plan tf-apply aca-allow-me ## Complete deploy
    @echo "Full deployment complete"
```

## Agentic Workflow (developer/maintainer)

OTICA ships an optional set of cooperating Claude agents that drive the GitLab
**issue → fix → review → merge** lifecycle, coordinating only through GitLab
scoped labels: **reporter** files/classifies issues, **resolver** triages and
fixes them (or answers how-to/question issues and closes them), **reviewer**
reviews the MR, and **integrator** merges approved, green MRs to `main`.

> **Run these from a dedicated OTICA clone, not `~/.otica`.** `~/.otica` is the
> shared install consumer projects check out to their pinned `OTICA_VERSION`; the
> resolver's branch switches would corrupt that. `git clone` OTICA elsewhere
> (e.g. `~/otica-agents`) and run there.

```bash
git clone git@code.stanford.edu:iac/cloud-framework.git ~/otica-agents && cd ~/otica-agents
make agentic-bots ARGS="provision-all"  # one-time: per-role GitLab bot identities
make agents                             # start the resolver/reviewer/integrator loops
make agents-view                        # monitor (claude agents)
make agents-stop                        # stop them
```

Full setup, deployment modes (background sessions vs. unattended cron), identity
model, and every knob: **[agent-instructions/agentic-workflow.md](agent-instructions/agentic-workflow.md)**.

## Contributing to OTICA

See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the full workflow: issues, module
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
      "Bash(git log:*)",
      "Bash(git show:*)",
      "Bash(git rev-parse:*)",
      "Read(~/.otica/**)"
      "Read(/**)"
    ],
    "deny": [
      "Bash(git push:*)",
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
  "permissions": {
    "allow": [
      "Bash(scripts/gl-flow.sh:*)",
      "Read(~/.otica/**)"
      "Read(/**)"
    ],
    "deny": [
      "Bash(git push:*)",
Loading