kibi-cursor 0.3.1 → 0.5.1
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/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +92 -0
- package/README.md +21 -4
- package/agent-plugin/mcp.json +10 -0
- package/agent-plugin/plugin.json +11 -0
- package/agent-plugin/skills/init-kibi/SKILL.md +62 -0
- package/agent-plugin/skills/kibi-freshness/SKILL.md +44 -0
- package/agent-plugin/skills/kibi-traceability/SKILL.md +54 -0
- package/agent-plugin/skills/kibi-usage/SKILL.md +270 -0
- package/agent-plugin/skills/kibi-usage/resources/fact-lanes.md +235 -0
- package/agent-plugin/skills/kibi-usage/resources/logic-ir.md +43 -0
- package/agent-plugin/skills/kibi-usage/resources/operation-access.md +44 -0
- package/agent-plugin/skills/kibi-usage/resources/relationship-directions.md +119 -0
- package/agent-plugin/skills/kibi-usage/resources/ui-requirements.md +96 -0
- package/agent-plugin/skills/kibi-usage/resources/workflows.md +80 -0
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/guidance.d.ts +10 -2
- package/dist/guidance.js +26 -17
- package/dist/hook-runner.d.ts +1 -0
- package/dist/hook-runner.js +34 -7
- package/dist/hook-state-storage.d.ts +11 -0
- package/dist/hook-state-storage.js +187 -0
- package/dist/hook-state.d.ts +3 -4
- package/dist/hook-state.js +6 -206
- package/dist/kb-mcp-tools.d.ts +3 -0
- package/dist/kb-mcp-tools.js +6 -0
- package/dist/messages.d.ts +4 -2
- package/dist/messages.js +14 -2
- package/dist/rules/kibi-workflow.mdc +3 -3
- package/dist/skills/.canon-hash.json +12 -0
- package/dist/skills/init-kibi/SKILL.md +50 -11
- package/dist/skills/kibi-freshness/SKILL.md +32 -10
- package/dist/skills/kibi-traceability/SKILL.md +41 -11
- package/dist/skills/kibi-usage/SKILL.md +149 -97
- package/dist/skills/kibi-usage/resources/fact-lanes.md +235 -0
- package/dist/skills/kibi-usage/resources/logic-ir.md +43 -0
- package/dist/skills/kibi-usage/resources/operation-access.md +44 -0
- package/dist/skills/kibi-usage/resources/relationship-directions.md +119 -0
- package/dist/skills/kibi-usage/resources/ui-requirements.md +96 -0
- package/dist/skills/kibi-usage/resources/workflows.md +80 -0
- package/package.json +3 -2
- package/rules/kibi-workflow.mdc +3 -3
- package/skills/.canon-hash.json +12 -0
- package/skills/init-kibi/SKILL.md +50 -11
- package/skills/kibi-freshness/SKILL.md +32 -10
- package/skills/kibi-traceability/SKILL.md +41 -11
- package/skills/kibi-usage/SKILL.md +149 -97
- package/skills/kibi-usage/resources/fact-lanes.md +235 -0
- package/skills/kibi-usage/resources/logic-ir.md +43 -0
- package/skills/kibi-usage/resources/operation-access.md +44 -0
- package/skills/kibi-usage/resources/relationship-directions.md +119 -0
- package/skills/kibi-usage/resources/ui-requirements.md +96 -0
- package/skills/kibi-usage/resources/workflows.md +80 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Relationship Directions
|
|
2
|
+
|
|
3
|
+
## Direction Table
|
|
4
|
+
|
|
5
|
+
| Relationship | Source -> Target | Semantic Meaning |
|
|
6
|
+
|-------------|------------------|------------------|
|
|
7
|
+
| `implements` | symbol -> req | Production code symbol owns or implements requirement behavior |
|
|
8
|
+
| `specified_by` | req -> scenario | Requirement is specified by a BDD scenario |
|
|
9
|
+
| `verified_by` | req/scenario -> test | Requirement or scenario is verified by a test case |
|
|
10
|
+
| `validates` | test -> req/scenario | Test validates a requirement or scenario (inverse of verified_by) |
|
|
11
|
+
| `executable_for` | symbol -> test | Test symbol (code) is executable code for a test entity |
|
|
12
|
+
| `constrains` | req -> fact(subject) | Requirement constrains a strict-lane domain fact |
|
|
13
|
+
| `requires_property` | req -> fact(property_value) | Requirement requires a specific property value fact |
|
|
14
|
+
| `supersedes` | old-req -> new-req | Old requirement is formally replaced by a new requirement |
|
|
15
|
+
| `covered_by` | symbol -> test | Production symbol has test coverage evidence |
|
|
16
|
+
|
|
17
|
+
## Valid Payload Examples
|
|
18
|
+
|
|
19
|
+
### implements
|
|
20
|
+
```yaml
|
|
21
|
+
relationships:
|
|
22
|
+
- type: implements
|
|
23
|
+
from: SYM-001
|
|
24
|
+
to: REQ-001
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### specified_by
|
|
28
|
+
```yaml
|
|
29
|
+
relationships:
|
|
30
|
+
- type: specified_by
|
|
31
|
+
from: REQ-001
|
|
32
|
+
to: SCEN-001
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### verified_by
|
|
36
|
+
```yaml
|
|
37
|
+
relationships:
|
|
38
|
+
- type: verified_by
|
|
39
|
+
from: REQ-001
|
|
40
|
+
to: TEST-001
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### validates
|
|
44
|
+
```yaml
|
|
45
|
+
relationships:
|
|
46
|
+
- type: validates
|
|
47
|
+
from: TEST-001
|
|
48
|
+
to: SCEN-001
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### executable_for
|
|
52
|
+
```yaml
|
|
53
|
+
relationships:
|
|
54
|
+
- type: executable_for
|
|
55
|
+
from: SYM-test-login
|
|
56
|
+
to: TEST-001
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### constrains
|
|
60
|
+
```yaml
|
|
61
|
+
relationships:
|
|
62
|
+
- type: constrains
|
|
63
|
+
from: REQ-019
|
|
64
|
+
to: FACT-USER-ROLE
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### requires_property
|
|
68
|
+
```yaml
|
|
69
|
+
relationships:
|
|
70
|
+
- type: requires_property
|
|
71
|
+
from: REQ-019
|
|
72
|
+
to: FACT-LIMIT-3
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### supersedes
|
|
76
|
+
```yaml
|
|
77
|
+
relationships:
|
|
78
|
+
- type: supersedes
|
|
79
|
+
from: REQ-001
|
|
80
|
+
to: REQ-001-v2
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### covered_by
|
|
84
|
+
```yaml
|
|
85
|
+
relationships:
|
|
86
|
+
- type: covered_by
|
|
87
|
+
from: SYM-handler
|
|
88
|
+
to: TEST-005
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Invalid Test-Fact Shortcuts
|
|
92
|
+
|
|
93
|
+
Do not model small behavior fixes as direct test-fact pairs. Facts describe invariants; requirements or scenarios are verified by tests.
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
# WRONG: fact -> test is not a valid verified_by shape
|
|
97
|
+
relationships:
|
|
98
|
+
- type: verified_by
|
|
99
|
+
from: FACT-HEADER-AVATAR-INITIAL-UPPERCASE
|
|
100
|
+
to: TEST-AVATAR-HEADER-FALLBACK
|
|
101
|
+
|
|
102
|
+
# WRONG: test -> fact is not a valid validates shape
|
|
103
|
+
relationships:
|
|
104
|
+
- type: validates
|
|
105
|
+
from: TEST-AVATAR-HEADER-FALLBACK
|
|
106
|
+
to: FACT-HEADER-AVATAR-INITIAL-UPPERCASE
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use a requirement as the verification target/source, then link that requirement to strict facts:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
relationships:
|
|
113
|
+
- type: verified_by
|
|
114
|
+
from: REQ-HEADER-AVATAR-INITIAL-UPPERCASE
|
|
115
|
+
to: TEST-AVATAR-HEADER-FALLBACK
|
|
116
|
+
- type: requires_property
|
|
117
|
+
from: REQ-HEADER-AVATAR-INITIAL-UPPERCASE
|
|
118
|
+
to: FACT-HEADER-AVATAR-INITIAL-UPPERCASE
|
|
119
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# UI / Visual Requirement Modeling
|
|
2
|
+
|
|
3
|
+
Optional, per-project lane for recording what the screen should look like so UI edits cannot
|
|
4
|
+
silently drift from the spec. Non-UI projects skip it entirely; no check rule requires it.
|
|
5
|
+
|
|
6
|
+
## Three layers
|
|
7
|
+
|
|
8
|
+
1. **Prose `req`** — the full on-screen description lives in the requirement body as the
|
|
9
|
+
searchable anchor agents discover with `kb_search` / `kb_query`.
|
|
10
|
+
2. **Strict facts** — checkable visual invariants as `fact_kind: subject` (`subject_key`,
|
|
11
|
+
linked `constrains`) plus `fact_kind: property_value` (`property_key`, `operator`, typed
|
|
12
|
+
`value_*`, linked `requires_property`). Incompatible values on the same subject/property
|
|
13
|
+
from two current requirements are rejected on write unless `supersedes`.
|
|
14
|
+
3. **Relational predicates** — ground `fact_kind: predicate` linked with `requires_predicate`.
|
|
15
|
+
The built-in `visual_layout_rule(subject, relation, target)` covers "X must remain visually
|
|
16
|
+
aligned with Y" (relation `aligned_with`). Other relational layout claims need a
|
|
17
|
+
project-local `predicate_schema` when the task authorizes ontology extension.
|
|
18
|
+
|
|
19
|
+
Kibi enforces stated facts and links, not pixels. Freeform spatial prose is stored and
|
|
20
|
+
searchable but is not machine-checked.
|
|
21
|
+
|
|
22
|
+
## Button position
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
id: FACT-UI-SUBMIT-REGION
|
|
26
|
+
fact_kind: subject
|
|
27
|
+
subject_key: settings.screen.submit_button
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
id: FACT-UI-SUBMIT-POSITION
|
|
32
|
+
fact_kind: property_value
|
|
33
|
+
subject_key: settings.screen.submit_button
|
|
34
|
+
property_key: position
|
|
35
|
+
operator: eq
|
|
36
|
+
value_type: string
|
|
37
|
+
value_string: bottom_right
|
|
38
|
+
canonical_key: settings.screen.submit_button.position.eq.bottom_right
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Link both facts from the requirement:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
id: REQ-UI-SETTINGS
|
|
45
|
+
relationships:
|
|
46
|
+
- type: constrains
|
|
47
|
+
from: REQ-UI-SETTINGS
|
|
48
|
+
to: FACT-UI-SUBMIT-REGION
|
|
49
|
+
- type: requires_property
|
|
50
|
+
from: REQ-UI-SETTINGS
|
|
51
|
+
to: FACT-UI-SUBMIT-POSITION
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A later requirement writing `position: top_left` on the same subject is rejected on write.
|
|
55
|
+
|
|
56
|
+
## Header item order
|
|
57
|
+
|
|
58
|
+
Use one indexed `property_key` per slot against the same subject region:
|
|
59
|
+
`nav_order_1: home`, `nav_order_2: search`, `nav_order_3: profile`, each as a separate
|
|
60
|
+
`property_value` fact linked with `requires_property`. This makes each slot independently
|
|
61
|
+
contradiction-checkable.
|
|
62
|
+
|
|
63
|
+
## Relational alignment
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
id: FACT-UI-NAV-ALIGN
|
|
67
|
+
fact_kind: predicate
|
|
68
|
+
predicate_name: visual_layout_rule
|
|
69
|
+
predicate_args: [navigation_rail, aligned_with, header]
|
|
70
|
+
polarity: assert
|
|
71
|
+
canonical_key: visual_layout_rule(navigation_rail,aligned_with,header)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Link with `requires_predicate`. An `assert`/`deny` pair over the same predicate namespace,
|
|
75
|
+
name, and ordered arguments is a blocking `domain-contradictions` conflict.
|
|
76
|
+
|
|
77
|
+
## UI component traceability
|
|
78
|
+
|
|
79
|
+
Model the component as a `symbol` with `sourceFile` and `symbol_role: behavioral`, linked
|
|
80
|
+
`implements` to the requirement, so component edits surface the visual spec in impact
|
|
81
|
+
diagnostics (`symbol_semantic_review_needed`).
|
|
82
|
+
|
|
83
|
+
## Workflow
|
|
84
|
+
|
|
85
|
+
1. `kb_semantic_advisor` on the full description; audit or supply `clauses`.
|
|
86
|
+
2. Relational clauses: `kb_suggest_predicates`, apply the predicate plan and
|
|
87
|
+
`requires_predicate`.
|
|
88
|
+
3. Scalar placement/alignment/order clauses: `kb_model_requirement`, apply the strict
|
|
89
|
+
subject/property plan and `constrains` / `requires_property`.
|
|
90
|
+
4. Preserve `claim_key` / `claim_text`; merge every key into the requirement
|
|
91
|
+
`logic_claims` manifest.
|
|
92
|
+
5. `kb_validate_upsert`, create endpoints first, then sequential `kb_upsert`.
|
|
93
|
+
6. `kb_check` with `logic-coverage`, `predicate-verifiability`, `domain-contradictions`,
|
|
94
|
+
then a final unfiltered `kb_check`.
|
|
95
|
+
|
|
96
|
+
Non-UI projects: declare `has_ui: false` during bootstrap and no UI entities are proposed.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Workflows
|
|
2
|
+
|
|
3
|
+
## Discovery to Validation Sequence
|
|
4
|
+
|
|
5
|
+
The canonical workflow for any KB operation follows this pattern:
|
|
6
|
+
|
|
7
|
+
1. **Discover**: `kb_search` with focused probes
|
|
8
|
+
2. **Confirm**: `kb_query` for exact IDs and state
|
|
9
|
+
3. **Inspect**: `kb_status` when freshness matters
|
|
10
|
+
4. **Decompose**: `kb_semantic_advisor` on the complete normative prose; verify or supply every atomic clause
|
|
11
|
+
5. **Choose per-clause lanes**: strict facts for scalar claims; `kb_suggest_predicates` for approved ground ontology relations; `kb_model_requirement` with `kibi.logic.v1` for conditions, exceptions, modalities, quantifiers, cardinality, and bounded temporal rules; observation review for ambiguity, nonlogical prose, and ontology gaps
|
|
12
|
+
6. **Preflight**: `kb_validate_upsert` for every intended entity or relationship payload
|
|
13
|
+
7. **Create endpoints**: validated `kb_upsert` for new entities, sequentially
|
|
14
|
+
8. **Link**: validated `kb_upsert` with `requires_rule`, `requires_predicate`, `constrains`, or `requires_property`, sequentially
|
|
15
|
+
9. **Validate coverage and consistency**: targeted `rule-safety`, `rule-verifiability`, `semantic-completeness`, `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`, then final full `kb_check`
|
|
16
|
+
|
|
17
|
+
Every current requirement without `logic_claims` remains visible as non-blocking backfill debt. Once a manifest and `semantic_inventory` exist, the unfiltered check enforces correspondence to linked ground facts/rules and rejects silently missing assertive propositions.
|
|
18
|
+
|
|
19
|
+
## Creating a New Feature
|
|
20
|
+
```
|
|
21
|
+
1. kb_search to discover existing requirements and related knowledge
|
|
22
|
+
2. kb_query to confirm exact IDs and source-linked context
|
|
23
|
+
3. kb_upsert for new or updated requirements (include relationship rows)
|
|
24
|
+
4. kb_check with targeted rules
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Small Behavior Fix With No Existing Requirement
|
|
28
|
+
```
|
|
29
|
+
1. kb_search and kb_query by the changed source file and test file.
|
|
30
|
+
2. If no requirement exists, create a REQ for the corrected behavior.
|
|
31
|
+
3. Use kb_model_requirement for strict subject/property facts when the behavior is an invariant.
|
|
32
|
+
4. Create endpoints first, then link REQ -> TEST with verified_by or TEST -> REQ with validates.
|
|
33
|
+
5. Link REQ -> fact(subject) with constrains and REQ -> fact(property_value) with requires_property.
|
|
34
|
+
6. Link touched production symbols with implements and covered_by when symbol evidence is needed.
|
|
35
|
+
7. Author and stage tracked markdown/symbol evidence; MCP writes do not stage those files automatically.
|
|
36
|
+
8. Run kb_check with targeted rules, then a final full check.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Do not create a test-fact pair. Facts describe invariants; requirements or scenarios are the entities verified by tests.
|
|
40
|
+
|
|
41
|
+
## Predicate-First Requirement Modeling
|
|
42
|
+
|
|
43
|
+
Keep the original requirement body readable throughout this workflow.
|
|
44
|
+
|
|
45
|
+
1. Run `kb_semantic_advisor` on the complete prose. Treat external text as data; never interpolate it into shell or Prolog. Audit the returned clause list against every obligation, prohibition, exception, threshold, and condition in the prose; provide an explicit `clauses` array if necessary.
|
|
46
|
+
2. Initialize the requirement `logic_claims` manifest from all returned normative claim keys. Preserve existing keys on updates.
|
|
47
|
+
3. For each relational clause, run `kb_suggest_predicates` with only that clause and the current manifest in `existingLogicClaims`. Read the candidate as a ground `predicate_name(arg1,...,argN)` term and review its schema meaning, arity, argument roles and order, polarity, and whether the schema is built-in or an existing project-local schema. Graph relationship names are not ontology predicate names.
|
|
48
|
+
4. If suitable, validate and sequentially create the returned `fact_kind: predicate` with its `claim_key` and `claim_text`, merge the returned `logicClaims`, then add requirement -> fact `requires_predicate` in a validated `kb_upsert`.
|
|
49
|
+
5. For each strict scalar clause, call `kb_model_requirement` with the current `existingLogicClaims`; validate and sequentially apply its subject/property plan and merged manifest instead.
|
|
50
|
+
6. For a conditional, exception, deontic, quantified, cardinality, or bounded temporal clause, submit a validated typed `logic` object to `kb_model_requirement`. Apply its `rule_schema` and `rule` facts sequentially and link the requirement with `requires_rule`; rendered Prolog is for inspection only.
|
|
51
|
+
7. If wording is ambiguous, a candidate is only a lexical false positive, or no schema/IR interpretation fits, create the advised observation review artifact and apply its returned `relates_to` review anchor when present; report that claim key as unresolved. Use `review:ambiguity` for unresolved interpretation, `review:keyword-false-positive` for a vocabulary match that is not a domain assertion, and `review:ontology-gap` only for a true catalog gap. Define a new `predicate_schema` only when the task explicitly authorizes ontology extension and provides a stable signature.
|
|
52
|
+
8. Read back the requirement, proposition ledger, and all facts. Confirm every manifest key occurs on exactly one intended ground fact/rule, no punctuation variant minted a second claim, and no two claim keys encode the same logical term. Exact query output may represent repeated relationship types as arrays, so inspect every target. Then run `kb_check` with `rule-safety`, `rule-verifiability`, `semantic-completeness`, `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`. Finish with an unfiltered `kb_check`.
|
|
53
|
+
|
|
54
|
+
Do not treat the manifest itself as proof of grounding. The advisor keeps readiness partial while there are fewer logical edge slots than normative claims; final readback and `logic-coverage` bind those slots to exact claim keys and ground terms.
|
|
55
|
+
|
|
56
|
+
Examples: built-in permission and deny claims use the suggested `permission_rule`; a project-local `commit_action` is valid only after its schema exists; session timeout is strict scalar; “better support” is ambiguous; `publishes_event` for publishing an article is a false positive; annotation anchoring without a fitting schema is an ontology gap. The authoritative payloads are in `resources/fact-lanes.md`.
|
|
57
|
+
|
|
58
|
+
On resume after interruption, repeat `kb_query` for exact endpoints and apply only missing validated writes. Keep `kb_upsert` concurrency at one.
|
|
59
|
+
|
|
60
|
+
## UI / Visual Requirement Modeling
|
|
61
|
+
|
|
62
|
+
Optional per-project workflow for recording what the screen should look like. Non-UI projects skip this lane entirely.
|
|
63
|
+
|
|
64
|
+
1. Create a prose `req` holding the full visual description; it is the searchable anchor agents discover before touching a UI file.
|
|
65
|
+
2. Run `kb_semantic_advisor` on the description; audit or supply `clauses`.
|
|
66
|
+
3. For relational layout clauses ("X must remain visually aligned with Y"), call `kb_suggest_predicates`, apply the returned `fact_kind: predicate` plan with `predicate_name: visual_layout_rule` and `requires_predicate`.
|
|
67
|
+
4. For scalar placement, alignment, and ordering clauses, call `kb_model_requirement` and apply strict `fact_kind: subject` / `fact_kind: property_value` facts linked with `constrains` / `requires_property`. Model header order as indexed property keys (`nav_order_1`, `nav_order_2`, ...) against one subject region.
|
|
68
|
+
5. Preserve `claim_key` / `claim_text` on every ground fact and merge every key into the requirement `logic_claims` manifest.
|
|
69
|
+
6. Model UI components as `symbol` entities with `sourceFile` and `symbol_role: behavioral`, linked `implements` to the requirement.
|
|
70
|
+
7. `kb_validate_upsert`, create endpoints first, then sequential `kb_upsert`. Run `kb_check` with `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`, then a final unfiltered `kb_check`.
|
|
71
|
+
|
|
72
|
+
Incompatible values on the same subject/property from two current requirements are rejected on write; change an intentional value via a replacement requirement linked with `supersedes`. Full payloads are in `resources/ui-requirements.md`.
|
|
73
|
+
|
|
74
|
+
## Fixing a Traceability Gap
|
|
75
|
+
```
|
|
76
|
+
1. kb_query --sourceFile <code-file> to find linked entities
|
|
77
|
+
2. kb_find_gaps --type req --missing-rel specified_by to find orphan requirements
|
|
78
|
+
3. kb_upsert to add missing relationship rows (sequential)
|
|
79
|
+
4. kb_check with rules: ["no-dangling-refs", "symbol-traceability"]
|
|
80
|
+
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-cursor",
|
|
3
3
|
"displayName": "Kibi",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
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/dist/guidance.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import type { McpState } from "./kb-mcp-tools.js";
|
|
2
|
+
export { resolveKibiInterface } from "./kb-mcp-tools.js";
|
|
3
|
+
export type GuidanceContext = {
|
|
4
|
+
readonly cwd: string | undefined;
|
|
5
|
+
readonly hasKibi: boolean;
|
|
6
|
+
readonly mcpState: McpState;
|
|
7
|
+
readonly workspaceTrusted: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function readGuidance(filePath: string, context: GuidanceContext): string | undefined;
|
|
10
|
+
export declare function writeGuidance(filePath: string, context: GuidanceContext): string | undefined;
|
package/dist/guidance.js
CHANGED
|
@@ -1,38 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
import { interfaceAdvisory } from "./messages.js";
|
|
2
|
+
// implements REQ-cursor-kibi-plugin-v1, REQ-agent-kibi-interface-selection
|
|
2
3
|
import { isDocumentationTrackedPath, isMeaningfulTrackedPath, toRepoRelativePath, } from "./path-policy.js";
|
|
3
|
-
export
|
|
4
|
-
|
|
4
|
+
export { resolveKibiInterface } from "./kb-mcp-tools.js";
|
|
5
|
+
export function readGuidance(filePath, context) {
|
|
6
|
+
if (!context.hasKibi) {
|
|
5
7
|
return undefined;
|
|
6
8
|
}
|
|
7
|
-
const relativePath = toRepoRelativePath(filePath, cwd);
|
|
9
|
+
const relativePath = toRepoRelativePath(filePath, context.cwd);
|
|
8
10
|
if (!isMeaningfulTrackedPath(relativePath)) {
|
|
9
11
|
return undefined;
|
|
10
12
|
}
|
|
11
|
-
|
|
12
|
-
"Kibi read guidance: before changing this file, discover linked knowledge
|
|
13
|
+
const guidance = [
|
|
14
|
+
"Kibi read guidance: before changing this file, discover linked knowledge through the selected MCP or CLI JSON route.",
|
|
13
15
|
`Start with kb_search, then kb_query with sourceFile="${relativePath}".`,
|
|
14
16
|
"Prefer Kibi facts and requirements over long inline comments for durable knowledge.",
|
|
15
|
-
]
|
|
17
|
+
];
|
|
18
|
+
const advisory = interfaceAdvisory(context.mcpState, context.workspaceTrusted);
|
|
19
|
+
return advisory ? [advisory, ...guidance].join("\n") : guidance.join("\n");
|
|
16
20
|
}
|
|
17
|
-
export function writeGuidance(filePath,
|
|
18
|
-
if (!hasKibi) {
|
|
21
|
+
export function writeGuidance(filePath, context) {
|
|
22
|
+
if (!context.hasKibi) {
|
|
19
23
|
return undefined;
|
|
20
24
|
}
|
|
21
|
-
const relativePath = toRepoRelativePath(filePath, cwd);
|
|
25
|
+
const relativePath = toRepoRelativePath(filePath, context.cwd);
|
|
22
26
|
if (!isMeaningfulTrackedPath(relativePath)) {
|
|
23
27
|
return undefined;
|
|
24
28
|
}
|
|
25
29
|
if (isDocumentationTrackedPath(relativePath)) {
|
|
26
|
-
|
|
30
|
+
const guidance = [
|
|
27
31
|
"Kibi write guidance: keep REQ, SCEN, and TEST artifacts separate.",
|
|
28
|
-
"Update KB entities through kb_upsert
|
|
29
|
-
"Do not edit
|
|
30
|
-
]
|
|
32
|
+
"Query before mutate. Update KB entities through kb_upsert sequentially. Run kb_check before completion.",
|
|
33
|
+
"Do not read or edit `.kb/` files directly.",
|
|
34
|
+
];
|
|
35
|
+
const advisory = interfaceAdvisory(context.mcpState, context.workspaceTrusted);
|
|
36
|
+
return advisory ? [advisory, ...guidance].join("\n") : guidance.join("\n");
|
|
31
37
|
}
|
|
32
|
-
|
|
33
|
-
"Kibi write guidance: link production symbols to requirements.",
|
|
38
|
+
const guidance = [
|
|
39
|
+
"Kibi write guidance: use the selected MCP or CLI JSON route to link production symbols to requirements.",
|
|
34
40
|
`After editing, run kb_check({sourceFiles:["${relativePath}"], includeImpactDiagnostics:true, includeWorkingTreeDiff:true}) for symbol granularity and semantic review of linked requirements/tests.`,
|
|
35
41
|
`After editing, resolve freshness with kb_search/kb_query for sourceFile="${relativePath}".`,
|
|
36
42
|
"Prefer symbol manifest + executable_for or // implements REQ-xxx for traceability.",
|
|
37
|
-
|
|
43
|
+
"Do not read or edit `.kb/` files directly. Query before mutate; run kb_upsert sequentially and kb_check before completion.",
|
|
44
|
+
];
|
|
45
|
+
const advisory = interfaceAdvisory(context.mcpState, context.workspaceTrusted);
|
|
46
|
+
return advisory ? [advisory, ...guidance].join("\n") : guidance.join("\n");
|
|
38
47
|
}
|
package/dist/hook-runner.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type CursorHookResult = {
|
|
|
8
8
|
};
|
|
9
9
|
export type HookEnvironment = {
|
|
10
10
|
pluginData?: string;
|
|
11
|
+
workspaceTrusted?: boolean;
|
|
11
12
|
};
|
|
12
13
|
export declare function runHook(rawInput: unknown, environment?: HookEnvironment): Promise<CursorHookResult>;
|
|
13
14
|
export declare const hookRunnerPath: string;
|
package/dist/hook-runner.js
CHANGED
|
@@ -7,7 +7,7 @@ import { readGuidance, writeGuidance } from "./guidance.js";
|
|
|
7
7
|
import { parseHookInput, parseStdinJson, readStdin } from "./hook-input.js";
|
|
8
8
|
import { addDirtyPaths, clearSessionHookState, hasGuidedPath, loadHookState, recordKbMcpTool, rememberGuidedPath, resolveStateDir, } from "./hook-state.js";
|
|
9
9
|
import { extractKbMcpToolCall } from "./kb-mcp-tools.js";
|
|
10
|
-
import { BOOTSTRAP_REMINDER, DIRECT_KB_EDIT_WARNING, stopFollowupMessage, } from "./messages.js";
|
|
10
|
+
import { BOOTSTRAP_REMINDER, DIRECT_KB_EDIT_WARNING, interfaceAdvisory, stopFollowupMessage, } from "./messages.js";
|
|
11
11
|
import { extractExplicitPathFields, isDirectKbPath, isMeaningfulTrackedPath, toRepoRelativePath, } from "./path-policy.js";
|
|
12
12
|
const editableTools = new Set([
|
|
13
13
|
"Edit",
|
|
@@ -48,12 +48,22 @@ export async function runHook(rawInput, environment = {}) {
|
|
|
48
48
|
const stateDir = resolveStateDir(pluginData, input.conversationId);
|
|
49
49
|
const cwd = resolveWorkspaceRoot(input);
|
|
50
50
|
const kibiReady = hasKibiConfig(cwd);
|
|
51
|
+
const workspaceTrusted = environment.workspaceTrusted === true;
|
|
52
|
+
const initialState = loadHookState(stateDir);
|
|
51
53
|
switch (input.event) {
|
|
52
54
|
case "sessionStart":
|
|
53
55
|
if (!kibiReady) {
|
|
54
|
-
|
|
56
|
+
const advisory = interfaceAdvisory(initialState.mcpState, workspaceTrusted);
|
|
57
|
+
return {
|
|
58
|
+
additional_context: advisory
|
|
59
|
+
? `${BOOTSTRAP_REMINDER}\n${advisory}`
|
|
60
|
+
: BOOTSTRAP_REMINDER,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
{
|
|
64
|
+
const advisory = interfaceAdvisory(initialState.mcpState, workspaceTrusted);
|
|
65
|
+
return advisory ? { additional_context: advisory } : emptyResult();
|
|
55
66
|
}
|
|
56
|
-
return emptyResult();
|
|
57
67
|
case "preToolUse": {
|
|
58
68
|
const explicitPaths = extractExplicitPathFields(input.toolInput);
|
|
59
69
|
const hasDirectKbEdit = isEditLikeTool(input.toolName) && explicitPaths.some(isDirectKbPath);
|
|
@@ -75,7 +85,12 @@ export async function runHook(rawInput, environment = {}) {
|
|
|
75
85
|
if (hasGuidedPath(state, "read", relativePath)) {
|
|
76
86
|
return { permission: "allow" };
|
|
77
87
|
}
|
|
78
|
-
const guidance = readGuidance(primaryPath,
|
|
88
|
+
const guidance = readGuidance(primaryPath, {
|
|
89
|
+
cwd,
|
|
90
|
+
hasKibi: kibiReady,
|
|
91
|
+
mcpState: state.mcpState,
|
|
92
|
+
workspaceTrusted,
|
|
93
|
+
});
|
|
79
94
|
if (!guidance) {
|
|
80
95
|
return { permission: "allow" };
|
|
81
96
|
}
|
|
@@ -110,7 +125,12 @@ export async function runHook(rawInput, environment = {}) {
|
|
|
110
125
|
if (hasGuidedPath(state, "read", relativePath)) {
|
|
111
126
|
return emptyResult();
|
|
112
127
|
}
|
|
113
|
-
const guidance = readGuidance(primaryPath,
|
|
128
|
+
const guidance = readGuidance(primaryPath, {
|
|
129
|
+
cwd,
|
|
130
|
+
hasKibi: kibiReady,
|
|
131
|
+
mcpState: state.mcpState,
|
|
132
|
+
workspaceTrusted,
|
|
133
|
+
});
|
|
114
134
|
if (!guidance) {
|
|
115
135
|
return emptyResult();
|
|
116
136
|
}
|
|
@@ -121,7 +141,12 @@ export async function runHook(rawInput, environment = {}) {
|
|
|
121
141
|
if (hasGuidedPath(state, "write", relativePath)) {
|
|
122
142
|
return emptyResult();
|
|
123
143
|
}
|
|
124
|
-
const guidance = writeGuidance(primaryPath,
|
|
144
|
+
const guidance = writeGuidance(primaryPath, {
|
|
145
|
+
cwd,
|
|
146
|
+
hasKibi: kibiReady,
|
|
147
|
+
mcpState: state.mcpState,
|
|
148
|
+
workspaceTrusted,
|
|
149
|
+
});
|
|
125
150
|
if (!guidance) {
|
|
126
151
|
return emptyResult();
|
|
127
152
|
}
|
|
@@ -149,7 +174,9 @@ export async function runHook(rawInput, environment = {}) {
|
|
|
149
174
|
}
|
|
150
175
|
}
|
|
151
176
|
async function main() {
|
|
152
|
-
const result = await runHook(parseStdinJson(await readStdin())
|
|
177
|
+
const result = await runHook(parseStdinJson(await readStdin()), {
|
|
178
|
+
workspaceTrusted: process.argv.includes("--trusted-workspace"),
|
|
179
|
+
});
|
|
153
180
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
154
181
|
}
|
|
155
182
|
const invokedPath = process.argv[1]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HookState } from "./hook-state.js";
|
|
2
|
+
export declare const maxDirtyPaths = 50;
|
|
3
|
+
export declare const maxGuidedPaths = 100;
|
|
4
|
+
export declare const maxKbMutationTools = 20;
|
|
5
|
+
export declare function normalizePath(dirtyPath: string): string;
|
|
6
|
+
export declare function mergeStringPaths(existingPaths: readonly string[], nextPaths: readonly string[]): string[];
|
|
7
|
+
export declare function emptyHookState(): HookState;
|
|
8
|
+
export declare function resolveStateDir(pluginData: string | undefined, conversationId: string | undefined): string | undefined;
|
|
9
|
+
export declare function loadHookState(stateDir: string | undefined): HookState;
|
|
10
|
+
export declare function saveHookState(stateDir: string | undefined, state: HookState): void;
|
|
11
|
+
export declare function updateHookState(stateDir: string | undefined, updater: (state: HookState) => HookState): HookState;
|