Skip to content

feat: YOLO mode, fully-customizable guard, customization skill + installer wiring#423

Merged
devinoldenburg merged 3 commits into
mainfrom
feat/customizable-yolo-mode
Jun 21, 2026
Merged

feat: YOLO mode, fully-customizable guard, customization skill + installer wiring#423
devinoldenburg merged 3 commits into
mainfrom
feat/customizable-yolo-mode

Conversation

@devinoldenburg

@devinoldenburg devinoldenburg commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Makes the Goal Mode guard highly customizable, adds an opt-in YOLO mode, ships a customization skill installed via the installer, and tidies the repo. Built as small, atomic commits.

Commits

  1. chore: remove leftover one-off issue-audit doc — drops the temporary 2026-06-20-issue-audit.md (not referenced, not packaged).
  2. feat(guard): YOLO mode + fully customizable allow/deny command rules (Co-authored-by: Gemini)
  3. feat(skill+installer): goal-mode customization skill, installed via the installer (Co-authored-by: Codeplane)

YOLO mode & customization (config/env)

  • yolo — relax the soft gates (network-exec block, completion enforcement, Goal-only subagent lock, block toasts); destructive guarding stays on.
  • allowDestructive — turn destructive guarding off too; with yolo = full YOLO (nothing blocked, all rights). Works standalone.
  • allowCommands — regex allow-list; a matching bash command is never blocked.
  • extraDestructive — regex deny-list; matching commands are treated destructive.
  • YOLO only relaxes keys you didn't set explicitly (per-key options always win). New GOAL_GUARD_* env vars + opencode.json options; invalid custom regexes are ignored, never fatal. Documented in the README config table + a YOLO section.

Customization skill + installer/update

  • skills/goal-mode-customization/SKILL.md and a /goal-mode-customize command teach the agent how to tune the guard and apply the change.
  • The installer ships them: skills is a new COMPONENT_DIR, skills/ is in the npm files allowlist, so they install with the package and refresh on every (re)install; --uninstall removes them (manifest-tracked).
  • Update flow: postinstall already re-runs the installer on a global update; added explicit update / reinstall scripts.

Verification

  • node --test "tests/*.test.mjs"660 pass, 0 fail (10 new YOLO/customization tests; install test asserts the skill+command install).
  • npm run lint clean; node scripts/validate-opencode-config.mjs passes; npm run publish:check -- --skip-registry ready; npm pack --dry-run ships skills/ + the command.
  • Full installer lifecycle exercised: dry-run → install (skill/command/tui.json land) → idempotent reinstall → uninstall (skill removed).

Does not touch Issue #2.

Devin Oldenburg and others added 3 commits June 21, 2026 13:55
2026-06-20-issue-audit.md was a temporary analysis artifact from a triage run —
not referenced anywhere and not part of the published package (files allowlist).
Remove it to keep the repo root clean.

Co-authored-by: Claude Fable 5 <81847+claude@users.noreply.github.com>
Adds opt-in YOLO mode and per-command customization so the whole guard is
tunable from config/env:

- yolo: relaxes the soft gates (network-exec block, completion enforcement,
  subagent lock, block toasts); destructive guarding stays on by default.
- allowDestructive: turns off destructive guarding too — with yolo that is
  'full YOLO' (nothing blocked); works standalone as a direct override.
- allowCommands: regex allow-list; a matching bash command is never blocked.
- extraDestructive: regex deny-list; matching commands are treated destructive.

YOLO only relaxes keys the user did not set explicitly, so any per-key option
still wins. New GOAL_GUARD_* env vars + opencode.json options for all of the
above; documented in the README config table with a YOLO section. 10 new tests.

Co-authored-by: Gemini <gemini@users.noreply.github.com>
…he installer

- Add a goal-mode-customization skill (skills/goal-mode-customization/SKILL.md)
  and a /goal-mode-customize OpenCode command that teach the agent how to tune the
  guard (config keys, YOLO, allow/deny rules, sidebar) and apply it correctly.
- Installer ships them: 'skills' is now a COMPONENT_DIR and skills/ is in the npm
  files allowlist, so the skill+command install with the package and are refreshed
  on every (re)install. Manifest-tracked, so --uninstall removes them.
- Update flow: postinstall already re-runs the installer on a global update; add
  explicit 'update' (npm i -g @latest) and 'reinstall' (installer --force) scripts.
- install.test.mjs updated to assert the skill+command install and the new
  COMPONENT_DIRS shape.

Co-authored-by: codeplane-agent[bot] <287208015+codeplane-agent[bot]@users.noreply.github.com>

@devinoldenburg devinoldenburg left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review — verdict: APPROVE (sound)

(Posting as a comment: GitHub blocks self-approval since I'm the PR author. No blocking defects found.)

Reviewed rigorously against all focus areas; verified by running the suite, lint, validator, config probes, and a full installer lifecycle.

Verification performed

  • node --test tests/*.test.mjs660 pass / 0 fail (incl. 10 new YOLO/customization tests + the install assertion).
  • npm run lint exits 0; node scripts/validate-opencode-config.mjs passes; npm pack --dry-run ships skills/goal-mode-customization/SKILL.md + commands/goal-mode-customize.md.
  • Full installer lifecycle into a temp config dir: install copies skill+command and records them in the manifest, reinstall is idempotent (0 copied), --uninstall removes them cleanly including the now-empty skills/ dir.

Focus-area findings (all sound)

  1. YOLO security/correctnessyolo relaxes only the four intended soft gates (blockNetworkExec, enforceCompletion, restrictSubagents, toastOnBlock); destructive guarding stays on. 'Explicit per-key wins' holds for both env and options (the explicit set is seeded from envConfig keys and grows in the opts loop — verified: {yolo:true}+GOAL_GUARD_BLOCK_NETWORK_EXEC=1 keeps blocking on; {restrictSubagents:true}+GOAL_GUARD_YOLO=1 keeps the lock). allowDestructive is correctly gated and works standalone. Default yolo:false → no accidental disabling.
  2. Allow-list bypass (guard.js:582,586-587) — applied only to the block decision; invalid patterns are swallowed in compileGuardPatterns; allowCommandPatterns.length>0 short-circuit means the empty default never bypasses anything; lastIndex=0 reset is harmless/defensive. User-supplied regex ReDoS is the user's own opt-in, not a guard vuln.
  3. extraDestructive precedence (guard.js:585-586) — allowlist correctly wins (!allowlisted && ... destructive). Test proves the allow path AND that a sibling command is still blocked.
  4. Config persistenceallowCommands/extraDestructive resolve to frozen string arrays; regex compilation lives in guard.js, so no RegExp leaks into the (snapshotted) config. JSON.stringify round-trips cleanly.
  5. Installerskills is a safe relative COMPONENT_DIR; the existing doesNotMatch /auth|sessions|.../ guard test still holds; manifest-tracked install/uninstall verified.
  6. Tests — non-tautological (assert both the bypass and the still-blocked counter-case; invalid-pattern test proves the guard still functions).

Nits (non-blocking)

  • tests/yolo.test.mjs:1-2 — Biome organizeImports wants the two imports sorted. npm run lint doesn't gate on it (exits 0), so harmless, but worth a one-line fix.
  • guard.js:580-581 — the 'no dirty mark' comment is precise for the before-hook, but tool.execute.after does not consult the allowlist, so an allow-listed destructive command still marks an active goal session dirty. This is arguably correct (the command did run/mutate) and never blocks — just slightly broader than the comment implies.
  • coerceList stringifies non-string inputs (object → "[object Object]", array null"null"). These compile to inert/non-matching regexes or are swallowed, so garbage-in is non-fatal — no change required.
  • README uses ./plugins/goal-guard.js while the skill/command use opencode-goal-mode; both are valid OpenCode plugin refs and each file is internally consistent.

Solid, well-tested, safe-by-default change. LGTM.

@devinoldenburg devinoldenburg force-pushed the feat/customizable-yolo-mode branch from 2efded3 to 5391b41 Compare June 21, 2026 12:10
@devinoldenburg devinoldenburg merged commit 2498404 into main Jun 21, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant