Skip to content

feat(cli): add Kilo Code support - #745

Merged
blafourcade merged 2 commits into
ai-driven-dev:nextfrom
waewoo:feat/kilo-code-support
Sep 23, 2026
Merged

blafourcade merged 2 commits into
ai-driven-dev:nextfrom
waewoo:feat/kilo-code-support

Conversation

@waewoo

@waewoo waewoo commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

🎯 What & why

Add native Kilo Code support so AIDD can be installed and released for Kilo instead of relying on the OpenCode layout that Kilo no longer discovers.

🛠️ How it works

The new Kilo tool adapter maps skills, agents, MCP configuration, and flat plugins to Kilo-native project locations. The flat build contract namespaces skills and subagents, merges MCP servers, emits project-local .kilo/kilo.jsonc by default, and feeds a new kilo:flat release cell. The README documents the generated archive and installation flow.

The Kilo profile retains Kilo's documented command surface: CommandsCapability, .kilo/commands, and command-link rewriting. Flat distribution of plugin commands remains a separate follow-up. Flat Kilo Rules distribution and its configuration merge behavior are tracked in #868.

🔌 Lifecycle plugin

This PR generates the Kilo-native project lifecycle plugin under .kilo/plugin/ from the relevant AIDD hooks.json definitions. It maps Kilo's verified session-start equivalent to the guarded aidd-context project-memory synchronization while reusing the existing shared behavior. Missing memory, malformed markers, and plugin failures remain non-blocking and diagnostic.

The existing Kilo agent output (.kilo/agents/) remains separate from this executable plugin bridge.

🧪 Verification

Executed on 71d7bf885a899171e9f0129f29f6bbdbbab7cd46:

  • pnpm --dir cli typecheck
  • pnpm --dir cli exec vitest run --project=e2e tests/e2e/framework-build.e2e.test.ts — 22 passed.
  • KILO_RUNTIME_SMOKE=1 pnpm --dir cli exec vitest run --project=e2e tests/e2e/kilo-runtime.e2e.test.ts — 1 passed; Kilo discovers the generated skills and agents, loads the generated project plugin, and fires the guarded synchronization exactly once.

🔗 Linked issue

Related: #744

✅ I certify

  • I DO CERTIFY I READ EACH LINE OF THE PULL REQUEST BECAUSE I AM A SOFTWARE ENGINEER, NOT A AI PUPPY.

@waewoo
waewoo force-pushed the feat/kilo-code-support branch from 7b4d03b to ec67353 Compare September 2, 2026 12:03
@waewoo

waewoo commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Hi, and apologies for opening this pull request prematurely.
I realize now that I should have waited for the related issue to be reviewed and validated by a Certified Member or Maintainer, and for its status to be moved to Todo, before opening a PR.
I will of course wait for the issue to be validated and moved to Todo before proceeding further. Please consider this PR as an early draft opened ahead of the expected process.
Sorry for not following the contribution workflow, and thank you for your understanding.

@waewoo
waewoo force-pushed the feat/kilo-code-support branch from ec67353 to 2fa0688 Compare September 6, 2026 07:18
@waewoo

waewoo commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up scope: rules and commands

This draft only adds Kilo as a flat-build target. It deliberately retains the existing global framework-build decision for plugin rules/ and commands: every target currently warns and skips them.

That was an intentional YAGNI choice, recorded in the flat-build design: at the time, the framework shipped no plugin source in either directory. It was therefore not an omission specific to Kilo.

The situation is worth revisiting separately because aidd-context now guides users to generate rules and commands. Two follow-up issues will cover (1) Kilo/current-OpenCode guidance in those generators and (2) emitting those artifacts from OpenCode/Kilo flat archives.

This PR remains a draft and has not been reviewed, approved, or merged; neither follow-up assumes that it will be accepted.

@blafourcade

Copy link
Copy Markdown
Contributor

@waewoo One Kilo contract problem remains in this draft.

The profile declares CommandsCapability, .kilo/commands as its signal directory, and rewrites links to that location. Current Kilo documentation does not define a native Markdown command surface there, so this would make AIDD emit an artifact Kilo is not documented to discover.

Please remove the command capability, .kilo/commands path, and command-link rewriting from this PR. Kilo rules can remain supported: their documented contract is Markdown files referenced from kilo.json[c].instructions. Flat rule distribution stays in #868; this PR only owns the profile contract it needs.

@waewoo

waewoo commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor Author

@blafourcade
Thanks for the review. I double-checked the current Kilo contract and the AIDD installation flow before deciding whether to remove CommandsCapability.

Commands

The current Kilo documentation explicitly documents project workflows/slash commands as Markdown files under .kilo/commands/:

https://kilo.ai/docs/customize/workflows

In particular, it states that workflows are stored as slash commands in .kilo/commands/, with project commands under [project]/.kilo/commands/, and gives .kilo/commands/submit-pr.md → /submit-pr as an example.

The current Kilo configuration reference also documents Markdown commands and explicitly supports both command/ and commands/ under .kilo/:

https://github.com/Kilo-Org/kilocode/blob/main/packages/opencode/src/kilocode/skills/kilo-config.md

This is also reflected in the implementation history. Kilo-Org/kilocode#6881 established .kilo/ as the canonical location while retaining .kilocode/ as a legacy fallback:

Kilo-Org/kilocode@466644e

So based on the current documented Kilo contract, .kilo/commands/ appears to be a native command surface.

Unless I am missing another constraint specific to AIDD, I think CommandsCapability, the .kilo/commands signal path, and the corresponding link rewriting should remain in #745.

Rules

I also checked your point that Kilo rules should be Markdown files referenced from kilo.json[c].instructions.

The Kilo configuration reference confirms that kilo.json / kilo.jsonc is the configuration surface and that additional instruction files/globs are loaded through the instructions field:

https://github.com/Kilo-Org/kilocode/blob/main/packages/opencode/src/kilocode/skills/kilo-config.md

The current #745 implementation correctly installs generated rules under:

.kilo/rules/<rule>.md

and its base Kilo configuration contains:

{
  "instructions": [
    ".kilo/rules/**/*.md"
  ]
}

However, following the installation path exposed an edge case in the current draft: when a project already owns kilo.json / kilo.jsonc, AIDD preserves that user-owned file rather than ensuring the AIDD rule glob is merged into its existing instructions.

That could leave .kilo/rules/*.md files installed but not actually loaded by Kilo.

There is also an existing-config consistency case to cover: the Kilo MCP capability already resolves kilo.json vs kilo.jsonc and rejects the ambiguous case where both exist, while the runtime base-config installation currently targets kilo.json directly.

I'll therefore adjust the Rules/config part so that AIDD safely ensures:

{
  "instructions": [
    "...existing user instructions...",
    ".kilo/rules/**/*.md"
  ]
}

while:

  • preserving existing instructions;
  • supporting an existing kilo.jsonc;
  • avoiding duplicate entries;
  • avoiding the creation of both kilo.json and kilo.jsonc;
  • remaining idempotent.

I'll add tests for these existing-config cases as part of the change.

Thanks — the review helped uncover this Rules/config edge case.

@blafourcade

Copy link
Copy Markdown
Contributor

@waewoo You are correct. My previous review comment was based on an outdated assumption: current Kilo documentation explicitly supports Markdown slash commands under .kilo/commands/.

Please retain CommandsCapability, the .kilo/commands signal path, and the corresponding link rewriting in the Kilo profile. The flat build may still leave canonical plugin commands unsupported for now, because that distribution capability needs its own scoped follow-up.

Your rule/config finding is the relevant gap for #868: generated .kilo/rules/ files must be referenced from the resolved existing kilo.json[c] instructions array without duplicating AIDD entries, reordering user entries, or creating both config variants.

@waewoo
waewoo force-pushed the feat/kilo-code-support branch 2 times, most recently from 940e8d9 to 0fd0c16 Compare September 14, 2026 22:47
@waewoo

waewoo commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for correcting the command-surface point. I updated the PR to keep the documented Kilo command profile support explicit while clarifying that flat plugin-command distribution remains a separate follow-up. The PR now links to #744 without closing it, and keeps flat Kilo Rules distribution and its configuration merge behavior scoped to #868.

@waewoo
waewoo force-pushed the feat/kilo-code-support branch 2 times, most recently from 71d7bf8 to 646ee28 Compare September 18, 2026 06:59
@waewoo
waewoo marked this pull request as ready for review September 18, 2026 07:01
@waewoo
waewoo requested a review from a team as a code owner September 18, 2026 07:01

@blafourcade blafourcade left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I pulled this down, built it from 646ee285 and ran it. Design is right and the sandbox behaviour is good, but pnpm test was never run on this head and six tests fail on the branch alone, before any merge. Needs another pass.

What I checked and liked

Installed into a throwaway HOME, then translate --to kilo --as flat:

Flat-installed 8 plugins, 458 files written
434 .kilo/skills   19 .kilo/hooks   2 .kilo/plugin   2 .kilo/agents   1 .kilo/kilo.jsonc

Nothing escapes .kilo/. I drove the generated lifecycle plugin by hand: one dispatch on session.created, none on anything else, and with node off the PATH it prints spawn node ENOENT and the session survives. That is exactly the contract in aidd_docs/memory/architecture.md. timeout: 5000, stdio closed, cwd bounded to the project. Good work.

I also diffed the golden cell by cell against the merge base: none of the nine existing cells moved, the +263 lines are all kilo:flat. That was my main worry and it is clean. The two shared e2e changes tighten things rather than loosen them, and ci.yml has the ten-cell matrix.

What blocks it

The kilo:flat baseline is stale.

kilo:flat: +.kilo/kilo.jsonc, ~.kilo/plugin/aidd-context-hooks.js, -kilo.json

Baseline still holds kilo.json, the build emits .kilo/kilo.jsonc. The build is right, the snapshot was never recaptured after the move your own description announces. Note your verification list names tests/e2e/framework-build.e2e.test.ts; the failing one is tests/golden/framework-build-golden.e2e.test.ts.

The telemetry reason string is written two ways, in six places you added. profile.ts:46 says Kilo OpenTelemetry is experimental and not yet supported by AIDD., and registry-conformance.unit.test.ts:143, read-local-cost-sweep.unit.test.ts:81 and diagnose-telemetry-use-case.unit.test.ts:654 expect telemetry has not been measured. Three of the six failures are just that.

kilo is in the static id list but not guaranteed in the registry.

UnregisteredToolError: Tool 'kilo' is not registered.
  at getToolConfig src/contexts/tools/domain/registry.ts:67
  at hostMarketplaceRegistryReaders .../host-marketplace-registry-reader-adapter.ts:27
  at tests/contexts/framework/application/clean-native-cache.integration.test.ts:705

AI_TOOL_IDS is static in src/kernel/tool.ts, TOOL_REGISTRY is a Map filled at runtime by registerTool(). Any path iterating the ids and calling getToolConfig without the Kilo profile imported throws. Wiring probably saves us in production, but the trap is there and this test finds it.

Conflict with next on opencode-mcp-merge.ts, which #870 rewrote. Small one: keep your arrayEntries helper (used at 63-64) and take next's comment, its assertContributedServerUnchanged body stays below.

Minor

  • catches-that-swallow flags kilo-hooks-bridge.ts, but that catch is inside a template literal, so it is generated JS and not executed TS. The guard reads source text and cannot tell. Add a BASELINE entry with a reason rather than touching the code.
  • Bundle is at 653.7 KB for a 654 KB budget. Three tenths of a kilobyte left. Next addition breaks the build.
  • The description links cli/src/domain/tools/ai/kilo.ts, which does not exist. Real path is cli/src/contexts/tools/domain/profiles/kilo/. Description only.

One thing to flag in the PR itself

KILO_RUNTIME_SMOKE=1 means CI never runs your strongest claim. Without the flag the test skips; with it, on my machine, spawn kilo ENOENT, since Kilo is not installed. So "Kilo discovers the generated skills and agents and fires the guarded synchronization exactly once" rests on your local run and nothing else can confirm it. Please say so in the description, otherwise a future reader reads a skipped test as a passing one.

Merged with next I get 6759 passed, 7 failed, typecheck clean. Fix the six, rebase, regenerate the golden and I will take another look.

@waewoo
waewoo force-pushed the feat/kilo-code-support branch 2 times, most recently from acd794e to 91eff15 Compare September 21, 2026 15:04
@waewoo

waewoo commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review and for checking the generated Kilo tree and lifecycle behaviour.

For clarity, this PR adds end-to-end Kilo Code support to the framework, including:

  • the Kilo tool profile and runtime registry wiring;
  • generated Kilo skills, agents, project-local plugins and hook integration;
  • Kilo MCP configuration generation and runtime MCP discovery;
  • Kilo telemetry classification;
  • a real Kilo runtime smoke test covering discovery and session memory synchronisation;
  • CI integration for Kilo runtime validation.

The OpenCode MCP changes only resolve the merge with next while preserving the existing array handling and contribution-protection logic; they do not introduce a separate OpenCode feature.

All requested corrections have now been addressed:

  • The kilo:flat golden baseline was regenerated. It now expects .kilo/kilo.jsonc, the generated Kilo hook bridge, and no legacy kilo.json.
  • The Kilo telemetry reason is now canonical and consistent across the profile and all affected tests.
  • The Kilo profile is imported through runtime wiring, so every path iterating over AI_TOOL_IDS can resolve it from the registry.
  • The OpenCode MCP merge conflict with next was resolved while preserving both the arrayEntries handling and assertContributedServerUnchanged protection.
  • The generated Kilo hook bridge now reports dispatch failures explicitly, and the architecture guard passes without requiring a dedicated baseline exception.
  • The Kilo runtime smoke is now part of cli-ci.yml, installs @kilocode/cli@7.7.5, and is included in the required cli / gate.
  • The runtime smoke now verifies Kilo skill discovery, agent discovery, MCP discovery, project-local plugin loading, and the session.created memory-sync path.
  • The bundle budget was updated with an explicit rationale. The current build is 727.1 KB / 734 KB.

Validation completed locally:

  • Kilo real-runtime smoke: 1/1 passed.
  • Targeted MCP/OpenCode/Kilo tests: 26/26 passed.
  • Architecture tests: 139/139 passed.
  • Telemetry-related unit tests, including reporting, diagnosis and local-cost-sweep coverage, passed successfully.
  • Typecheck, type-honesty, Knip, build and bundle checks passed.
  • The full CLI suite was executed: 528 test files passed, with one unrelated failure in commit-session-trailer.integration.test.ts, where the local environment generates the Git trailer twice.
  • Coverage reproduced the same trailer failure and also hit a deterministic timeout in the golden-baseline test under instrumentation.
  • The smoke suite completed with 134 passing tests, one unrelated Claude local-scope failure, and one skipped test. No Kilo or MCP scenario failed.
  • Full mutation testing was not completed locally because the Stryker run is too expensive for the complete scope. The Kilo-specific mutation scope passed with 65.4%, above the 64% threshold.

I also identified two separate repository/tooling follow-ups that do not belong in this PR:

  1. The scripts-tests pre-commit command quotes its glob, so Node looks for the literal path scripts/__tests__/**/*.test.js even though test files exist. The manual run also exposed unrelated environment issues involving root permissions and a missing .aidd/config.json.
  2. The complete mutation scope is too slow for practical local validation and may need a separate optimization or scoping issue.

Those should be tracked separately rather than expanding this PR.

@waewoo
waewoo requested a review from blafourcade September 21, 2026 15:32
waewoo007 and others added 2 commits September 22, 2026 12:25
AIDD-Session-Id: 01a0c897-e6c0-78d0-8f7c-3e908106d4a9
AIDD-Session-Id: 01a0c897-e6c0-78d0-8f7c-3e908106d4a9
@blafourcade
blafourcade force-pushed the feat/kilo-code-support branch from bfa7fb9 to 2db7cc0 Compare September 22, 2026 19:19
@blafourcade

Copy link
Copy Markdown
Contributor

Thanks for the clarification.

I rebased the branch onto next and verified HEAD 2db7cc08. I also fixed the two remaining local gates:

  • the Kilo runtime smoke now resolves the installed binary before isolating its environment;
  • the Claude smoke uses distinct marketplace names per scope, avoiding silent host-level deduplication.

Final local validation:

  • pnpm typecheck && pnpm lint && pnpm test: 529 test files passed, 6,794 tests passed, 1 skipped;
  • pnpm test:e2e:kilo: 1/1 passed with real Kilo CLI 7.7.5;
  • pnpm smoke: 0 failures, 33/33 commands covered.

No remaining blocking issue identified in this PR. Ready to merge once CI is green.

@blafourcade blafourcade left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-verified on 2db7cc0: CI, Validate, CodeQL, cli CI, Windows, Kilo runtime smoke, coverage, and mutation gates all pass. Previous blocking findings are resolved.

@blafourcade
blafourcade merged commit c3a3355 into ai-driven-dev:next Sep 23, 2026
39 checks passed
@aidd-bot aidd-bot Bot mentioned this pull request Sep 24, 2026
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.

3 participants