kibi-opencode 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/config.js +0 -4
- package/dist/index.d.ts +5 -0
- package/dist/index.js +22 -8
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +50 -2
- package/dist/prompt.js +30 -21
- package/dist/scheduler.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,6 +96,15 @@ The plugin injects guidance into OpenCode sessions to improve agent grounding. U
|
|
|
96
96
|
|
|
97
97
|
OpenCode exposes Kibi MCP prompts as slash commands. The `/init-kibi` command runs the retroactive bootstrap workflow using only public MCP tools.
|
|
98
98
|
|
|
99
|
+
### Discovery-first MCP guidance
|
|
100
|
+
|
|
101
|
+
Agent-visible guidance is intentionally limited to the curated public MCP surface:
|
|
102
|
+
|
|
103
|
+
- Discovery/reporting: `kb_search`, `kb_query`, `kb_status`, `kb_find_gaps`, `kb_coverage`, `kb_graph`
|
|
104
|
+
- Mutation/validation: `kb_upsert`, `kb_delete`, `kb_check`
|
|
105
|
+
|
|
106
|
+
The plugin guidance prefers `kb_search` for broad discovery, then `kb_query` for exact/source-linked follow-up.
|
|
107
|
+
|
|
99
108
|
### Background Sync Operations
|
|
100
109
|
|
|
101
110
|
Internal maintenance automatically syncs the knowledge base after relevant file edits:
|
|
@@ -141,6 +150,19 @@ Config files (project overrides global):
|
|
|
141
150
|
|
|
142
151
|
Per ADR-016, prompt text injection uses only `experimental.chat.system.transform`. The `chat.params` hook is reserved for model option enrichment (temperature, topP, etc.) and never carries prompt text.
|
|
143
152
|
|
|
153
|
+
### Logging Policy
|
|
154
|
+
|
|
155
|
+
The plugin follows a **silent-except-errors** policy for terminal output:
|
|
156
|
+
|
|
157
|
+
| Channel | Terminal | Structured log |
|
|
158
|
+
|---------|----------|---------------|
|
|
159
|
+
| Normal operation (sync success, guidance injection, session summaries) | No | Yes, via `client.app.log()` |
|
|
160
|
+
| Error-class events (bootstrap-needed, sync/check failure, hook/init failure) | Yes, via `console.error` | Yes, via `client.app.log()` |
|
|
161
|
+
|
|
162
|
+
Routine diagnostics route through [`client.app.log()`](https://opencode.ai/docs/plugins/) and never appear in the terminal. Only error-class events break terminal silence. This keeps the developer's workspace clean while preserving full visibility in structured logs for debugging.
|
|
163
|
+
|
|
164
|
+
The `experimental.chat.system.transform` hook handles prompt injection (see [Hook Policy](#hook-policy)). The `chat.params` hook is compatibility-only and never carries prompt text.
|
|
165
|
+
|
|
144
166
|
### Hook Modes
|
|
145
167
|
|
|
146
168
|
- `auto`: Use `experimental.chat.system.transform` (primary); `chat.params` is a no-op registration for host compatibility
|
|
@@ -186,6 +208,7 @@ This repository's OpenCode setup dogfoods local built artifacts. `opencode.json`
|
|
|
186
208
|
This is a thin bridge layer per ADR-016:
|
|
187
209
|
|
|
188
210
|
- **Agent-visible guidance**: Public MCP tools (`kb_query`, `kb_upsert`, `kb_check`, etc.) and sanctioned slash commands (`/init-kibi`)
|
|
211
|
+
- **Discovery-first workflow**: Agents are guided to use `kb_search` first, then `kb_query`, then reporting tools like `kb_status`, `kb_find_gaps`, `kb_coverage`, and `kb_graph` when needed
|
|
189
212
|
- **Internal maintenance**: Background sync operations handle KB synchronization; agents do NOT run sync commands directly
|
|
190
213
|
- Does NOT own KB storage, parsing, or validation
|
|
191
214
|
|
package/dist/config.js
CHANGED
|
@@ -132,10 +132,6 @@ export function loadConfig(projectDir = process.cwd()) {
|
|
|
132
132
|
if (projectObj)
|
|
133
133
|
merged = { ...merged, ...projectObj };
|
|
134
134
|
const validated = validateAndMerge(merged);
|
|
135
|
-
if (!validated) {
|
|
136
|
-
logger.warn("Configuration invalid, falling back to defaults");
|
|
137
|
-
return DEFAULTS;
|
|
138
|
-
}
|
|
139
135
|
return validated;
|
|
140
136
|
}
|
|
141
137
|
// implements REQ-opencode-kibi-plugin-v1
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
1
2
|
import { analyzeCodeFile, } from "./comment-analysis.js";
|
|
2
3
|
import * as config from "./config.js";
|
|
3
4
|
import * as fileFilter from "./file-filter.js";
|
|
4
5
|
import * as logger from "./logger.js";
|
|
5
|
-
import * as path from "node:path";
|
|
6
6
|
import { analyzePath } from "./path-kind.js";
|
|
7
|
-
import {
|
|
7
|
+
import { buildPrompt, SENTINEL } from "./prompt.js";
|
|
8
8
|
import { isMustPriorityRequirement } from "./requirement-doc.js";
|
|
9
9
|
import { createSyncScheduler } from "./scheduler.js";
|
|
10
10
|
import { getSessionTracker } from "./session-tracker.js";
|
|
@@ -56,9 +56,15 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
56
56
|
return {};
|
|
57
57
|
}
|
|
58
58
|
// Check workspace health for bootstrap nudges
|
|
59
|
+
// Reset the logger client first to avoid leaking a previous invocation's
|
|
60
|
+
// client into this instance, then set the new one if provided.
|
|
61
|
+
logger.resetClient();
|
|
62
|
+
if (input.client) {
|
|
63
|
+
logger.setClient(input.client);
|
|
64
|
+
}
|
|
59
65
|
const workspaceHealth = checkWorkspaceHealth(input.worktree);
|
|
60
66
|
if (workspaceHealth.needsBootstrap) {
|
|
61
|
-
logger.
|
|
67
|
+
logger.error("kibi-opencode: workspace needs Kibi bootstrap");
|
|
62
68
|
getSessionTracker().recordWarning("bootstrap-needed", input.worktree, "Workspace missing Kibi bootstrap");
|
|
63
69
|
}
|
|
64
70
|
// Log session summary periodically (gated on config)
|
|
@@ -131,7 +137,7 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
131
137
|
: suggestion.suggestionType === "adr"
|
|
132
138
|
? "long-comment-missed-adr"
|
|
133
139
|
: "missing-traceability";
|
|
134
|
-
logger.
|
|
140
|
+
logger.warn(`kibi-opencode: detected durable ${suggestion.suggestionType} knowledge in ${filePath}`);
|
|
135
141
|
getSessionTracker().recordWarning(warningCategory, filePath, `Consider routing this ${suggestion.suggestionType} knowledge to Kibi instead of inline comments: ${suggestion.reasoning}`);
|
|
136
142
|
}
|
|
137
143
|
}
|
|
@@ -172,15 +178,23 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
172
178
|
const hookMode = cfg.prompt.hookMode;
|
|
173
179
|
if (hookMode === "system-transform" || hookMode === "auto") {
|
|
174
180
|
hooks["experimental.chat.system.transform"] = async (_input, output) => {
|
|
175
|
-
|
|
176
|
-
|
|
181
|
+
// Skip if sentinel already present in any existing entry
|
|
182
|
+
if (output.system.some((entry) => entry.includes(SENTINEL))) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Build only the guidance block and append it; existing entries are preserved
|
|
186
|
+
const guidance = buildPrompt({
|
|
177
187
|
recentEdits,
|
|
178
188
|
workspaceHealth,
|
|
179
189
|
hasRecentKbEdit,
|
|
180
190
|
recentCommentSuggestion,
|
|
181
191
|
});
|
|
182
|
-
output.system.length
|
|
183
|
-
|
|
192
|
+
const last = output.system.length > 0
|
|
193
|
+
? output.system[output.system.length - 1]
|
|
194
|
+
: undefined;
|
|
195
|
+
if (last !== guidance) {
|
|
196
|
+
output.system.push(guidance);
|
|
197
|
+
}
|
|
184
198
|
};
|
|
185
199
|
}
|
|
186
200
|
if (hookMode === "chat-params" || hookMode === "auto") {
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface PluginClient {
|
|
2
|
+
app: {
|
|
3
|
+
log: (payload: Record<string, unknown>) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
export declare function setClient(c: PluginClient): void;
|
|
7
|
+
export declare function resetClient(): void;
|
|
1
8
|
export declare function info(msg: string): void;
|
|
2
9
|
export declare function warn(msg: string): void;
|
|
3
10
|
export declare function error(msg: string): void;
|
package/dist/logger.js
CHANGED
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
// implements REQ-opencode-kibi-plugin-v1
|
|
2
|
+
let client = null;
|
|
3
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
4
|
+
export function setClient(c) {
|
|
5
|
+
client = c;
|
|
6
|
+
}
|
|
7
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
8
|
+
export function resetClient() {
|
|
9
|
+
client = null;
|
|
10
|
+
}
|
|
11
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
2
12
|
export function info(msg) {
|
|
3
|
-
|
|
13
|
+
if (client) {
|
|
14
|
+
void client.app
|
|
15
|
+
.log({
|
|
16
|
+
body: {
|
|
17
|
+
service: "kibi-opencode",
|
|
18
|
+
level: "info",
|
|
19
|
+
message: msg,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
.catch(console.error);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Fallback when no client is available (e.g. during tests or early init)
|
|
4
26
|
}
|
|
27
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
5
28
|
export function warn(msg) {
|
|
6
|
-
|
|
29
|
+
if (client) {
|
|
30
|
+
void client.app
|
|
31
|
+
.log({
|
|
32
|
+
body: {
|
|
33
|
+
service: "kibi-opencode",
|
|
34
|
+
level: "warn",
|
|
35
|
+
message: msg,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
.catch(console.error);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Fallback when no client is available
|
|
7
42
|
}
|
|
8
43
|
// implements REQ-opencode-kibi-plugin-v1
|
|
9
44
|
export function error(msg) {
|
|
45
|
+
// Always emit to console for user visibility
|
|
10
46
|
console.error("[kibi-opencode]", msg);
|
|
47
|
+
// Also emit to structured logs if client is available
|
|
48
|
+
if (client) {
|
|
49
|
+
void client.app
|
|
50
|
+
.log({
|
|
51
|
+
body: {
|
|
52
|
+
service: "kibi-opencode",
|
|
53
|
+
level: "error",
|
|
54
|
+
message: msg,
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
.catch(console.error);
|
|
58
|
+
}
|
|
11
59
|
}
|
package/dist/prompt.js
CHANGED
|
@@ -13,8 +13,9 @@ function buildContextualGuidance(context) {
|
|
|
13
13
|
The Kibi knowledge base is managed through public MCP tools and internal maintenance flows. Direct manual edits to files under .kb/** can cause inconsistencies and should be avoided.
|
|
14
14
|
|
|
15
15
|
Instead:
|
|
16
|
+
- Use kb_search to discover relevant entities
|
|
16
17
|
- Use kb_upsert to create/update entities
|
|
17
|
-
- Use kb_query
|
|
18
|
+
- Use kb_query for exact lookup and source-linked follow-up
|
|
18
19
|
- Use kb_check to validate consistency
|
|
19
20
|
`);
|
|
20
21
|
}
|
|
@@ -26,7 +27,7 @@ This repository does not appear to have Kibi initialized. Agents should:
|
|
|
26
27
|
- Use \`/init-kibi\` for retroactive bootstrap of existing repos (preferred MCP command)
|
|
27
28
|
- Ask the user/operator to run setup or repair outside this session if \`/init-kibi\` is insufficient
|
|
28
29
|
|
|
29
|
-
Do not run \`kibi\` CLI commands directly; use the MCP tools (kb_query, kb_upsert, kb_delete, kb_check).
|
|
30
|
+
Do not run \`kibi\` CLI commands directly; use the public MCP tools (kb_search, kb_query, kb_status, kb_find_gaps, kb_coverage, kb_graph, kb_upsert, kb_delete, kb_check).
|
|
30
31
|
`);
|
|
31
32
|
}
|
|
32
33
|
const codeEdits = context.recentEdits.filter((e) => e.kind === "code");
|
|
@@ -77,9 +78,11 @@ This ensures behavior is documented and traceable.`;
|
|
|
77
78
|
routingMessage = `📝 **Code changes detected**
|
|
78
79
|
|
|
79
80
|
Before implementing or explaining code:
|
|
80
|
-
1. **
|
|
81
|
-
2. **
|
|
82
|
-
3. **
|
|
81
|
+
1. **Discover first** - Run kb_search to find related requirements, ADRs, tests, facts, and symbols.
|
|
82
|
+
2. **Follow up exactly** - Run kb_query by sourceFile, id, type, or tags once you know what you need.
|
|
83
|
+
3. **Check freshness when needed** - Run kb_status if you need branch or stale-state confirmation.
|
|
84
|
+
4. **Prefer Kibi over comments** - Store durable knowledge in KB entities instead of inline comments.
|
|
85
|
+
5. **Add traceability** - Add traceability comments to new or modified functions/classes so the pre-commit hook can verify coverage (e.g., \`// implements REQ-xxx\` in JS/TS or docstring references in Python).`;
|
|
83
86
|
}
|
|
84
87
|
parts.push(routingMessage);
|
|
85
88
|
}
|
|
@@ -88,9 +91,11 @@ Before implementing or explaining code:
|
|
|
88
91
|
📝 **Code changes detected**
|
|
89
92
|
|
|
90
93
|
Before implementing or explaining code:
|
|
91
|
-
1. **
|
|
92
|
-
2. **
|
|
93
|
-
3. **
|
|
94
|
+
1. **Discover first** - Run kb_search to find related requirements, ADRs, tests, facts, and symbols.
|
|
95
|
+
2. **Follow up exactly** - Run kb_query by sourceFile, id, type, or tags once you know what you need.
|
|
96
|
+
3. **Check freshness when needed** - Run kb_status if you need branch or stale-state confirmation.
|
|
97
|
+
4. **Prefer Kibi over comments** - Store durable knowledge in KB entities instead of inline comments.
|
|
98
|
+
5. **Add traceability** - Add traceability comments to new or modified functions/classes (e.g., \`// implements REQ-xxx\` in JS/TS or docstring references in Python) so the pre-commit hook can verify coverage.
|
|
94
99
|
|
|
95
100
|
If you're adding long explanatory comments, consider routing that knowledge to:
|
|
96
101
|
- \`FACT\` for domain invariants, properties, limits, cardinalities
|
|
@@ -129,7 +134,7 @@ When editing KB documentation:
|
|
|
129
134
|
if (parts.length === 1) {
|
|
130
135
|
parts.push(`This project uses Kibi (via MCP). Prefer storing durable knowledge in Kibi over code comments.
|
|
131
136
|
|
|
132
|
-
Before changing behavior:
|
|
137
|
+
Before changing behavior: use kb_search for discovery, then kb_query by sourceFile, id, type, or tags for exact follow-up; do not rely on undocumented tools.
|
|
133
138
|
|
|
134
139
|
Keep changed symbols traceable: add \`// implements REQ-xxx\` to every new or modified function/class so the pre-commit hook can verify coverage.
|
|
135
140
|
|
|
@@ -138,12 +143,14 @@ Run kb_check after KB mutations.
|
|
|
138
143
|
Dogfood note for this repo: OpenCode here uses local built \`kibi-mcp\` and \`kibi-opencode\` artifacts. If you change package versions or local package wiring, run \`bun run build\` before relying on OpenCode in this workspace.
|
|
139
144
|
|
|
140
145
|
**Kibi-first workflow:**
|
|
141
|
-
1. **Discover**: Run
|
|
142
|
-
2. **
|
|
143
|
-
3. **
|
|
144
|
-
4. **
|
|
146
|
+
1. **Discover**: Run kb_search to find relevant requirements, ADRs, tests, facts, and symbols.
|
|
147
|
+
2. **Confirm**: Run kb_query with sourceFile, id, type, or tags once you know the exact follow-up target.
|
|
148
|
+
3. **Inspect freshness**: Run kb_status when branch or stale-state confidence matters.
|
|
149
|
+
4. **Document intent**: If you are about to explain code, STOP. Route that explanation to kb_upsert instead of inline comments.
|
|
150
|
+
5. **Link during work**: When creating KB entities, include relationship rows: specified_by (req→scenario), verified_by (req→test), implements (symbol→req), covered_by (symbol→test).
|
|
151
|
+
6. **Validate**: Run kb_check after KB mutations to catch violations early.
|
|
145
152
|
|
|
146
|
-
**Public Kibi tools only:** kb_query, kb_upsert, kb_delete, kb_check.
|
|
153
|
+
**Public Kibi tools only:** kb_search, kb_query, kb_status, kb_find_gaps, kb_coverage, kb_graph, kb_upsert, kb_delete, kb_check.
|
|
147
154
|
|
|
148
155
|
Do not invoke Kibi CLI commands directly from the agent.
|
|
149
156
|
|
|
@@ -157,7 +164,7 @@ Bootstrap existing repos: use \`/init-kibi\` to run the retroactive initializati
|
|
|
157
164
|
const BASE_GUIDANCE = `${SENTINEL}
|
|
158
165
|
This project uses Kibi (via MCP). Prefer storing durable knowledge in Kibi over code comments.
|
|
159
166
|
|
|
160
|
-
Before changing behavior:
|
|
167
|
+
Before changing behavior: use kb_search for discovery, then kb_query by sourceFile, id, type, or tags for exact follow-up; do not rely on undocumented tools.
|
|
161
168
|
|
|
162
169
|
Keep changed symbols traceable: add \`// implements REQ-xxx\` to every new or modified function/class so the pre-commit hook can verify coverage.
|
|
163
170
|
|
|
@@ -166,12 +173,14 @@ Run kb_check after KB mutations.
|
|
|
166
173
|
Dogfood note for this repo: OpenCode here uses local built \`kibi-mcp\` and \`kibi-opencode\` artifacts. If you change package versions or local package wiring, run \`bun run build\` before relying on OpenCode in this workspace.
|
|
167
174
|
|
|
168
175
|
**Kibi-first workflow:**
|
|
169
|
-
1. **Discover**: Run
|
|
170
|
-
2. **
|
|
171
|
-
3. **
|
|
172
|
-
4. **
|
|
173
|
-
|
|
174
|
-
**
|
|
176
|
+
1. **Discover**: Run kb_search to find relevant requirements, ADRs, tests, facts, and symbols.
|
|
177
|
+
2. **Confirm**: Run kb_query with sourceFile, id, type, or tags once you know the exact follow-up target.
|
|
178
|
+
3. **Inspect freshness**: Run kb_status when branch or stale-state confidence matters.
|
|
179
|
+
4. **Document intent**: If you are about to explain code, STOP. Route that explanation to kb_upsert instead of inline comments.
|
|
180
|
+
5. **Link during work**: When creating KB entities, include relationship rows: specified_by (req→scenario), verified_by (req→test), implements (symbol→req), covered_by (symbol→test).
|
|
181
|
+
6. **Validate**: Run kb_check after KB mutations to catch violations early.
|
|
182
|
+
|
|
183
|
+
**Public Kibi tools only:** kb_search, kb_query, kb_status, kb_find_gaps, kb_coverage, kb_graph, kb_upsert, kb_delete, kb_check.
|
|
175
184
|
|
|
176
185
|
Do not invoke Kibi CLI commands directly from the agent.
|
|
177
186
|
|
package/dist/scheduler.js
CHANGED
|
@@ -114,7 +114,7 @@ class WorktreeSyncScheduler {
|
|
|
114
114
|
const checkResult = await this.runCheck(this.worktree, checkRules);
|
|
115
115
|
checkExitCode = checkResult.exitCode;
|
|
116
116
|
if (checkExitCode !== 0) {
|
|
117
|
-
logger.
|
|
117
|
+
logger.error(`check.failed ${JSON.stringify({ rules: checkRules, exitCode: checkExitCode })}`);
|
|
118
118
|
}
|
|
119
119
|
else {
|
|
120
120
|
logger.info(`check.succeeded ${JSON.stringify({ rules: checkRules })}`);
|
|
@@ -157,7 +157,7 @@ class WorktreeSyncScheduler {
|
|
|
157
157
|
logger.info(`sync.succeeded ${JSON.stringify(meta)}`);
|
|
158
158
|
}
|
|
159
159
|
else {
|
|
160
|
-
logger.
|
|
160
|
+
logger.error(`sync.failed ${JSON.stringify(meta)}`);
|
|
161
161
|
}
|
|
162
162
|
this.onRunComplete?.(meta);
|
|
163
163
|
}
|