Harness parity: prompt-time knowledge injection only wired for Claude Code and Codex
- Dominant language
- JavaScript
- Stars
- 26
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
## The gap
Prompt-time knowledge injection (`kk-prompt-context` → `src/lib/prompt-retrieval.ts`, the deterministic per-prompt retrieval surface) is a headline capability, but it ships on only **2 of 5** registered harnesses:
| Harness | Prompt-submit hook declared? | Prompt-time injection today |
|---|---|---|
| Claude Code | `UserPromptSubmit` → `kk-prompt-context.cjs` | ✅ |
| Codex CLI | `UserPromptSubmit` → `kk-prompt-context.cjs` | ✅ |
| Cursor | — (`stop` / `sessionEnd` / `preCompact` / `sessionStart`) | ❌ |
| OpenCode | — (`session.idle` / `session.created`) | ❌ |
| GitHub Copilot CLI | — (`sessionStart` / `sessionEnd` / `agentStop`) | ❌ |
Users on Cursor, OpenCode, and Copilot get SessionStart catalog injection but **not** the after-the-prompt-is-known, per-task retrieval block. That's a silent capability asymmetry: the same knowledge base gives a materially better experience depending on which harness you happen to use. Parity across harnesses is a core kenkeep value ("single install, every agent"), so this asymmetry should be closed or explicitly, visibly documented as a host limitation — not left implicit.
## Why it's currently gated (this is not arbitrary)
The capability is represented by an adapter declaring a **native** prompt-submit `HookSpec` whose output can inject additional context back to the model. Two constitution-level constraints mean we can't just fake it:
1. **No event-name translation across adapters** (AGENTS.md). We only wire a harness once its host emits a *genuinely native* prompt-submit event — we don't map some other event onto it.
2. **The hook must be able to return injected context.** Claude and Codex both expose `UserPromptSubmit` → `additionalContext`. The other three have not had an equivalent native channel verified.
So the three unwired harnesses stay unregistered *until a native prompt-context channel is verified* — deliberately fail-safe, but it has left a real parity gap that nobody is tracking. This issue tracks it.
## Investigation, per harness
Each harness needs a capability check answering two questions: **(a)** does the host emit a native event when the user submits a prompt, before the model runs? **(b)** does that event have a supported mechanism to inject text the model will see?
- [ ] **Cursor.** Cursor's hook system (`.cursor/hooks.json`, camelCase events) already carries `sessionStart` / `stop` / etc. Does it expose a `beforeSubmitPrompt` / `beforeShellExecution`-style *pre-prompt* hook, and can that hook return context injected into the model's turn? If yes → declare it in `cursorHookSpecs`, add `src/harnesses/cursor/hooks/kk-prompt-context.ts`, done.
- [ ] **OpenCode.** OpenCode is plugin-based (event bus → `kk-hooks/`). Is there a native `message`/`prompt`-submit event on the bus that fires before the model responds, with a way to append context to the prompt? If yes → subscribe in the plugin shim and dispatch to a prompt-context script.
- [ ] **GitHub Copilot CLI.** Hardest case: Copilot fires lifecycle hooks (`.github/hooks/`) but **has no `additionalContext` channel at all** — SessionStart already routes through a file-based sentinel bridge into `.github/copilot-instructions.md` (see [`practice-copilot-file-based-sessionstart-must-use-shared-context-builder`](.ai/kenkeep/nodes/practice-copilot-file-based-sessionstart-must-use-shared-context-builder.md)). Two sub-questions: is there any pre-prompt lifecycle event, and even if so, is there *any* transport to inject per-prompt context (the file bridge is session-scoped, not per-prompt)? If neither exists, prompt-time injection may be genuinely infeasible on Copilot today — in which case the deliverable is documentation, not code.
## Definition of done
For **each** of the three harnesses, land one of:
1. **Wired** — a native prompt-submit `HookSpec` + a `kk-prompt-context` hook reusing the shared `src/lib/prompt-retrieval.ts` core (no forked retrieval logic), with the same guarantees the existing two have: **synchronous, bounded by a short hard deadline, fails open** (no injected context on missing prompt/KB, malformed KB, or error), and the prompt is never logged. Add the harness to the prompt-injection regression coverage.
2. **Documented as unsupported** — a clear, discoverable statement (AGENTS.md + `docs/internals/hooks.md` + `doctor`'s per-harness block) that prompt-time injection is unavailable on that host, *why* (no native pre-prompt channel / no context-injection transport), and what would unblock it. `doctor` should surface it so a user on that harness isn't left guessing why their per-prompt retrieval never fires.
## Constraints (must respect)
- **No event-name translation.** Each adapter declares its host's real event name; do not introduce a global prompt-submit enum. (AGENTS.md — "No event-name translation across adapters.")
- **Shared retrieval core only.** Reuse `prompt-retrieval.ts`; do not fold prompt-time logic into `buildSessionStartContext`, and do not reimplement ranking per adapter.
- **Synchronous, never via the async launcher.** Context-producing hooks must stay sync (AGENTS.md — "Context-producing hooks MUST stay synchronous").
- **Fail open, never block.** A missing/slow prompt-context channel must degrade to zero injected context, never delay or break the user's turn.
## Non-goals
- Not a change to the ranking algorithm itself — this is purely about extending the *delivery* surface to the remaining harnesses.
- Not SessionStart injection (already at parity across all five).
- Not inventing a synthetic prompt-submit event where the host has none — if a host genuinely lacks the channel, document it rather than translating some other event onto it.
## Related
- Prompt-time injection design: `docs/internals/hooks.md#kk-prompt-contextcjs-prompt-time-injection`, `.ai/strikethroo/archive/56--prompt-time-knowledge-injection/`
- Copilot's context-injection limitation precedent: `practice-copilot-file-based-sessionstart-must-use-shared-context-builder`
- Eval coverage for the surface being extended: #109
Contributor guide
Research direction
Start with AGENTS.md and docs/internals/hooks.md, then inspect src/lib/prompt-retrieval.ts, cursorHookSpecs, the existing harness hook adapters, and the Copilot files under .github/hooks/. For Cursor, OpenCode, and GitHub Copilot CLI, verify whether a native pre-prompt event and context-injection transport exist. Done means each harness is either wired with shared retrieval and regression coverage or documented as unsupported in AGENTS.md, docs/internals/hooks.md, and doctor.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100