kibi-cursor 0.2.0 → 0.2.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
3
  "displayName": "Kibi",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "description": "Optional Cursor adapter for Kibi. Requires SWI-Prolog 9+ and project-local kibi-cli, kibi-mcp, and kibi-core before the bundled MCP server can start.",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "author": {
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # kibi-cursor
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Kibi now gives agents clearer guidance for the diagnostics flow, so the release notes should reflect that the bundled usage text and MCP logging story were tightened together.
8
+
9
+ This update also keeps the package mirrors aligned where applicable, which helps downstream plugin consumers stay in sync with the canonical guidance.
10
+
11
+ - Hardened bundled skill guidance for kibi usage.
12
+ - Improved MCP diagnostic logging shape and validation hints.
13
+ - Synced packaged skill copies where they are shipped with the release.
14
+
15
+ ## 0.2.1
16
+
17
+ ### Patch Changes
18
+
19
+ - 5d2975a: Cursor stop hooks no longer inject a long multi-line Kibi freshness reminder after every agent response. Follow-ups are now one line, and most sessions stay silent.
20
+
21
+ - Track `kb_upsert`, `kb_delete`, and `kb_check` MCP usage during the session.
22
+ - Emit no stop follow-up when nothing KB-relevant changed, or when `kb_check` already ran after edits.
23
+ - Emit a short summary (`Kibi KB updated (kb_upsert).`) after KB mutations, or a single-line sync nudge when source files changed without KB activity.
24
+ - Fix publish workflow to build and pack `kibi-cursor` tarballs before npm publish.
25
+
26
+ - Cursor sessions now use Cursor's documented workspace root payload when deciding whether Kibi is already configured. This prevents the plugin from telling agents that Kibi needs bootstrapping just because the hook process is running from the plugin install directory instead of the actual workspace. The bootstrap reminder now names the missing `.kb/config.json` condition directly instead of implying MCP is unavailable.
27
+
28
+ - Parse `workspace_roots` from Cursor hook payloads and prefer the first workspace root for Kibi config detection.
29
+ - Add a regression test covering `sessionStart` without `cwd` when `workspace_roots` points at a configured workspace.
30
+ - Reword the bootstrap reminder to describe a missing workspace config rather than generic initialization failure.
31
+
3
32
  ## 0.2.0
4
33
 
5
34
  ### Minor Changes
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
3
  "displayName": "Kibi",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "description": "Optional Cursor adapter for Kibi. Requires SWI-Prolog 9+ and project-local kibi-cli, kibi-mcp, and kibi-core before the bundled MCP server can start.",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "author": {
@@ -2,6 +2,7 @@ export type HookEvent = "sessionStart" | "preToolUse" | "postToolUse" | "beforeR
2
2
  export type HookInput = {
3
3
  event: string;
4
4
  cwd?: string;
5
+ workspaceRoots?: readonly string[];
5
6
  toolName?: string;
6
7
  toolInput?: unknown;
7
8
  conversationId?: string;
@@ -10,6 +10,19 @@ function readString(record, keys) {
10
10
  }
11
11
  return undefined;
12
12
  }
13
+ function readStringArray(record, keys) {
14
+ for (const key of keys) {
15
+ const value = record[key];
16
+ if (!Array.isArray(value)) {
17
+ continue;
18
+ }
19
+ const strings = value.filter((item) => typeof item === "string" && item.length > 0);
20
+ if (strings.length > 0) {
21
+ return strings;
22
+ }
23
+ }
24
+ return undefined;
25
+ }
13
26
  function normalizeEventName(event) {
14
27
  const trimmed = event.trim();
15
28
  if (trimmed.length === 0) {
@@ -34,6 +47,10 @@ export function parseHookInput(input) {
34
47
  "current_working_directory",
35
48
  "workspace",
36
49
  ]);
50
+ const workspaceRoots = readStringArray(input, [
51
+ "workspace_roots",
52
+ "workspaceRoots",
53
+ ]);
37
54
  const toolName = readString(input, ["toolName", "tool_name", "tool"]);
38
55
  const toolInput = input.toolInput ?? input.tool_input ?? input.input;
39
56
  const conversationId = readString(input, [
@@ -45,6 +62,9 @@ export function parseHookInput(input) {
45
62
  if (cwd !== undefined) {
46
63
  parsed.cwd = cwd;
47
64
  }
65
+ if (workspaceRoots !== undefined) {
66
+ parsed.workspaceRoots = workspaceRoots;
67
+ }
48
68
  if (toolName !== undefined) {
49
69
  parsed.toolName = toolName;
50
70
  }
@@ -5,8 +5,8 @@ import path from "node:path";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { readGuidance, writeGuidance } from "./guidance.js";
7
7
  import { parseHookInput, parseStdinJson, readStdin } from "./hook-input.js";
8
- import { extractKbMcpToolName } from "./kb-mcp-tools.js";
9
8
  import { addDirtyPaths, clearSessionHookState, hasGuidedPath, loadHookState, recordKbMcpTool, rememberGuidedPath, resolveStateDir, } from "./hook-state.js";
9
+ import { extractKbMcpToolName } from "./kb-mcp-tools.js";
10
10
  import { BOOTSTRAP_REMINDER, DIRECT_KB_EDIT_WARNING, stopFollowupMessage, } from "./messages.js";
11
11
  import { extractExplicitPathFields, isDirectKbPath, isMeaningfulTrackedPath, toRepoRelativePath, } from "./path-policy.js";
12
12
  const editableTools = new Set([
@@ -33,7 +33,7 @@ function isReadLikeTool(toolName) {
33
33
  return toolName === undefined || readTools.has(toolName);
34
34
  }
35
35
  function resolveWorkspaceRoot(input) {
36
- return input.cwd ?? process.cwd();
36
+ return input.workspaceRoots?.[0] ?? input.cwd ?? process.cwd();
37
37
  }
38
38
  function resolvePrimaryPath(input) {
39
39
  if (input.filePath) {
@@ -231,7 +231,9 @@ export function recordKbMcpTool(stateDir, toolName) {
231
231
  if (normalized === "kb_upsert" || normalized === "kb_delete") {
232
232
  return {
233
233
  ...state,
234
- kbMutationTools: mergeStringPaths(state.kbMutationTools, [normalized]).slice(-maxKbMutationTools),
234
+ kbMutationTools: mergeStringPaths(state.kbMutationTools, [
235
+ normalized,
236
+ ]).slice(-maxKbMutationTools),
235
237
  };
236
238
  }
237
239
  return state;
@@ -27,7 +27,11 @@ export function extractKbMcpToolName(toolName, toolInput) {
27
27
  }
28
28
  const nestedArgs = toolInput.arguments ?? toolInput.args;
29
29
  if (isRecord(nestedArgs)) {
30
- const nestedTool = readString(nestedArgs, ["toolName", "tool_name", "name"]);
30
+ const nestedTool = readString(nestedArgs, [
31
+ "toolName",
32
+ "tool_name",
33
+ "name",
34
+ ]);
31
35
  if (nestedTool?.startsWith("kb_")) {
32
36
  return nestedTool;
33
37
  }
@@ -1,5 +1,5 @@
1
1
  import type { HookState } from "./hook-state.js";
2
- export declare const BOOTSTRAP_REMINDER = "Kibi is not initialized for this workspace. Use the Kibi MCP workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
2
+ export declare const BOOTSTRAP_REMINDER = "Kibi config was not found at the Cursor workspace root. Use the Kibi MCP /init-kibi workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
3
3
  export declare const DIRECT_KB_EDIT_WARNING = "Avoid direct edits to .kb/. Use Kibi MCP tools for KB discovery and mutations so project memory stays valid.";
4
4
  export declare function stopFollowupMessage(state: HookState): string | undefined;
5
5
  /** @deprecated Use stopFollowupMessage */
package/dist/messages.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isKbFreshnessRelevantPath } from "./path-policy.js";
2
- export const BOOTSTRAP_REMINDER = "Kibi is not initialized for this workspace. Use the Kibi MCP workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
2
+ export const BOOTSTRAP_REMINDER = "Kibi config was not found at the Cursor workspace root. Use the Kibi MCP /init-kibi workflow to bootstrap project memory before relying on KB lookups; do not edit .kb/ files directly.";
3
3
  export const DIRECT_KB_EDIT_WARNING = "Avoid direct edits to .kb/. Use Kibi MCP tools for KB discovery and mutations so project memory stays valid.";
4
4
  export function stopFollowupMessage(state) {
5
5
  if (state.kbMutationTools.length > 0) {
@@ -1,23 +1,216 @@
1
1
  ---
2
- name: kibi-usage
3
- description: Use Kibi MCP discovery tools to find relevant requirements and context before editing code.
2
+ id: kibi-usage
3
+ name: Kibi Usage
4
+ description: Guides agents to use Kibi MCP, facts, relationships, and validation correctly
5
+ version: 1.0.0
6
+ kibiCompatibility: ">=0.11.0"
7
+ tags:
8
+ - kibi
9
+ - mcp
10
+ - knowledge-base
11
+ - traceability
12
+ - agent-guidance
13
+ resources:
14
+ - resources/relationship-directions.md
15
+ - resources/fact-lanes.md
16
+ - resources/workflows.md
4
17
  ---
5
18
 
6
- ## Goal
19
+ # Kibi Usage
7
20
 
8
- Help an agent discover existing knowledge in Kibi before making changes.
21
+ Consult this skill before any Kibi knowledge base operation, on first interaction with a Kibi-enabled repo, after detecting stale or dirty KB status, and before performing mutations.
9
22
 
10
- ## MCP workflow
23
+ ## MCP-Only Rules
11
24
 
12
- - Start with `kb_search` using domain keywords and requirement intent.
13
- - Move to `kb_query` for exact entity retrieval by `id` or `type`.
14
- - Use `kb_status` when context is stale or branch linkage is unclear.
15
- - Use curated reports only when the question needs them: `kb_find_gaps`, `kb_coverage`, or `kb_graph`.
16
- - Mutate only through `kb_upsert` or `kb_delete`, then validate with `kb_check`.
25
+ Interact with the knowledge base exclusively through MCP tools. Do not read or edit files inside `.kb/` directly. Do not run any `kibi` CLI commands from the agent session. The MCP surface is the only sanctioned interface for agents.
17
26
 
18
- ## Guidance
27
+ ### Tool Name Prefixes
19
28
 
20
- - Prefer source-linked lookups and traceability-aware retrieval via `kb_query` filters.
21
- - Never open or patch files under `.kb/` directly.
22
- - When unsure about scope, re-run `kb_search` with tighter terms, then validate with `kb_query`.
23
- - Report the KB outcome before completion: updated, no-impact with rationale, or deferred/failed.
29
+ Kibi's canonical MCP names are `kb_search`, `kb_query`, `kb_upsert`, `kb_check`, and related `kb_*` tools. Some hosts add a server prefix when exposing tools to agents. In OpenCode, use the visible `kibi_kb_search`, `kibi_kb_query`, `kibi_kb_upsert`, and `kibi_kb_check` names when exact tool identifiers are required; they map to the same canonical MCP names.
30
+
31
+ ## Discovery-First Workflow
32
+
33
+ Always discover before you mutate. Start with `kb_search` for exploratory discovery across metadata and markdown body text. Split broad queries into 1-3 focused probes. Review top hits for relevance before concluding the KB lacks knowledge.
34
+
35
+ Follow up with `kb_query` for exact lookups by `id`, `type`, `tags`, or `sourceFile`. Call `kb_status` to inspect branch attachment and freshness when stale context would affect decisions. Only after discovery and confirmation should you mutate.
36
+
37
+ ## Relationship Directions
38
+
39
+ Relationship direction is fixed and semantic. Getting it wrong breaks traceability queries and validation.
40
+
41
+ | Relationship | Direction | Meaning |
42
+ |-------------|-----------|---------|
43
+ | `implements` | symbol -> req | Symbol owns or implements requirement behavior |
44
+ | `specified_by` | req -> scenario | Requirement is specified by a scenario |
45
+ | `verified_by` | req/scenario -> test | Requirement or scenario is verified by a test |
46
+ | `validates` | test -> req/scenario | Test validates a requirement or scenario |
47
+ | `executable_for` | symbol -> test | Symbol is executable test code for a test entity |
48
+ | `constrains` | req -> fact(subject) | Requirement constrains a domain fact |
49
+ | `requires_property` | req -> fact(property_value) | Requirement requires a property value |
50
+ | `supersedes` | old-req -> new-req | Old requirement is replaced by new requirement |
51
+ | `covered_by` | symbol -> test | Production symbol has coverage evidence from a test |
52
+
53
+ See `resources/relationship-directions.md` for detailed payload examples.
54
+
55
+ ## Symbol-First Traceability
56
+
57
+ Trace code through `symbol` entities, not inline legacy comments. Do not use legacy `// implements REQ-xxx` comments as the primary marker for new or modified code. If a symbol is new or its requirement ownership changes, create or update the `symbol` entity and add an `implements` relationship from the symbol to the requirement.
58
+
59
+ Use comments only as a temporary backward-compatibility fallback when the symbol manifest cannot be updated in the same task. Prefer durable symbol coordinates in `documentation/symbols.yaml` and `documentation/symbol-coordinates.yaml`, then link those symbols through MCP relationships.
60
+
61
+ ```yaml
62
+ # Preferred traceability model
63
+ symbol:
64
+ id: SYM-admin-billing-policy
65
+ title: Admin billing policy check
66
+ status: active
67
+ relationships:
68
+ - type: implements
69
+ from: SYM-admin-billing-policy
70
+ to: REQ-ADMIN-BILLING-POLICY
71
+ ```
72
+
73
+ ## Strict Fact Lane
74
+
75
+ Normative requirements that must participate in contradiction blocking use the strict fact lane. Create a `fact_kind: subject` fact and link it from the requirement via `constrains`. Create a `fact_kind: property_value` fact and link it via `requires_property`.
76
+
77
+ ```yaml
78
+ # Fact entity
79
+ id: FACT-USER-ROLE
80
+ title: User Role Assignment
81
+ status: active
82
+ fact_kind: subject
83
+ subject_key: user.role_assignment
84
+
85
+ # Requirement entity
86
+ id: REQ-019
87
+ title: Users can have up to 3 roles
88
+ status: open
89
+ relationships:
90
+ - type: constrains
91
+ from: REQ-019
92
+ to: FACT-USER-ROLE
93
+ - type: requires_property
94
+ from: REQ-019
95
+ to: FACT-LIMIT-3
96
+ ```
97
+
98
+ See `resources/fact-lanes.md` for the full strict vs observation lane comparison.
99
+
100
+ ### Granular fact examples for coherence checks
101
+
102
+ Model one semantic claim per strict `property_value` fact. Reusing the same `subject_key` and `property_key` lets `domain-contradictions` compare requirements mechanically.
103
+
104
+ Incoherent role-set example: `REQ-ROLE-SET-2` says the allowed user roles are exactly `[user, admin]`, while `REQ-ROLE-SET-3` says the same property is exactly `[user, admin, superadmin]`. Both constrain `FACT-USER-ROLES` and require different values for `user.roles.allowed_set`, so they cannot both be current.
105
+
106
+ ```yaml
107
+ subject:
108
+ id: FACT-USER-ROLES
109
+ fact_kind: subject
110
+ subject_key: user.roles
111
+
112
+ property_values:
113
+ - id: FACT-USER-ROLES-ALLOWED-2
114
+ fact_kind: property_value
115
+ subject_key: user.roles
116
+ property_key: user.roles.allowed_set
117
+ operator: eq
118
+ value_type: list
119
+ value_json: '["user", "admin"]'
120
+ - id: FACT-USER-ROLES-ALLOWED-3
121
+ fact_kind: property_value
122
+ subject_key: user.roles
123
+ property_key: user.roles.allowed_set
124
+ operator: eq
125
+ value_type: list
126
+ value_json: '["user", "admin", "superadmin"]'
127
+
128
+ requirements:
129
+ - id: REQ-ROLE-SET-2
130
+ relationships:
131
+ - { type: constrains, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES }
132
+ - { type: requires_property, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES-ALLOWED-2 }
133
+ - id: REQ-ROLE-SET-3
134
+ relationships:
135
+ - { type: constrains, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES }
136
+ - { type: requires_property, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES-ALLOWED-3 }
137
+ ```
138
+
139
+ Incoherent permission example: `REQ-ADMIN-CAN-MANAGE-BILLING` says `admin` can manage billing, while `REQ-ONLY-SUPERADMIN-MANAGES-BILLING` says the only allowed actor is `superadmin`. Model both against `billing.manage.allowed_actor` with `operator: eq` so the conflict is explicit.
140
+
141
+ ```yaml
142
+ property_values:
143
+ - id: FACT-BILLING-MANAGE-ACTOR-ADMIN
144
+ fact_kind: property_value
145
+ subject_key: billing.manage
146
+ property_key: billing.manage.allowed_actor
147
+ operator: eq
148
+ value_type: string
149
+ value_string: admin
150
+ - id: FACT-BILLING-MANAGE-ACTOR-SUPERADMIN
151
+ fact_kind: property_value
152
+ subject_key: billing.manage
153
+ property_key: billing.manage.allowed_actor
154
+ operator: eq
155
+ value_type: string
156
+ value_string: superadmin
157
+ ```
158
+
159
+ If a new requirement intentionally changes a value, create a replacement requirement and link the old requirement to the new one with `supersedes` instead of leaving two current contradictory requirements.
160
+
161
+ ## Fact vs Flag
162
+
163
+ Use `flag` for runtime or config gates only. Feature flags, kill-switches, and deferred capabilities are valid `flag` entities.
164
+
165
+ Bugs, incidents, and workarounds belong in `fact` entities with `fact_kind: observation` or `meta`. These fact kinds are excluded from contradiction inference, making them appropriate for non-blocking evidence.
166
+
167
+ Anti-example: do not create a `flag` named `BUG-123` to track a defect. Create a `fact` with `fact_kind: observation` instead.
168
+
169
+ ## Create-Before-Link
170
+
171
+ Always confirm or create endpoint entities before linking them. Query target IDs with `kb_query` first. If an endpoint does not exist, create it with `kb_upsert` before creating the relationship. Creating relationships to non-existent entities produces dangling references that `kb_check` will flag.
172
+
173
+ For `kb_upsert`, keep relationship rows anchored to the entity you are upserting: each row's `from` must equal the upserted entity ID. If you need a `SYM -> REQ` link, upsert the symbol endpoint first, then link that symbol to the requirement.
174
+
175
+ Keep symbol payloads minimal: include only the fields needed to identify the symbol, its status, and its source traceability. Put extra prose, examples, or audit notes in docs or evidence files instead of custom `kb_upsert.properties`; strict `kb_upsert.properties` rejects unknown fields.
176
+
177
+ When a generic `Query failed` appears, do not keep retrying the same payload. First call `kb_validate_upsert`, query or create the missing endpoints, reduce the payload to the minimum required fields, and retry once. If it still fails, report the blocker instead of looping.
178
+
179
+ ## Sequential Upserts
180
+
181
+ Never fire `kb_upsert` calls in parallel. Execute them sequentially to avoid lock contention and ensure deterministic ordering. This is especially important when creating chains of related entities.
182
+
183
+ ## Targeted and Final Checks
184
+
185
+ Run `kb_check` with specific rules during iteration for fast feedback. For example, use `rules: ["required-fields", "no-dangling-refs"]` after small changes. Run a full `kb_check` without rule filters before declaring work complete.
186
+
187
+ ## Domain Contradictions and Evolution
188
+
189
+ The `domain-contradictions` rule detects conflicts between strict-lane facts linked to requirements. When a contradiction is found, the supported escape hatch is `supersedes`: create a new requirement that supersedes the old one, then link the new requirement to updated facts.
190
+
191
+ Use `kb_model_requirement` for automated strict-fact modeling. It generates the subject and property_value facts, links them via `constrains` and `requires_property`, and handles low-confidence downgrades to `observation` facts automatically.
192
+
193
+ ## Stale or Dirty KB Handling
194
+
195
+ Call `kb_status` when you suspect the branch KB is stale or when switching context. Report freshness findings to the user rather than relying on outdated KB context. If `kb_status` indicates a schema migration is needed, ask the user or operator to handle it outside the agent session.
196
+
197
+ ## Anti-Patterns and Remediation
198
+
199
+ | Anti-Pattern | Problem | Remediation |
200
+ |-------------|---------|-------------|
201
+ | Reversed relationship direction | Traceability queries break | Verify direction against the relationship table above |
202
+ | Legacy implements comments | Comments are not durable queryable symbols | Create or update a `symbol` entity and link it to the requirement |
203
+ | Bug-as-flag | `flag` misused for defect tracking | Use `fact` with `fact_kind: observation` or `meta` |
204
+ | Parallel upserts | Lock contention and nondeterminism | Execute `kb_upsert` calls sequentially |
205
+ | Embedded scenarios in reqs | Violates canonical traceability chain | Create separate `req`, `scen`, and `test` entities |
206
+ | Missing `kb_check` | Undetected dangling refs and violations | Run targeted checks during work, full check at completion |
207
+ | Tags as multi-ID lookup | Tags are metadata, not identifiers | Use `kb_query` with explicit `id` values |
208
+ | `relates_to` for strict modeling | Loses contradiction safety | Use `constrains` and `requires_property` instead |
209
+ | `status: implemented` on requirements | Not a valid lifecycle status | Use a valid status such as `closed`, add an `implemented` tag, and link evidence instead |
210
+
211
+ Before/after for reversed direction:
212
+
213
+ - Wrong: `relationships: [{ type: "implements", from: "REQ-001", to: "SYM-001" }]`
214
+ - Right: `relationships: [{ type: "implements", from: "SYM-001", to: "REQ-001" }]`
215
+
216
+ See `resources/workflows.md` for the golden-path discovery to validation sequence.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cursor",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Kibi Cursor plugin - thin adapter for Cursor MCP integration and editor hooks",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,23 +1,216 @@
1
1
  ---
2
- name: kibi-usage
3
- description: Use Kibi MCP discovery tools to find relevant requirements and context before editing code.
2
+ id: kibi-usage
3
+ name: Kibi Usage
4
+ description: Guides agents to use Kibi MCP, facts, relationships, and validation correctly
5
+ version: 1.0.0
6
+ kibiCompatibility: ">=0.11.0"
7
+ tags:
8
+ - kibi
9
+ - mcp
10
+ - knowledge-base
11
+ - traceability
12
+ - agent-guidance
13
+ resources:
14
+ - resources/relationship-directions.md
15
+ - resources/fact-lanes.md
16
+ - resources/workflows.md
4
17
  ---
5
18
 
6
- ## Goal
19
+ # Kibi Usage
7
20
 
8
- Help an agent discover existing knowledge in Kibi before making changes.
21
+ Consult this skill before any Kibi knowledge base operation, on first interaction with a Kibi-enabled repo, after detecting stale or dirty KB status, and before performing mutations.
9
22
 
10
- ## MCP workflow
23
+ ## MCP-Only Rules
11
24
 
12
- - Start with `kb_search` using domain keywords and requirement intent.
13
- - Move to `kb_query` for exact entity retrieval by `id` or `type`.
14
- - Use `kb_status` when context is stale or branch linkage is unclear.
15
- - Use curated reports only when the question needs them: `kb_find_gaps`, `kb_coverage`, or `kb_graph`.
16
- - Mutate only through `kb_upsert` or `kb_delete`, then validate with `kb_check`.
25
+ Interact with the knowledge base exclusively through MCP tools. Do not read or edit files inside `.kb/` directly. Do not run any `kibi` CLI commands from the agent session. The MCP surface is the only sanctioned interface for agents.
17
26
 
18
- ## Guidance
27
+ ### Tool Name Prefixes
19
28
 
20
- - Prefer source-linked lookups and traceability-aware retrieval via `kb_query` filters.
21
- - Never open or patch files under `.kb/` directly.
22
- - When unsure about scope, re-run `kb_search` with tighter terms, then validate with `kb_query`.
23
- - Report the KB outcome before completion: updated, no-impact with rationale, or deferred/failed.
29
+ Kibi's canonical MCP names are `kb_search`, `kb_query`, `kb_upsert`, `kb_check`, and related `kb_*` tools. Some hosts add a server prefix when exposing tools to agents. In OpenCode, use the visible `kibi_kb_search`, `kibi_kb_query`, `kibi_kb_upsert`, and `kibi_kb_check` names when exact tool identifiers are required; they map to the same canonical MCP names.
30
+
31
+ ## Discovery-First Workflow
32
+
33
+ Always discover before you mutate. Start with `kb_search` for exploratory discovery across metadata and markdown body text. Split broad queries into 1-3 focused probes. Review top hits for relevance before concluding the KB lacks knowledge.
34
+
35
+ Follow up with `kb_query` for exact lookups by `id`, `type`, `tags`, or `sourceFile`. Call `kb_status` to inspect branch attachment and freshness when stale context would affect decisions. Only after discovery and confirmation should you mutate.
36
+
37
+ ## Relationship Directions
38
+
39
+ Relationship direction is fixed and semantic. Getting it wrong breaks traceability queries and validation.
40
+
41
+ | Relationship | Direction | Meaning |
42
+ |-------------|-----------|---------|
43
+ | `implements` | symbol -> req | Symbol owns or implements requirement behavior |
44
+ | `specified_by` | req -> scenario | Requirement is specified by a scenario |
45
+ | `verified_by` | req/scenario -> test | Requirement or scenario is verified by a test |
46
+ | `validates` | test -> req/scenario | Test validates a requirement or scenario |
47
+ | `executable_for` | symbol -> test | Symbol is executable test code for a test entity |
48
+ | `constrains` | req -> fact(subject) | Requirement constrains a domain fact |
49
+ | `requires_property` | req -> fact(property_value) | Requirement requires a property value |
50
+ | `supersedes` | old-req -> new-req | Old requirement is replaced by new requirement |
51
+ | `covered_by` | symbol -> test | Production symbol has coverage evidence from a test |
52
+
53
+ See `resources/relationship-directions.md` for detailed payload examples.
54
+
55
+ ## Symbol-First Traceability
56
+
57
+ Trace code through `symbol` entities, not inline legacy comments. Do not use legacy `// implements REQ-xxx` comments as the primary marker for new or modified code. If a symbol is new or its requirement ownership changes, create or update the `symbol` entity and add an `implements` relationship from the symbol to the requirement.
58
+
59
+ Use comments only as a temporary backward-compatibility fallback when the symbol manifest cannot be updated in the same task. Prefer durable symbol coordinates in `documentation/symbols.yaml` and `documentation/symbol-coordinates.yaml`, then link those symbols through MCP relationships.
60
+
61
+ ```yaml
62
+ # Preferred traceability model
63
+ symbol:
64
+ id: SYM-admin-billing-policy
65
+ title: Admin billing policy check
66
+ status: active
67
+ relationships:
68
+ - type: implements
69
+ from: SYM-admin-billing-policy
70
+ to: REQ-ADMIN-BILLING-POLICY
71
+ ```
72
+
73
+ ## Strict Fact Lane
74
+
75
+ Normative requirements that must participate in contradiction blocking use the strict fact lane. Create a `fact_kind: subject` fact and link it from the requirement via `constrains`. Create a `fact_kind: property_value` fact and link it via `requires_property`.
76
+
77
+ ```yaml
78
+ # Fact entity
79
+ id: FACT-USER-ROLE
80
+ title: User Role Assignment
81
+ status: active
82
+ fact_kind: subject
83
+ subject_key: user.role_assignment
84
+
85
+ # Requirement entity
86
+ id: REQ-019
87
+ title: Users can have up to 3 roles
88
+ status: open
89
+ relationships:
90
+ - type: constrains
91
+ from: REQ-019
92
+ to: FACT-USER-ROLE
93
+ - type: requires_property
94
+ from: REQ-019
95
+ to: FACT-LIMIT-3
96
+ ```
97
+
98
+ See `resources/fact-lanes.md` for the full strict vs observation lane comparison.
99
+
100
+ ### Granular fact examples for coherence checks
101
+
102
+ Model one semantic claim per strict `property_value` fact. Reusing the same `subject_key` and `property_key` lets `domain-contradictions` compare requirements mechanically.
103
+
104
+ Incoherent role-set example: `REQ-ROLE-SET-2` says the allowed user roles are exactly `[user, admin]`, while `REQ-ROLE-SET-3` says the same property is exactly `[user, admin, superadmin]`. Both constrain `FACT-USER-ROLES` and require different values for `user.roles.allowed_set`, so they cannot both be current.
105
+
106
+ ```yaml
107
+ subject:
108
+ id: FACT-USER-ROLES
109
+ fact_kind: subject
110
+ subject_key: user.roles
111
+
112
+ property_values:
113
+ - id: FACT-USER-ROLES-ALLOWED-2
114
+ fact_kind: property_value
115
+ subject_key: user.roles
116
+ property_key: user.roles.allowed_set
117
+ operator: eq
118
+ value_type: list
119
+ value_json: '["user", "admin"]'
120
+ - id: FACT-USER-ROLES-ALLOWED-3
121
+ fact_kind: property_value
122
+ subject_key: user.roles
123
+ property_key: user.roles.allowed_set
124
+ operator: eq
125
+ value_type: list
126
+ value_json: '["user", "admin", "superadmin"]'
127
+
128
+ requirements:
129
+ - id: REQ-ROLE-SET-2
130
+ relationships:
131
+ - { type: constrains, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES }
132
+ - { type: requires_property, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES-ALLOWED-2 }
133
+ - id: REQ-ROLE-SET-3
134
+ relationships:
135
+ - { type: constrains, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES }
136
+ - { type: requires_property, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES-ALLOWED-3 }
137
+ ```
138
+
139
+ Incoherent permission example: `REQ-ADMIN-CAN-MANAGE-BILLING` says `admin` can manage billing, while `REQ-ONLY-SUPERADMIN-MANAGES-BILLING` says the only allowed actor is `superadmin`. Model both against `billing.manage.allowed_actor` with `operator: eq` so the conflict is explicit.
140
+
141
+ ```yaml
142
+ property_values:
143
+ - id: FACT-BILLING-MANAGE-ACTOR-ADMIN
144
+ fact_kind: property_value
145
+ subject_key: billing.manage
146
+ property_key: billing.manage.allowed_actor
147
+ operator: eq
148
+ value_type: string
149
+ value_string: admin
150
+ - id: FACT-BILLING-MANAGE-ACTOR-SUPERADMIN
151
+ fact_kind: property_value
152
+ subject_key: billing.manage
153
+ property_key: billing.manage.allowed_actor
154
+ operator: eq
155
+ value_type: string
156
+ value_string: superadmin
157
+ ```
158
+
159
+ If a new requirement intentionally changes a value, create a replacement requirement and link the old requirement to the new one with `supersedes` instead of leaving two current contradictory requirements.
160
+
161
+ ## Fact vs Flag
162
+
163
+ Use `flag` for runtime or config gates only. Feature flags, kill-switches, and deferred capabilities are valid `flag` entities.
164
+
165
+ Bugs, incidents, and workarounds belong in `fact` entities with `fact_kind: observation` or `meta`. These fact kinds are excluded from contradiction inference, making them appropriate for non-blocking evidence.
166
+
167
+ Anti-example: do not create a `flag` named `BUG-123` to track a defect. Create a `fact` with `fact_kind: observation` instead.
168
+
169
+ ## Create-Before-Link
170
+
171
+ Always confirm or create endpoint entities before linking them. Query target IDs with `kb_query` first. If an endpoint does not exist, create it with `kb_upsert` before creating the relationship. Creating relationships to non-existent entities produces dangling references that `kb_check` will flag.
172
+
173
+ For `kb_upsert`, keep relationship rows anchored to the entity you are upserting: each row's `from` must equal the upserted entity ID. If you need a `SYM -> REQ` link, upsert the symbol endpoint first, then link that symbol to the requirement.
174
+
175
+ Keep symbol payloads minimal: include only the fields needed to identify the symbol, its status, and its source traceability. Put extra prose, examples, or audit notes in docs or evidence files instead of custom `kb_upsert.properties`; strict `kb_upsert.properties` rejects unknown fields.
176
+
177
+ When a generic `Query failed` appears, do not keep retrying the same payload. First call `kb_validate_upsert`, query or create the missing endpoints, reduce the payload to the minimum required fields, and retry once. If it still fails, report the blocker instead of looping.
178
+
179
+ ## Sequential Upserts
180
+
181
+ Never fire `kb_upsert` calls in parallel. Execute them sequentially to avoid lock contention and ensure deterministic ordering. This is especially important when creating chains of related entities.
182
+
183
+ ## Targeted and Final Checks
184
+
185
+ Run `kb_check` with specific rules during iteration for fast feedback. For example, use `rules: ["required-fields", "no-dangling-refs"]` after small changes. Run a full `kb_check` without rule filters before declaring work complete.
186
+
187
+ ## Domain Contradictions and Evolution
188
+
189
+ The `domain-contradictions` rule detects conflicts between strict-lane facts linked to requirements. When a contradiction is found, the supported escape hatch is `supersedes`: create a new requirement that supersedes the old one, then link the new requirement to updated facts.
190
+
191
+ Use `kb_model_requirement` for automated strict-fact modeling. It generates the subject and property_value facts, links them via `constrains` and `requires_property`, and handles low-confidence downgrades to `observation` facts automatically.
192
+
193
+ ## Stale or Dirty KB Handling
194
+
195
+ Call `kb_status` when you suspect the branch KB is stale or when switching context. Report freshness findings to the user rather than relying on outdated KB context. If `kb_status` indicates a schema migration is needed, ask the user or operator to handle it outside the agent session.
196
+
197
+ ## Anti-Patterns and Remediation
198
+
199
+ | Anti-Pattern | Problem | Remediation |
200
+ |-------------|---------|-------------|
201
+ | Reversed relationship direction | Traceability queries break | Verify direction against the relationship table above |
202
+ | Legacy implements comments | Comments are not durable queryable symbols | Create or update a `symbol` entity and link it to the requirement |
203
+ | Bug-as-flag | `flag` misused for defect tracking | Use `fact` with `fact_kind: observation` or `meta` |
204
+ | Parallel upserts | Lock contention and nondeterminism | Execute `kb_upsert` calls sequentially |
205
+ | Embedded scenarios in reqs | Violates canonical traceability chain | Create separate `req`, `scen`, and `test` entities |
206
+ | Missing `kb_check` | Undetected dangling refs and violations | Run targeted checks during work, full check at completion |
207
+ | Tags as multi-ID lookup | Tags are metadata, not identifiers | Use `kb_query` with explicit `id` values |
208
+ | `relates_to` for strict modeling | Loses contradiction safety | Use `constrains` and `requires_property` instead |
209
+ | `status: implemented` on requirements | Not a valid lifecycle status | Use a valid status such as `closed`, add an `implemented` tag, and link evidence instead |
210
+
211
+ Before/after for reversed direction:
212
+
213
+ - Wrong: `relationships: [{ type: "implements", from: "REQ-001", to: "SYM-001" }]`
214
+ - Right: `relationships: [{ type: "implements", from: "SYM-001", to: "REQ-001" }]`
215
+
216
+ See `resources/workflows.md` for the golden-path discovery to validation sequence.