--- id: REIN-OW-WP-0001 title: "Bootstrap: minimal open-weight agentic loop" status: proposed --- First working milestone for rein-openweights: prove an agentic tool-use loop against a current open-weight model via OpenRouter/llm-connect, comparable in scope to rein-aharness's `green-commit-only` profile, ready to implement the glas-harness rein contract once `glas-harness/GLAS-WP-0001-T01` defines it. ## Task: Pick the starter open-weight model + OpenRouter path Checked `llm-connect`'s existing OpenRouter integration (`OpenRouterAdapter.execute_prompt`): it takes a single prompt string, builds a fixed `[system, user]` message pair itself, and never surfaces `message.tool_calls` in its response — it cannot drive a multi-turn tool-calling loop without a breaking change to llm-connect's frozen Core `LLMAdapter` ABC. Decision: rein-openweights uses its own minimal OpenRouter client (`openrouter_client.py`) for the agentic loop instead; `tools`/`tool_choice` already pass through llm-connect's own `OPENAI_CHAT_PASSTHROUGH_FIELDS` allow-list, confirming the request shape is standard OpenAI-compatible function-calling, just not round-tripped by that adapter today. Starter model is a `--model`-configurable default (`meta-llama/llama-3.1-70b-instruct`), not hardcoded. ```task id: REIN-OW-WP-0001-T01 status: done priority: high ``` ## Task: Minimal agentic loop Implemented in `loop.py` + `tools.py`: plan → tool call → observe → repeat with a hard tool allow-list matching rein-aharness's `green-commit-only` (`read_file`/`write_file`/`edit_file`/`glob_files`/ `grep_files` + `git_status`/`git_diff`/`git_log`/`git_add_commit`, no push/network/shell), bounded by `max_turns` and a token budget. Budget tracker is vendored locally (`budget.py`), not `llm-connect`'s — consistent with T01/ADR-002 keeping llm-connect optional. Path-traversal guarded (`_resolve`); tool errors are reported back to the model as a `role: tool` message rather than crashing the loop. 26 tests, all mocked at the `httpx`/subprocess boundary. ```task id: REIN-OW-WP-0001-T02 status: done priority: high ``` ## Task: Success criterion + reporting Implemented in `runner.py`/`hub.py`: a local git commit is the sole success signal (`RunResult.ok == committed`), State Hub progress event (`executor_run`) and token event posted on completion via a hub module mirroring rein-aharness's, `--no-hub` to skip. Not yet exercised against a live State Hub call in this pass (mocked in tests) — same caveat as rein-aharness/glas-harness's own not-yet-live-run notes elsewhere in this rein family. ```task id: REIN-OW-WP-0001-T03 status: done priority: medium ``` ## Task: Credential brokering Resolved by glas-harness `docs/adr/ADR-002-credential-brokering-and-composable-reins.md` (Option B): rein-openweights acquires its own OpenRouter credential. Implemented in `credentials.py`, mirroring rein-aharness's mailscan.py OpenBao AppRole/ambient-token pattern (explicit env var → AppRole exchange → ambient token → single `kv get`). glas-harness does not broker this. ```task id: REIN-OW-WP-0001-T04 status: done priority: medium ``` ## Task: Forgejo repo creation This repo is local-only. Create `coulomb/rein-openweights.git` on Forgejo and wire the remote once T02 has something worth pushing — coordinate with the operator (repo creation is not something this session can do unattended). ```task id: REIN-OW-WP-0001-T05 status: todo priority: low ```