diff --git a/known-issues.md b/known-issues.md new file mode 100644 index 0000000..370941b --- /dev/null +++ b/known-issues.md @@ -0,0 +1,141 @@ +# Known Issues — claude-code Workspace Template + +This document tracks unresolved and partially-resolved issues that are known to occur when +running this workspace template. Each entry includes the symptom, affected versions, +workaround, and (where applicable) a link to the upstream or internal tracker. + +--- + +## 1. `CLAUDE_CODE_OAUTH_TOKEN` Missing Causes Silent Auth Failures + +**Severity:** High +**Affects:** All template versions. + +**Symptom:** +The agent starts but immediately fails to call the LLM with: + +``` +anthropic.AuthenticationError: Incorrect API key provided +``` + +or, in platform-managed environments: + +``` +401 Unauthorized — Bearer token invalid or expired +``` + +**Root cause:** +`config.yaml` requires `CLAUDE_CODE_OAUTH_TOKEN` but the adapter has no API-key +fallback. If the environment variable is unset, empty, or expired, the LLM client +uses an empty/bogus credential and the first turn fails. + +**Workaround:** +Set the token before starting the adapter: + +```bash +export CLAUDE_CODE_OAUTH_TOKEN="your-oauth-token-here" +python adapter.py +``` + +For platform-managed workspaces, ensure the token is injected via the workspace +environment configuration in the Molecule platform dashboard. + +**Fix:** The adapter should emit a startup warning if `CLAUDE_CODE_OAUTH_TOKEN` is +empty or absent. Tracked in internal ticket MOL-XXXX. + +--- + +## 2. HEARTBEAT Not Emitted — Platform Shows "Silent" Status + +**Severity:** Medium +**Affects:** All template versions prior to explicit HEARTBEAT wiring. + +**Symptom:** +The Molecule platform activity dashboard shows the workspace as "silent" even +though the agent is actively processing tasks. No heartbeat events arrive at the +platform. The platform may timeout the workspace as inactive. + +**Root cause:** +The `entrypoint.sh` launches the adapter but does not configure a HEARTBEAT +interval. The platform relies on periodic POSTs to `/api/v1/heartbeat` to confirm +liveness. Without this, long-running agent tasks (> ~60s) may trigger platform +timeouts. + +**Workaround:** +Set `HEARTBEAT_INTERVAL_SECONDS` in the environment (if supported by the adapter): + +```bash +export HEARTBEAT_INTERVAL_SECONDS=30 +python adapter.py +``` + +Or, if the adapter does not support this env var, keep agent tasks short (< 60s) +or use `delegate_task_async` to return control immediately. + +**Fix:** The adapter should emit a HEARTBEAT event every 30 seconds when running +in platform mode. A future template update will add explicit HEARTBEAT wiring. + +--- + +## 3. `system-prompt.md` Customisations Overwritten on Template Update + +**Severity:** Medium +**Affects:** Users who customise `system-prompt.md` directly in the workspace. + +**Symptom:** +After pulling a new template version (e.g. `git pull` in a persistent workspace), +the agent's behaviour changes unexpectedly even though `config.yaml` was not +modified. On inspection, `system-prompt.md` has been overwritten with the +template's canonical version. + +**Root cause:** +`system-prompt.md` is a template-managed file. When the platform rebuilds or +refreshes the workspace container it copies files from the registered template +tag, overwriting any local customisations. + +**Workaround — Option A (recommended):** +Do not edit `system-prompt.md` directly. If the platform supports an override +mechanism, use `MOLECULE_SYSTEM_PROMPT_OVERRIDE` environment variable or the +`system_prompt_override` field in `config.yaml` (platform v1.2+). + +**Workaround — Option B:** +Fork the template and pin to a specific tag. Apply your customisations as patches +on top of that tag. + +--- + +## 4. `template_schema_version` Drift After Platform Upgrade + +**Severity:** High +**Affects:** Any workspace pinned to a schema version below the platform minimum +after a platform upgrade. + +**Symptom:** +The adapter fails to start with: + +``` +ValidationError: template schema version '1' is not supported. +Minimum supported version: '2'. Please update config.yaml. +``` + +**Root cause:** +The Molecule platform increments the minimum supported `template_schema_version` +when it makes backward-incompatible changes to the config format. Workspaces that +pin an older schema version will fail validation immediately. + +**Workaround:** +After a platform upgrade, edit `config.yaml` and update the +`template_schema_version` field to the new minimum reported in the platform's +release notes: + +```yaml +template_schema_version: 2 # change from 1 to 2 +``` + +**Prevention:** +Check the platform release notes before updating the platform. The release +checklist in `CLAUDE.md` includes a step to review the platform's minimum +schema version before tagging a new template release. + +**Fix:** Once `template_schema_version` is updated, the adapter starts normally. +No adapter code changes are required for schema-only bumps. diff --git a/runbooks/local-dev-setup.md b/runbooks/local-dev-setup.md new file mode 100644 index 0000000..d1e9dd2 --- /dev/null +++ b/runbooks/local-dev-setup.md @@ -0,0 +1,220 @@ +# Runbook: Local Development Setup — claude-code Workspace Template + +Use this runbook to set up a local development environment for the claude-code +workspace template. It covers cloning, dependency installation, running the adapter +outside Docker, overriding config for dev, building the container, and diagnosing +common problems. + +--- + +## Prerequisites + +| Requirement | Version | Notes | +|---|---|---| +| Python | 3.11+ | 3.12 recommended | +| pip | 23+ | | +| Docker | 24+ | | +| Docker Compose | v2 (standalone or compose plugin) | | +| Git | 2.40+ | | +| `gh` CLI | 2.40+ | Required for agent autonomy features (git, gh operations) | +| Molecule platform access | Token with `workspace:dev` scope | | + +--- + +## Step 1 — Clone the Repository + +```bash +git clone https://github.com/Molecule-AI/molecule-ai-workspace-template-claude-code.git +cd molecule-ai-workspace-template-claude-code +``` + +Always branch off `main` for local development: + +```bash +git checkout -b feat/your-feature-name +``` + +--- + +## Step 2 — Install Dependencies + +```bash +pip install -r requirements.txt +``` + +If you encounter dependency conflicts with an existing virtual environment, create an +isolated one: + +```bash +python -m venv .venv +source .venv/bin/activate # Linux/macOS +# .\.venv\Scripts\Activate.ps1 # Windows PowerShell +pip install -r requirements.txt +``` + +Verify the adapter is importable: + +```bash +python -c "from adapter import MoleculeClaudeCodeAdapter; print('OK')" +``` + +--- + +## Step 3 — Configure Environment Variables + +The adapter requires `CLAUDE_CODE_OAUTH_TOKEN` to authenticate with the LLM. +There is no API-key fallback — this variable must be set. + +```bash +# Required — OAuth token for the LLM provider +export CLAUDE_CODE_OAUTH_TOKEN="your-oauth-token-here" + +# Platform URL (required for agent task polling) +export MOLECULE_PLATFORM_URL="https://platform.molecule.ai" + +# Workspace instance ID (assigned by the platform) +export MOLECULE_WORKSPACE_ID="ws-dev-local" + +# Optional — override adapter log level +export LOG_LEVEL=DEBUG + +# Optional — HEARTBEAT interval in seconds (prevents platform timeout on long tasks) +export HEARTBEAT_INTERVAL_SECONDS=30 +``` + +> **Security note:** Never commit `.env.local` to version control. Create a +> `.env.local` file and ensure it is listed in `.gitignore`. + +--- + +## Step 4 — Dev Overrides in `config.yaml` + +The `config.yaml` shipped in the repo is production-oriented. For local dev, +the recommended approach is to pass environment-variable overrides. Alternatively, +create `config.dev.yaml` that the adapter merges on top of `config.yaml`: + +```yaml +# config.dev.yaml — local development overrides +runtime_config: + model: sonnet + timeout: 300 # shorter timeout for faster dev cycles +``` + +Apply dev overrides when running locally: + +```bash +python adapter.py --config config.yaml --config-override config.dev.yaml +``` + +If the adapter does not support `--config-override`, set `MOLECULE_CONFIG_OVERLAY` +to the path of the dev config file. + +--- + +## Step 5 — Run the Adapter Locally + +Start the adapter in foreground mode: + +```bash +python adapter.py +``` + +Expected startup output: + +``` +[molecule.adapter] INFO — resolved config template_schema_version=1 +[molecule.adapter] INFO — runtime: claude-code, model: sonnet +[molecule.adapter] INFO — OAuth token: present +[molecule.adapter] INFO — workspace ready, polling https://platform.molecule.ai/api/v1/tasks +``` + +Press `Ctrl+C` to stop. For background operation: + +```bash +nohup python adapter.py > adapter.log 2>&1 & +echo $! > adapter.pid +``` + +Stop with: + +```bash +kill $(cat adapter.pid) +``` + +--- + +## Step 6 — Test the Docker Build + +Build the dev image: + +```bash +docker build \ + --build-arg BUILDKIT_INLINE_CACHE=1 \ + -t molecule-claude-code-workspace:dev \ + . +``` + +Run a smoke test (adapter starts and reaches idle state): + +```bash +docker run --rm \ + --env CLAUDE_CODE_OAUTH_TOKEN \ + --env MOLECULE_PLATFORM_URL \ + --env MOLECULE_WORKSPACE_ID \ + molecule-claude-code-workspace:dev \ + python -c " +from adapter import MoleculeClaudeCodeAdapter +a = MoleculeClaudeCodeAdapter() +a.load_config() +print('smoke test PASSED') +" +``` + +Full Docker Compose stack: + +```bash +docker compose up --build +``` + +Logs: + +```bash +docker compose logs -f workspace +``` + +Teardown: + +```bash +docker compose down -v +``` + +--- + +## Common Issues Table + +| Symptom | Likely Cause | Resolution | +|---|---|---| +| `401 Unauthorized — Bearer token invalid` | `CLAUDE_CODE_OAUTH_TOKEN` unset or expired | Set a valid token: `export CLAUDE_CODE_OAUTH_TOKEN=...` | +| `anthropic.AuthenticationError` | Wrong token or token lacks required scopes | Verify token has `model:read` and `agent:invoke` scopes | +| Adapter starts but never receives tasks | Wrong `MOLECULE_PLATFORM_URL` or token expired | Check URL; refresh token | +| Platform shows "silent" after ~60s | No HEARTBEAT configured; platform timed out the workspace | Set `HEARTBEAT_INTERVAL_SECONDS=30`; upgrade adapter | +| `docker build` fails with `Step N/12: RUN pip install...` | Network / pip index issue | Proxy through corporate firewall or mirror: `pip install --index-url https://pypi.org/simple/ -r requirements.txt` | +| `docker run` exits immediately with code 0 | `CLAUDE_CODE_OAUTH_TOKEN` not set | Pass `-e CLAUDE_CODE_OAUTH_TOKEN` or `--env-file .env.local` | +| `ValidationError: template schema version '1' not supported` | Platform minimum schema version increased | Update `template_schema_version` in `config.yaml` to match platform minimum | + +--- + +## IDE Setup (VS Code) + +```json +// .vscode/settings.json — create in workspace root +{ + "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python", + "python.analysis.typeCheckingMode": "basic", + "files.insertFinalNewline": true, + "[python]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "charliermarsh.ruff" + } +} +```