Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9b72aac
fix(opencode): load hooks and telemetry in both plugin runtimes
blafourcade Oct 7, 2026
3a2c3df
docs(framework): record completed OpenCode compatibility validation
blafourcade Oct 7, 2026
ae500bf
fix(opencode): share runtime adapter across plugin delivery paths
blafourcade Oct 7, 2026
ffa9c44
docs(framework): record shared runtime delivery and final validation
blafourcade Oct 7, 2026
b1a37fe
docs(framework): record independent OpenCode review and challenge
blafourcade Oct 7, 2026
d609721
fix(cli): verify Kilo hooks and repair mutation asset loading
blafourcade Oct 7, 2026
23dc0ce
test(cli): cover Kilo parser and session lifecycle mutations
blafourcade Oct 7, 2026
3e762c3
test(cli): assert final Kilo hook counts after shutdown
blafourcade Oct 7, 2026
0528e5c
docs(framework): record independent Kilo verification review
blafourcade Oct 7, 2026
16d8b22
test(cli): refresh Kilo bridge golden after lifecycle support
blafourcade Oct 7, 2026
debb074
docs(framework): verify corrected Kilo golden baseline
blafourcade Oct 7, 2026
116f791
fix(cli): keep embedded configuration bytes stable on Windows
blafourcade Oct 7, 2026
cdd2e59
docs(framework): record Windows checkout verification
blafourcade Oct 7, 2026
6daf59f
test(cli): remove code interpolation from Kilo probes
blafourcade Oct 7, 2026
2b866dd
refactor(cli): remove obsolete Kilo parser and stale hook comments
blafourcade Oct 7, 2026
fde9605
docs(framework): shorten documentation and add concise Claude rules
blafourcade Oct 7, 2026
52e7e88
docs(framework): keep architecture focused on boundaries
blafourcade Oct 7, 2026
551ce97
docs(framework): clarify architecture and telemetry for all readers
blafourcade Oct 8, 2026
4eca888
docs(framework): organize documentation by section purpose
blafourcade Oct 8, 2026
7083435
docs(framework): consolidate concise documentation rules
blafourcade Oct 8, 2026
61d7500
docs(framework): explain architecture from marketplace to components
blafourcade Oct 8, 2026
144de00
docs(framework): prefer architecture diagrams and tables
blafourcade Oct 8, 2026
bf400eb
fix(cli): repair runtime files for current plugins
blafourcade Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .claude/rules/01-standards/1-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
paths:
- "**/README.md"
- "**/ARCHITECTURE.md"
- "docs/**/*.md"
- "**/aidd_docs/memory/**/*.md"
- "**/GUIDELINES.md"
- "**/CONTRIBUTING.md"
---

# Concise documentation

- Edit durable, authored Markdown individually; exclude history, generated content and fixtures.
- Architecture: components, boundaries, flows, invariants. README: purpose, usage, limits.
- Use descriptive, hierarchical headings; include only relevant facts, once per document.
- Preserve contracts, decisions, rationale, limits, procedures, linked anchors and generator markers. Keep memory safeguards self-contained; never invent performance requirements.
- Remove filler, repetition, narrated history, dates, counters, ticket/run IDs, snapshots, temporary evidence and measured timings, ratios or comparisons.
- Prefer diagrams for relationships and tables for roles; keep necessary prose concise. Retain required versions, constants and useful examples.
- State actions and verification commands; link canonical sources for supporting details.
- Read back: check section scope, preserved information, commands and links.
4 changes: 2 additions & 2 deletions .github/workflows/cli-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ jobs:
key: pnpm-${{ runner.os }}-${{ hashFiles('cli/pnpm-lock.yaml') }}
restore-keys: pnpm-${{ runner.os }}-
- run: cd cli && pnpm install --frozen-lockfile
# The test starts Kilo's local server and asks it to load the generated project plugin.
# No model or account is needed for this protocol-level smoke.
# Exercise generated hooks and memory with the released Kilo server and read tool.
# Inference uses a deterministic loopback endpoint; no provider account is needed.
- name: Install Kilo Code CLI
run: npm install -g @kilocode/cli@7.7.5
- run: cd cli && pnpm test:e2e:kilo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"backlog": "ai-driven-dev/framework#953",
"written_at": "2026-10-07T13:49:41.828285Z",
"written_by": "aidd-dev:01-plan"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Challenge
No blocker within the [reviewed scope](./review.md).

One shared adapter and existing delivery paths satisfy the need. Real-host effects and failing counterproofs support the result.

Runtime boundaries: [OpenCode](./verification.md), [Kilo](./kilo-verification.md). Keep the bundle-size gate. If event handling expands, add interleaved calls sharing a tool ID across different session/message identities; that scenario has no dedicated regression.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Kilo verification

Need: replace a session-only smoke that substituted the memory script with a complete real turn and repair red CI. Research preceded implementation: [plugin contract](https://kilo.ai/docs/automate/extending/plugins), [custom provider](https://kilo.ai/docs/code-with-ai/agents/custom-models), [SDK 7.7.5 types](https://unpkg.com/@kilocode/sdk@7.7.5/dist/v2/gen/types.gen.d.ts).

Implementation: map session creation, completed tools and idle to `SessionStart/PostToolUse/Stop`. Preserve actual identity/cwd, parse commands, filter exact or pipe-separated matchers, consume each tool part once, reset idle suppression on busy and release deleted sessions. Report failed hooks without blocking the host.

## Tests

- [Bridge](../../../../cli/tests/contexts/tools/domain/profiles/kilo/kilo-hooks-bridge.unit.test.ts): missing declarations/commands, argument parsing, released lifecycle events, malformed/incomplete/failed tools, matchers, replay, new turns and deleted-session recreation. Nonzero exit, spawn and dispatch failures are reported once.
- [Delivery](../../../../cli/tests/contexts/framework/application/plugin/kilo-plugin-delivery.integration.test.ts): setup/install/update for `kilo.jsonc` and `.kilo/kilo.jsonc`; exact JSONC bytes, comments, model, permissions and MCP preserved. Verify scripts/manifest version and restore a deleted bridge. These are application use cases with filesystem/fetch doubles.
- [Checkout](../../../../cli/tests/architecture/bundled-config-checkout.arch.test.ts): isolated real Git checkout with `core.autocrlf=true` preserves LF for embedded assets; removing the attribute rule defeats preservation.
- [Real Kilo 7.7.5](../../../../cli/tests/e2e/kilo-runtime.e2e.test.ts): actual CLI translation, byte-identical memory script updating `AGENTS.md`, skills/agents/MCP discovery, real read/result and exact hook payloads. Independent host observation and a final snapshot after process-group shutdown reject late duplicates. Assert server/captured-process shutdown and model cleanup. Profiles are isolated; only inference is substituted. Translation may normalize JSON; delivered configuration remains byte-identical during execution.

Re-run in a disposable environment, as [CI](../../../../.github/workflows/cli-ci.yml) does; the install command replaces its global Kilo executable:

```sh
npm install -g @kilocode/cli@7.7.5
pnpm --dir cli test:e2e:kilo
pnpm --dir cli exec vitest run --project=unit tests/contexts/tools/domain/profiles/kilo/kilo-hooks-bridge.unit.test.ts
pnpm --dir cli exec vitest run --config vitest.mutation.config.ts tests/contexts/framework/application/plugin/kilo-plugin-delivery.integration.test.ts
pnpm --dir cli test:mutation:tools-opencode
pnpm --dir cli test:mutation:tools-kilo
pnpm --dir cli test:arch
```

The ordinary suite skips the opt-in host case; its dedicated CI job runs it explicitly.

## Counterproofs and repairs

Before implementation, the real turn fired only `SessionStart`; bridge regressions also failed. A copied deleted-session mutant failed recreation; injecting an extra final hook failed the exact count assertion. Assertions check the actual tool result rather than request totals because Kilo also requests a title.

The mutation loader reads `.txt` assets as source, matching normal tests. LF checkout fixes Windows bundle growth; thresholds and budget stay unchanged. A stale golden bridge hash was recaptured without changing file lists; comparison mode then passed. Test probes use static code rather than interpolated paths, addressing the [CodeQL embedding rule](https://codeql.github.com/codeql-query-help/javascript/js-bad-code-sanitization/). No alert was suppressed. The obsolete parser wrapper was removed; representative generator inputs produced byte-identical modules after cleanup. [Final gates](./review.md).

Kilo telemetry remains unsupported. Paid providers, global-profile operation, hot reload, exhaustive process-tree auditing and Windows Kilo runtime remain outside this proof.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
status: done
---

# OpenCode contract
Both plugins export default `id/server/setup` (V1 >= 1.18.29; V2). V1 returns after `server`, without invoking named factories again. A dependency-free CLI-owned adapter lives at `.opencode/hooks/opencode-events.js`, outside plugin discovery; payload mapping stays plugin-specific.

Translation emits the helper once; setup tracks tool ownership; restoration includes it. Plugin install/update backfill missing helpers without replacing existing configuration, existing helper contents or recorded ownership/drift hashes. Source retrieval reuses one loader.

V2 setup subscribes with cancellable cleanup. Its `data/location` events correlate tool input and success by session/message/tool identity. Success consumes pending state; failures and terminal events discard it. Completion closes the turn; shutdown interruption leaves it resumable.

## Acceptance
- Import spawns no hooks.
- V1 invokes once; V2 setup returns promptly and cleanup aborts its stream.
- Malformed events, failed tools and repeated success are safe.
- Coding and architecture gates pass.
- Real V2 loads both plugins and updates memory/journal.
- Real V1 preserves effects without duplicate start.
- Verification distinguishes real-host effects from controlled regressions and substituted inference.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
status: implemented
---

# Plan — OpenCode plugin loading
Load context and telemetry plugins on OpenCode V2 while preserving V1 compatibility. Require observable effects, prior web research and failing regressions before implementation.

- [OpenCode contract](./phase-1.md): compatible entrypoints, shared adapter and safe delivery.
- [Runtime proof](./verification.md): research first, failing regression, real hosts.
- [Accepted Kilo extension](./kilo-verification.md): complete hooks, configuration preservation and CI repair.
- [Final review](./review.md): quality and required gates.

Constraints: isolated profiles, local inference, unchanged mutation thresholds and bundle budget, user files untouched. Generic host adaptation belongs to the CLI; plugin-specific payload mapping stays with each plugin. Keep hook tests outside shipped plugin trees.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Review: OpenCode loading and Kilo lifecycle

- **Verdict**: approve within the runtime limits below
- **Diff**: `origin/next...fix/opencode-plugin-loading`, including the final repair
- **Axes run**: code, functional, relevancy; fresh reviewers received no prior verdict
- **Date**: 2026_10_08
- **Findings**: 0 critical, 0 warning, 0 minor remaining

## Phases

### Phase 1: OpenCode compatibility and delivery

- [x] Import starts no hook — `cli/tests/e2e/opencode-hooks-bridge-generated.e2e.test.ts`.
- [x] V1 invokes once; V2 setup returns promptly and cancels its stream — `scripts/__tests__/aidd-telemetry-opencode-payloads.test.js:60`, `scripts/__tests__/opencode-plugin.test.js:168` and released loader/SDK sources in [proof](./verification.md).
- [x] Malformed events, failed tools and repeated success stay safe — `scripts/__tests__/opencode-plugin.test.js:138,272`, generated-module regressions and [counterproof](./verification.md).
- [x] Coding and architecture gates pass — prior-head CI and fresh local checks below; final-head gates required before merge.
- [x] Real V2 loads both plugins and changes memory/journal — [observed effects](./verification.md).
- [x] Real V1 preserves effects without duplicate start — same proof, released host 1.18.29.
- [x] Verification distinguishes real-host effects, controlled regressions and substituted inference — same proof.

### Authorized extensions

- [x] Helper outside discovery, unique ownership and safe install/update repair — `cli/tests/contexts/framework/application/plugin/plugin-runtime-files.integration.test.ts:61,75,94,112,125`.
- [x] Kilo lifecycle, matchers, replay, new turns, deleted-session recreation and failure reporting — `cli/tests/contexts/tools/domain/profiles/kilo/kilo-hooks-bridge.unit.test.ts:33,96,203`.
- [x] Kilo JSONC preservation and real complete turn after shutdown — `cli/tests/contexts/framework/application/plugin/kilo-plugin-delivery.integration.test.ts:77,87,98`, `cli/tests/e2e/kilo-runtime.e2e.test.ts:192`.
- [x] Windows LF preservation and drift counterproof — `cli/tests/architecture/bundled-config-checkout.arch.test.ts:41,45`.
- [x] No unused addition or weakened gate identified — static review of 62 implementation/test/CI files; prior-head CLI CI passed all 29 jobs.
- [x] Architecture/docs match responsibilities; concise rule remains Claude-only; project memories untouched — complete diff checked for relevance and contradictions.
- [ ] Historical research → regression → implementation chronology — not reconstructed independently; not applicable to current-state review.

## Findings

| Sev | Kind | Phase | Location | Issue | Fix |
| --- | --- | --- | --- | --- | --- |

## Verification

| Metric | Value |
| --- | --- |
| Verified | Functional reviewer corroborated 22/23 checks (96%); historical chronology excluded from current-state verdict |
| Files checked | Entire PR diff; 62 implementation/test/CI files checked for code quality; documentation checked for relevance and contradictions |
| Resolved | Same-version update skipped helper repair: repair now precedes version comparison. Fixture depended on working directory: uses `REPOSITORY_ROOT`. Both fixes independently rechecked. |
| Regression | Missing-helper test failed before repair; 36 selected update/runtime tests then passed. |
| Built CLI | Isolated setup → install → delete helper → same-version update restored exact helper bytes; preserved configuration/plugin record and unique ownership. |
| Local checks | Changed-file Biome, diff whitespace and build passed within unchanged budget. |
| Merge gates | Required local hooks and [exact-head PR checks](https://github.com/ai-driven-dev/framework/pull/971/checks) must pass before merge. Prior head `144de007` passed all executed checks. |
| Unchecked | Historical chronology: not applicable. Temporary real OpenCode probes and limits documented in [proof](./verification.md). |
| Runtime limits | Inference substituted locally; paid providers, global profiles, hot reload and Windows Kilo runtime untested. Kilo telemetry unsupported. |
| Unplanned | None beyond user-authorized Kilo, verification and documentation extensions. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# OpenCode proof

Research: [migration](https://opencode.ai/v2/docs/build/plugins/migrate-v1), [plugin API](https://opencode.ai/v2/docs/build/plugins), [released event types](https://unpkg.com/@opencode/client@2.0.22/dist/promise/generated/types.d.ts). The [V1 loader](https://github.com/anomalyco/opencode/blob/v1.18.29/packages/opencode/src/plugin/index.ts) returns after `default.server`; the [V2 coordinator](https://github.com/anomalyco/opencode/blob/v2.0.22/packages/core/src/session/execution.ts) preserves shutdown-interrupted executions for restart.

Before: V2 reported `Missing key at ["default"]` despite exit zero; memory unchanged, journal empty. Exit status alone could not prove success.

After: real macOS runs passed for translated V1 1.18.29, translated V2 2.0.22, fresh V2 setup and existing V2 installation missing its helper. Each refreshed the seeded memory reference, fired `SessionStart/PostToolUse(read)/Stop` exactly once and wrote `session_start/task_declared/turn_end`. Payloads carried the actual session identity and task-document argument. No loader error; existing configuration preserved byte-for-byte and the helper recorded once as tool-owned.

Observed V2 events were granular tool input/call/success and execution completion, without `session.idle` or content snapshots. The shared adapter correlates inputs, consumes success once and preserves shutdown-interrupted turns. Controlled regressions cover malformed/incomplete/failed events, terminal cleanup and subscription cancellation; these are not live-host failure scenarios. A copied success-consumption mutant failed the duplicate-task assertion. Missing-helper regressions failed before backfill; existing contents and hashes remain protected.

Re-run the committed adapter, payload, generated-layout and delivery regressions:

```sh
node scripts/check-tests-leave-git-alone.js -- node --test scripts/__tests__/opencode-plugin.test.js scripts/__tests__/aidd-telemetry-opencode-payloads.test.js
pnpm --dir cli exec vitest run --project=unit tests/contexts/tools/domain/profiles/opencode/opencode-hooks-bridge.unit.test.ts
pnpm --dir cli exec vitest run --project=integration tests/contexts/framework/application/plugin/plugin-runtime-files.integration.test.ts
pnpm --dir cli exec vitest run --project=e2e tests/e2e/opencode-hooks-bridge-generated.e2e.test.ts
```

The real-host probe was temporary and is not a committed reproduction harness. Commands above exercise adapters and delivery, without launching released OpenCode hosts. The observed host runs isolated profiles and substituted only inference with a loopback provider; plugin loading, events, the read tool, hooks and journal were real. Global installation, paid providers, hot reload, other releases/OS and concurrent sessions were not exercised. [Kilo proof](./kilo-verification.md); [final gates](./review.md).
3 changes: 3 additions & 0 deletions cli/.gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
# "a test reads this file's raw bytes", which is true of any fixture format, not a property
# of JSON specifically.
tests/fixtures/** text eol=lf

# Raw config assets are embedded in the bundle; CRLF changes their bytes and its size.
assets/configs/** text eol=lf
21 changes: 20 additions & 1 deletion cli/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,26 @@ Memory ownership (CLAUDE.md, AGENTS.md, copilot-instructions.md) is delegated to

## Translate (author-side)

`aidd translate` (renamed from `framework build` in phase 18) converts a Claude-format framework source into a target-native distribution. Five targets (`claude`, `cursor`, `copilot`, `codex`, `opencode`) × two modes (`marketplace`, `--as flat`); `opencode` is flat-only, so 9 build cells. The orchestrators (`MarketplaceBuildStrategy`, `FlatBuildStrategy`) read a per-tool `ToolBuildContract` — no per-tool branching. **Scope:** skills, agents, mcp, and hooks are emitted; `rules` and `commands` are currently out of scope (warn + skip per plugin). See `README.md` → `aidd translate` for the per-tool layout matrix.
`aidd translate` converts a Claude-format framework source into a target-native distribution. The orchestrators (`MarketplaceBuildStrategy`, `FlatBuildStrategy`) read a per-tool `ToolBuildContract` without per-tool branching. **Scope:** skills, agents, mcp, and hooks are emitted; `rules` and `commands` are out of scope (warn + skip per plugin). The [CLI reference](README.md#translate) owns the supported targets and output layout matrix.

## Hook adaptation

OpenCode needs JS adapters. The CLI owns the shared host protocol; plugins own payload mapping. Its helper is delivered once outside plugin discovery, tracked as a tool file, and backfilled only when missing. Installation must neither rewrite user configuration nor claim existing untracked helpers. Generic `SessionStart` runs idempotently at host initialization; telemetry follows actual sessions.

<details>
<summary>Tool compatibility and adapter contracts</summary>

Hooks are authored with `${CLAUDE_PLUGIN_ROOT}`; the installer translates the root for each tool.
| Tool | Runs bundled hooks | Plugin root | Notes |
| -------------- | --------------------- | ---------------------- | ----- |
| Claude Code | yes | `${CLAUDE_PLUGIN_ROOT}` | Authoring spelling, nothing substituted |
| Codex | yes | `${PLUGIN_ROOT}` | Also expands `${CLAUDE_PLUGIN_ROOT}`; runs a hook only once trusted |
| GitHub Copilot | yes | `${PLUGIN_ROOT}` | Declared, never observed running |
| Cursor | declared | `./` | Own hook format: the converter rewrites the root to a plugin-relative path before token substitution. No plugin hook observed firing headless; what registers a plugin in Cursor's plugin directory is unknown |
| OpenCode | no, by a second route | — | See below |
Runtime contracts: [hook bridge](src/contexts/tools/domain/profiles/opencode/opencode-hooks-bridge.ts), [shared V2 adapter](assets/configs/opencode/opencode-events.js.txt), [telemetry payload adapter](../plugins/aidd-telemetry/hooks/opencode-plugin.js). The shared helper is `.opencode/hooks/opencode-events.js`. [Telemetry coverage](../plugins/aidd-telemetry/README.md#coverage) states supported versions and limitations. Unsupported hooks and skipped installation surfaces must be reported.

</details>

## Dependency Wiring

Expand Down
Loading
Loading