Skip to content

fix: write opencode events plugin to auto-discovered .opencode/plugins/ dir - #15

Merged
kanfil merged 3 commits into
mainfrom
fix/opencode-plugin-dir
Sep 27, 2026
Merged

kanfil merged 3 commits into
mainfrom
fix/opencode-plugin-dir

Conversation

@kanfil

@kanfil kanfil commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Scope (expanded)

  1. Fix: opencode events plugin written to auto-discovered .opencode/plugins/ dir
  2. Fix: accumulate hook entries sharing one native event (latent collision bug)
  3. Feat: file_edited canonical event — draft-written clarify-skill nudge

1. Plugin path fix

OpenCode auto-loads local plugins only from .opencode/plugins/ (plural) or the plugin config array (docs). adlc-cli was writing to .opencode/plugin/ (singular) — never discovered.

# Check (team-diagnose chain) Result
1 .adlc/init-options.json configured green
2 jq on PATH green
3 boot.sh emits block green
4 Mirror vs source differs (expected)
5 Injection side FAIL — plugin in non-discovered dir

2. Accumulation fix

buildJsonNestedHooks/buildCopilotHooks assigned result[nativeEvent] = entries, so two canonical events sharing one native event silently overwrote each other. Latent until file_edited made collisions live (file_edited + post_tool_use → PostToolUse).

3. file_edited canonical event

Boot skills already capture decision drafts to .adlc/drafts/{type}/; this adds the injection channel that nudges the agent toward the matching clarify skill when a draft lands — replacing the unworkable session_end dependency for opencode.

Agent Native hook Delivery
opencode file.edited (generic event subscription) stdout stashed → injected into last user message on next messages.transform (pre-guard)
claude-code PostToolUse + matcher hookSpecificOutput.additionalContext
codex PostToolUse suppressed (safe no-op)
cursor postToolUse suppressed (safe no-op)
others — explicit null until documented

Also: dispatcher passes ADLC_EVENT env to skill scripts; CANONICAL_EVENTS 7→8.

Verification

$ npm test
# pass 295 / fail 0

Companion: tikalk/adlc-team-skills#40 (team-boot payload mode).

…s/ dir

OpenCode auto-loads local plugins only from .opencode/plugins/ (plural)
and the plugin array in config. adlc-cli was writing to .opencode/plugin/
(singular), which is never discovered by the agent.

- registry.mjs: fix config_file path
- events.test.mjs: update 12 path assertions + mkdir join part
- e2e-{workspace,profiles}.sh: assert plugins/ (not plugin/)
- README.md: document correct path

Closes team-context auto-injection failure (team-diagnose link 5).
Two canonical events mapping to the same native event (e.g. file_edited and
post_tool_use both → PostToolUse) silently overwrote each other: the
build functions assigned result[nativeEvent] = entries, dropping every
entry except the last canonical event processed.

Latent until now (no manifest declared colliding canonical events); the
file_edited mapping makes collisions live on claude-code, cursor, and codex.

buildJsonNestedHooks (claude-code/cursor/devin) and buildCopilotHooks now
accumulate into the existing array instead of overwriting.
Boot skills already capture decision drafts to .adlc/drafts/{type}/. This
adds the injection channel that nudges the agent to run the matching
existing clarify skill when a draft lands — replacing the unworkable
session_end dependency for opencode (no native session.end event).

- registry.mjs: file_edited canonical event; mappings for opencode
  (file.edited), claude-code (PostToolUse + hookSpecificOutput envelope),
  codex (PostToolUse + suppress), cursor (postToolUse, inherits "*":
  suppress); explicit null for gemini/qwen/copilot/devin/tabnine until a
  native surface is documented. CANONICAL_EVENTS updated (7→8).
- events.mjs (opencode generator): generic `event` subscription handler
  (file.edited has no named hook key), runEvent payload param → dispatcher
  stdin, _pendingNudge stash drained into the last user message by
  messages.transform BEFORE the EXTREMELY_IMPORTANT early-return guard
  (which would strand a mid-session nudge), standalone drainer when no
  session_start handler is declared, own [pending-drafts] dedup marker.
- dispatcher.mjs: ADLC_EVENT env var so multi-mode skill scripts can
  branch without payload sniffing.
- Tests: 5 new suites (generator shape, standalone drainer, accumulation
  regression + envelope, codex/cursor suppression, unmapped agents skip).
- README: 8 canonical events table + file_edited per-agent delivery matrix.
kanfil added a commit to tikalk/adlc-team-skills that referenced this pull request Sep 27, 2026
…l nudge

Boot skills already capture decision drafts to .adlc/drafts/{type}/; this
adds only the timely nudge toward the existing clarify skill, replacing
the unworkable session_end dependency for opencode (no native event).

- boot.sh/boot.ps1: ADLC_EVENT=file_edited mode — extract the edited file
  path from the payload (opencode flat/nested + claude-code tool_input
  shapes), stay silent unless it matches .adlc/drafts/**, then echo one
  [pending-drafts] line naming the matching skill (adr→/architect-clarify,
  pdr→/product-clarify, chdr→/change-clarify, cdr→/team-learn,
  evals→/evals-clarify). Default session-start output byte-identical.
- .events.json: declare file_edited (timeout 10, matcher Edit|Write —
  consumed only by agents that support it).
- docs/event-hook-contract.md: draft-nudge contract + per-agent delivery
  matrix (opencode stash-drain, claude-code additionalContext, codex/cursor
  suppressed no-ops).
- tests: 6 new functional tests (nudge mapping, non-draft silence, payload
  shapes, garbage silence, default-mode untouched, ps1 parity).

Companion: tikalk/adlc-cli#15 (canonical event wiring + generator).
@kanfil
kanfil merged commit f8c0a8f into main Sep 27, 2026
9 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