-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Description
Consolidate developer-specific configuration (handsoff, supervisor, Telegram, server runtime) into .agentize.local.yaml, making docs YAML-first while preserving env-var overrides for compatibility. This addresses roadmap items P2.4 (Configurable Permission Rules) and P2.8 (Multi-Repository Support) from issue #598.
Problem: Configuration is scattered across 28+ environment variables documented in docs/envvar.md, making it difficult to manage developer-specific settings consistently.
Solution: Extend the existing .agentize.local.yaml infrastructure to support handsoff and Telegram settings, with environment variables remaining as overrides for backward compatibility.
Proposed Solution
Consensus Summary
Adopt a YAML-first, minimal-dependency approach by extending the existing .agentize.local.yaml loader and wiring it into the Python server and Claude plugin hooks, while keeping environment variables as overrides for backward compatibility.
YAML Schema Specification
Complete .agentize.local.yaml Structure
# =============================================================================
# .agentize.local.yaml - Developer-specific local configuration
# =============================================================================
# This file is gitignored and contains secrets/personal preferences.
# Environment variables can override any setting (higher precedence).
# =============================================================================
# -----------------------------------------------------------------------------
# Handsoff Mode - Automatic workflow continuation
# -----------------------------------------------------------------------------
handsoff:
enabled: true # HANDSOFF_MODE (default: true)
max_continuations: 10 # HANDSOFF_MAX_CONTINUATIONS (default: 10)
auto_permission: true # HANDSOFF_AUTO_PERMISSION (default: true)
debug: false # HANDSOFF_DEBUG (default: false)
supervisor:
provider: claude # HANDSOFF_SUPERVISOR (default: none)
model: opus # HANDSOFF_SUPERVISOR_MODEL (default: provider-specific)
flags: "--timeout 1800" # HANDSOFF_SUPERVISOR_FLAGS (default: "")
# -----------------------------------------------------------------------------
# Telegram Approval - Remote approval via Telegram bot
# -----------------------------------------------------------------------------
telegram:
enabled: false # AGENTIZE_USE_TG (default: false)
token: "123456:ABC-DEF..." # TG_API_TOKEN (required when enabled)
chat_id: "-1001234567890" # TG_CHAT_ID (required when enabled)
timeout_sec: 60 # TG_APPROVAL_TIMEOUT_SEC (default: 60, max: 7200)
poll_interval_sec: 5 # TG_POLL_INTERVAL_SEC (default: 5)
allowed_user_ids: "123,456,789" # TG_ALLOWED_USER_IDS (CSV string, optional)
# -----------------------------------------------------------------------------
# Server Runtime - lol serve configuration
# -----------------------------------------------------------------------------
server:
period: 5m # Polling interval (default: 5m)
num_workers: 5 # Worker pool size (default: 5)
# -----------------------------------------------------------------------------
# Workflow Model Assignments - Model selection per workflow type
# -----------------------------------------------------------------------------
workflows:
impl:
model: opus # Model for implementation workflows
refine:
model: sonnet # Model for refinement workflowsEnvironment Variable to YAML Mapping
| Environment Variable | YAML Path | Type | Default | Scope |
|---|---|---|---|---|
| Handsoff Mode | ||||
HANDSOFF_MODE |
handsoff.enabled |
bool | true |
YAML + env override |
HANDSOFF_MAX_CONTINUATIONS |
handsoff.max_continuations |
int | 10 |
YAML + env override |
HANDSOFF_AUTO_PERMISSION |
handsoff.auto_permission |
bool | true |
YAML + env override |
HANDSOFF_DEBUG |
handsoff.debug |
bool | false |
YAML + env override |
HANDSOFF_SUPERVISOR |
handsoff.supervisor.provider |
string | none |
YAML + env override |
HANDSOFF_SUPERVISOR_MODEL |
handsoff.supervisor.model |
string | provider-specific | YAML + env override |
HANDSOFF_SUPERVISOR_FLAGS |
handsoff.supervisor.flags |
string | "" |
YAML + env override |
| Telegram Approval | ||||
AGENTIZE_USE_TG |
telegram.enabled |
bool | false |
YAML + env override |
TG_API_TOKEN |
telegram.token |
string | - | YAML + env override |
TG_CHAT_ID |
telegram.chat_id |
string | - | YAML + env override |
TG_APPROVAL_TIMEOUT_SEC |
telegram.timeout_sec |
int | 60 |
YAML + env override |
TG_POLL_INTERVAL_SEC |
telegram.poll_interval_sec |
int | 5 |
YAML + env override |
TG_ALLOWED_USER_IDS |
telegram.allowed_user_ids |
CSV string | - | YAML + env override |
| Server Runtime | ||||
| (CLI only) | server.period |
string | 5m |
YAML only |
| (CLI only) | server.num_workers |
int | 5 |
YAML only |
| Env-Only Variables (not in YAML) | ||||
AGENTIZE_HOME |
- | path | - | env-only (setup.sh) |
PYTHONPATH |
- | path | - | env-only (setup.sh) |
WT_DEFAULT_BRANCH |
- | string | main |
env-only (shell scripts) |
WT_CURRENT_WORKTREE |
- | path | - | env-only (auto-set) |
TEST_SHELLS |
- | string | - | env-only (test suite) |
Precedence Order (highest to lowest)
1. CLI arguments (e.g., --tg-token)
2. Environment variables (e.g., TG_API_TOKEN)
3. .agentize.local.yaml
4. Default values
Type Coercion Rules
| Type | Accepted Values | Example |
|---|---|---|
bool |
true, false, 1, 0, on, off, enable, disable |
enabled: true or enabled: 1 |
int |
Numeric strings or integers | timeout_sec: 60 or timeout_sec: "60" |
CSV string |
Comma-separated values (parsed as list internally) | allowed_user_ids: "123,456,789" |
Note: The minimal YAML parser does not support native arrays. Use CSV strings for list fields like allowed_user_ids.
Goal
Consolidate developer-specific configuration (handsoff, supervisor, Telegram, server runtime) into .agentize.local.yaml, making docs YAML-first while preserving env-var overrides for compatibility.
Success criteria:
.agentize.local.yamlsupports handsoff, supervisor, and Telegram settings used by hooks and server, with env vars still overriding.docs/envvar.mdis updated to YAML-first guidance with a clear mapping and explicit env-only exceptions.- Existing behavior remains unchanged when
.agentize.local.yamlis absent.
Out of scope:
- Shell script migration for
HANDSOFF_*,TG_*,WT_*, orTEST_*. - YAML-based permission rule definitions (remain Python).
- Deep-merge semantics, array support, or external YAML dependencies.
- New CLI commands like
lol config show/validate.
Codebase Analysis
File changes:
| File | Level | Purpose |
|---|---|---|
docs/envvar.md |
major | Rewrite to YAML-first config reference with env override mapping |
docs/architecture/metadata.md |
minor | Clarify .agentize.local.yaml scope and precedence |
docs/feat/core/handsoff.md |
medium | Add YAML config section and precedence notes |
docs/feat/permissions/telegram.md |
medium | Add YAML config section and precedence notes |
docs/feat/server.md |
minor | Align runtime config section with YAML-first guidance |
python/agentize/server/runtime_config.md |
medium | Update schema to include handsoff and notes on CSV fields |
python/agentize/server/README.md |
minor | Align server config guidance with YAML-first approach |
.claude-plugin/hooks/pre-tool-use.md |
medium | Replace env-var-only guidance with YAML-first mapping |
.claude-plugin/hooks/README.md |
minor | Note YAML-based config for hooks |
.claude-plugin/lib/README.md |
minor | Document new local config helper |
.claude-plugin/lib/session_utils.md |
medium | Update handsoff enablement to YAML-first |
.claude-plugin/lib/permission/README.md |
minor | Add YAML config mention for Telegram |
.claude-plugin/lib/local_config.md (new) |
major | Document new local config interface (Est: 80 LOC) |
.agentize.local.example.yaml (new) |
major | Provide YAML template for developer setup (Est: 50 LOC) |
python/tests/README.md |
minor | Add new test file to test matrix |
python/agentize/server/runtime_config.py |
medium | Accept handsoff and metadata keys; add coercion helpers |
python/agentize/server/__main__.py |
medium | Apply .agentize.local.yaml for server defaults |
python/agentize/server/github.py |
medium | Use config-aware HANDSOFF_DEBUG helper |
.claude-plugin/lib/local_config.py (new) |
major | Load YAML, cache, and resolve env override |
.claude-plugin/lib/session_utils.py |
medium | Read handsoff enabled from YAML with env override |
.claude-plugin/lib/logger.py |
minor | Read handsoff.debug from YAML with env override |
.claude-plugin/lib/permission/determine.py |
medium | Read Telegram and auto-permission from YAML |
.claude-plugin/lib/workflow.py |
medium | Read supervisor config from YAML |
.claude-plugin/hooks/stop.py |
minor | Read max continuations from YAML |
python/tests/test_runtime_config.py |
medium | Add handsoff schema and coercion tests |
python/tests/test_local_config.py (new) |
major | Tests for YAML lookup and env override (Est: 120 LOC) |
Interface Design
New interfaces:
lib/local_config.pyload_local_config(start_dir: Path | None = None) -> tuple[dict, Path | None]— Parse.agentize.local.yamlby walking parent directories.get_local_value(path: str, env: str | None, default: Any, coerce: Callable | None = None) -> Any— Resolve YAML value by dotted path, apply env override, optional coercion.coerce_bool(value: Any, default: bool) -> bool— Accept1/0/true/false/on/off/enable/disable.coerce_int(value: Any, default: int) -> int— Handle numeric strings and ints.coerce_csv_ints(value: Any) -> list[int]— Parse comma-separated user IDs.
Modified interfaces:
python/agentize/server/runtime_config.pytop-level key whitelist expands:
- VALID_TOP_LEVEL_KEYS = {"server", "telegram", "workflows"}
+ VALID_TOP_LEVEL_KEYS = {"server", "telegram", "workflows", "handsoff", "project", "git", "agentize", "worktree", "pre_commit"}Test Strategy
Test modifications:
python/tests/test_runtime_config.py— add cases forhandsoffsection parsing and key whitelist expansion.python/tests/test_runtime_config.py— add tests for boolean coercion helper behavior.python/tests/test_local_config.py(new) — YAML lookup by dotted path and env override precedence.python/tests/test_local_config.py(new) — CSV parsing fortelegram.allowed_user_ids.
Test data required:
- Temporary
.agentize.local.yamlfixtures withhandsoff,telegram, andserversections. - CSV string fixture for
telegram.allowed_user_ids.
Implementation Steps
Step 1: Update documentation and sample config (Estimated: 260 LOC)
- Update all docs to YAML-first guidance
- Create
.agentize.local.example.yamltemplate - Dependencies: None
Step 2: Add/extend tests for YAML config and precedence (Estimated: 200 LOC)
- Add tests for
handsoffparsing and key whitelist - Create
test_local_config.pyfor YAML lookup, env override, and CSV parsing - Dependencies: Step 1
Step 3: Extend runtime config parser (Estimated: 90 LOC)
- Expand
VALID_TOP_LEVEL_KEYSto includehandsoffand metadata keys - Add coercion helpers (bool/int/CSV)
- Dependencies: Step 2
Step 4: Add local config helper and wire Claude plugin modules (Estimated: 260 LOC)
- Create
.claude-plugin/lib/local_config.pywith YAML loader, caching, env override - Update
session_utils.py,logger.py,determine.py,workflow.py,stop.py - Dependencies: Step 2
Step 5: Wire server entrypoint to YAML defaults (Estimated: 140 LOC)
- Update
__main__.pyto load.agentize.local.yamland apply defaults - Update
github.pyto use config-awareHANDSOFF_DEBUGhelper - Dependencies: Step 2
Total estimated complexity: 950 LOC (Large)
Recommended approach: Milestone commits
Milestone strategy:
- M1: Complete docs + example file + tests (Steps 1–2)
- M2: Runtime config and local_config implementation (Steps 3–4)
- Delivery: Server wiring + test pass (Step 5)
Risks and Mitigations
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Minimal YAML parser lacks arrays | H | M | Document CSV for allowed_user_ids; keep parser minimal |
| Scope creep into shell scripts | M | H | Explicitly keep shell env vars out of scope and documented as env-only |
| Backward compatibility regressions | M | H | Env overrides remain, add tests for precedence |
| Duplicate config loaders | M | M | Keep local_config small and documented; consider consolidation later |
Dependencies
No new external dependencies; continue using the existing minimal YAML parser.
Related PR
TBD - will be updated when PR is created