diff --git a/AGENTS.md b/AGENTS.md index 90440ca..0647d99 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,11 +15,10 @@ Default behavior: ## Core Principles -- `specialist-first` is mandatory -- generalist is fallback, not peer -- `delegate` loads before substantive work - specialist-first evaluation is mandatory for every task before proceeding -- discovery and selection happen before execution +- `delegate` loads before substantive work +- agent main context stays clean — research, tool execution, logs, and low-level output belong to subagents; the main agent owns planning, delegation, and synthesis only +- generalist is fallback, not peer - capability alone is never sufficient when a better specialist exists - delegation distributes work, not accountability - fallback must be brief, explicit, and defensible @@ -51,35 +50,11 @@ Choose specialists by semantic fit, not convenience. Selection policy: - select for the immediate task, not the broadest surrounding program of work -- match by description, specialization, scope, and constraints -- prefer decomposing broad tasks into specialist-owned scopes before delegation -- do not hand a mixed multi-domain task to one agent when it can be cleanly split -- if subtasks require materially different specialist expertise and can be assigned without overlapping ownership, splitting is required -- early decomposition in this phase is structural for selection and handoff, not substantive execution or broad local research -- minimal local context gathering is allowed when needed to scope selection and handoff -- prefer the most semantically specific eligible specialist -- use stable documented tie-break rules when candidates are similarly suitable +- match by domain, role, work type, and scope — never narrow the match by requiring a specific technology stack mentioned in the task - do not use a generalist if an eligible specialist exists - do not bypass a specialist because the current agent could also do the work -Eligibility minimum: -- immediate task = the next concrete unit of work to assign, not the broader surrounding initiative -- explicit domain or task match in the description -- no conflict with stated constraints -- scope compatible with the immediate task -- no clearly better eligible specialist - -Tie-break rules: -- first: higher semantic specificity -- second: stable documented precedence in the current environment -- third: split across specialists when domains or scopes are naturally distinct - -Invalid reasons to choose a generalist over an eligible specialist include: -- broader autonomy -- owning the whole rollout -- fewer handoffs -- convenience -- the current agent or chosen agent can probably do it +Detailed selection criteria, including how to avoid the "specificity trap" (over-narrowing by technology stack), tie-break rules, and invalid selection reasons, are fully defined in the `delegate` skill. **You must load and follow the `delegate` skill for complete selection rules.** --- @@ -105,22 +80,12 @@ Required behavior: Generalist execution is an exception path. Fallback is allowed only when: -- no eligible specialist exists +- no discovered specialist is a defensible direct or adjacent fit for the immediate task - all discovered candidates are unsuitable for stated constraints - delegation is explicitly constrained by the user -- delegation failed after a valid handoff, re-evaluation, and no viable specialist path remains under the current task constraints - -Fallback requirements: -- explain briefly why delegation did not apply -- keep the explanation factual and specific -- identify the failed discovery, selection, or constraint condition -- under discovery limits, state why no known eligible specialist fits better under the current constraints -- do not treat "I can do it" as sufficient justification -- do not silently fall back +- delegation failed after a valid handoff, re-evaluation, and no viable specialist path remains -Fallback mode: -- prefer delegating to a generalist agent when the environment supports it -- direct execution by the current agent is allowed only when delegation is constrained, unavailable, or already failed under the current task constraints +Detailed fallback requirements, invalid justifications (such as missing technology keywords), and fallback execution modes are defined in the `delegate` skill. **You must load and follow the `delegate` skill to validate any fallback decision.** --- @@ -186,16 +151,19 @@ Provide enough explicit context to avoid avoidable clarification loops. 6. Discover eligible specialists. 7. Select the best specialist or specialists. -Hard-gate before execution: -- [ ] `delegate` activated before substantive work -- [ ] specialist-first evaluation completed -- [ ] immediate task identified before agent selection -- [ ] done criteria defined or clarified -- [ ] `wiki/index.md` consulted before broad workspace exploration when available -- [ ] discovery completed -- [ ] eligible candidates assessed -- [ ] delegation decision made under this policy -- [ ] any fallback explicitly justified +## Before Any Execution + +**STOP. Do not proceed with any substantive work until ALL conditions below are confirmed true.** + +1. **`delegate` activated** — `skill('delegate')` has been loaded and evaluated. No exceptions. +2. **Specialist-first evaluation completed** — you have inspected available agents and selected by semantic fit. +3. **Immediate task identified** — the concrete next unit of work is named, not the broader initiative. +4. **Done criteria defined** — success is unambiguous; if unclear, stop and clarify. +5. **`wiki/index.md` consulted** — read it if it exists before any broad exploration. +6. **Discovery completed** — eligible candidates were gathered from all observable sources. +7. **Delegation decision made** — you chose under this policy, with explicit justification if fallback. + +If ANY condition is false: **STOP. Go back to Phase 1.** ### Phase 2: Execute @@ -204,6 +172,8 @@ Hard-gate before execution: 3. Allow subdelegation when it improves specialization or decomposition. 4. Review and synthesize before returning results upward. +**Agent Main Rule:** Do not execute tools directly unless task constraints explicitly require main-agent execution. All research, tool invocation, log collection, and low-level work belongs to subagents. The main agent context stays clean for planning, delegation, and synthesis. + ### Phase 3: After Task 1. Load `wiki`. diff --git a/src/opencode/devcontainer-feature.json b/src/opencode/devcontainer-feature.json index 3b0cc39..e71927d 100644 --- a/src/opencode/devcontainer-feature.json +++ b/src/opencode/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "opencode CLI", "id": "opencode", - "version": "0.3.5", + "version": "0.3.6", "description": "Installs the opencode AI coding agent CLI and ensures volume-mounted data directories are owned by the correct user.", "documentationURL": "https://opencode.ai", "options": { diff --git a/src/opencode/install.sh b/src/opencode/install.sh index 353c301..b5aea6f 100644 --- a/src/opencode/install.sh +++ b/src/opencode/install.sh @@ -54,6 +54,10 @@ ensure_prerequisites() { missing="${missing} curl" fi + if ! command -v jq >/dev/null 2>&1; then + missing="${missing} jq" + fi + if [ ! -f /etc/ssl/certs/ca-certificates.crt ]; then missing="${missing} ca-certificates" fi @@ -185,6 +189,29 @@ chown -R "${USERNAME}:${USERNAME}" \ "${USER_HOME}/.local/share/opencode" \ "${USER_HOME}/.local/state/opencode" +log "Configuring LSP in opencode.json..." + +opencode_config="${USER_HOME}/.config/opencode/opencode.json" + +if [ -f "$opencode_config" ]; then + if ! jq -e '.lsp' "$opencode_config" >/dev/null 2>&1; then + jq '. + {"lsp": {}}' "$opencode_config" > "${opencode_config}.tmp" && mv "${opencode_config}.tmp" "$opencode_config" + log "Added 'lsp' key to existing opencode.json" + else + log "'lsp' key already exists in opencode.json" + fi +else + cat > "$opencode_config" <<'EOF' +{ + "$schema": "https://opencode.ai/config.json", + "lsp": {} +} +EOF + log "Created opencode.json with LSP enabled" +fi + +chown "${USERNAME}:${USERNAME}" "$opencode_config" + cat > /usr/local/bin/opencode-fix-permissions </`: - `default.sh` / `default_auto.sh` — default behavior - `scenarios.json` — scenario definitions -- `custom_*.sh` — specific option combinations \ No newline at end of file +- `custom_*.sh` — specific option combinations + +### User-Home File Paths in Tests + +When testing files inside user home directories (e.g. `~/.config/opencode/opencode.json`), +the path depends on the base image. Autogenerated tests use plain images (`debian:latest`, +`ubuntu:latest`) where user is `root` (`/root/`). Scenario tests use `devcontainers/base` +images where user is `vscode` (`/home/vscode/`). Always probe both paths dynamically. \ No newline at end of file diff --git a/wiki/testing.md b/wiki/testing.md index 5b86553..4fafaa5 100644 --- a/wiki/testing.md +++ b/wiki/testing.md @@ -16,6 +16,21 @@ devcontainer features test --skip-scenarios -f opencode . devcontainer features test --skip-autogenerated --skip-duplicated -f opencode . ``` +## Test Execution + +There are two test modes with different behaviors: + +- **Autogenerated** (`--skip-scenarios`): builds fresh from a base image, runs `test//test.sh` as the test suite. Use for testing against plain images like `debian:latest` or `ubuntu:latest` where the user is `root`. +- **Scenario** (`--skip-autogenerated`): builds from predefined scenarios in `test//scenarios.json`, runs **only** the scenario-specific `.sh` file (e.g. `default.sh`). The generic `test.sh` is **not** executed here. + +When writing tests that check user-home files (like `~/.config/opencode/opencode.json`), both user contexts must be supported: + +```bash +OPENCODE_CONFIG="" +[ -f /root/.config/opencode/opencode.json ] && OPENCODE_CONFIG=/root/.config/opencode/opencode.json +[ -f /home/vscode/.config/opencode/opencode.json ] && OPENCODE_CONFIG=/home/vscode/.config/opencode/opencode.json +``` + ## Available Features | Feature | Description | Autoupdate |