kibi-cli 0.11.0 → 0.11.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +36 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -1
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +2 -3
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +7 -2
- package/dist/commands/skills.d.ts +14 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +86 -0
- package/dist/commands/sync/manifest.d.ts +1 -1
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +7 -4
- package/dist/commands/sync/staging.d.ts.map +1 -1
- package/dist/commands/sync/staging.js +2 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +3 -1
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +3 -1
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -1
- package/dist/extractors/symbol-coordinates.js +1 -1
- package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/extractors/symbols-coordinator.js +2 -1
- package/dist/extractors/symbols-ts.d.ts.map +1 -1
- package/dist/extractors/symbols-ts.js +3 -1
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +14 -1
- package/dist/public/ignore-policy.d.ts.map +1 -1
- package/dist/public/ignore-policy.js +8 -4
- package/dist/public/operational-artifacts.d.ts.map +1 -1
- package/dist/public/operational-artifacts.js +1 -0
- package/dist/public/skills/kibi-usage/SKILL.md +205 -0
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +123 -0
- package/dist/public/skills/kibi-usage/resources/relationship-directions.md +89 -0
- package/dist/public/skills/kibi-usage/resources/workflows.md +28 -0
- package/dist/public/skills.d.ts +42 -0
- package/dist/public/skills.d.ts.map +1 -0
- package/dist/public/skills.js +270 -0
- package/dist/search-ranking.d.ts.map +1 -1
- package/dist/traceability/evidence-model.d.ts.map +1 -1
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-diagnostics.js +1 -1
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +8 -2
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +4 -1
- package/dist/utils/config.d.ts +3 -18
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +4 -40
- package/dist/utils/manifest-paths.d.ts.map +1 -1
- package/dist/utils/manifest-paths.js +3 -1
- package/dist/utils/schema-version.d.ts.map +1 -1
- package/dist/utils/strict-modeling.d.ts +1 -1
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +13 -3
- package/package.json +7 -13
- package/schema/config.json +0 -68
- package/src/public/ignore-policy.ts +26 -10
- package/src/public/operational-artifacts.ts +2 -1
- package/src/public/skills/kibi-usage/SKILL.md +205 -0
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +123 -0
- package/src/public/skills/kibi-usage/resources/relationship-directions.md +89 -0
- package/src/public/skills/kibi-usage/resources/workflows.md +28 -0
- package/src/public/skills.ts +427 -0
- package/dist/public/brief-config.d.ts +0 -4
- package/dist/public/brief-config.d.ts.map +0 -1
- package/dist/public/brief-config.js +0 -21
- package/src/public/brief-config.ts +0 -25
package/schema/config.json
CHANGED
|
@@ -61,74 +61,6 @@
|
|
|
61
61
|
"description": "[DEPRECATED] No longer used. Branch lifecycle now follows git naturally without requiring a configured default. This field is ignored but kept for backward compatibility.",
|
|
62
62
|
"deprecated": true
|
|
63
63
|
},
|
|
64
|
-
"briefs": {
|
|
65
|
-
"type": "object",
|
|
66
|
-
"description": "Configuration for shared brief delivery defaults",
|
|
67
|
-
"properties": {
|
|
68
|
-
"enabled": {
|
|
69
|
-
"type": "boolean",
|
|
70
|
-
"default": true
|
|
71
|
-
},
|
|
72
|
-
"retention": {
|
|
73
|
-
"type": "object",
|
|
74
|
-
"properties": {
|
|
75
|
-
"maxPerBranch": {
|
|
76
|
-
"type": "integer",
|
|
77
|
-
"minimum": 1,
|
|
78
|
-
"maximum": 10000,
|
|
79
|
-
"default": 200
|
|
80
|
-
},
|
|
81
|
-
"maxAgeDays": {
|
|
82
|
-
"type": "integer",
|
|
83
|
-
"minimum": 1,
|
|
84
|
-
"maximum": 3650,
|
|
85
|
-
"default": 14
|
|
86
|
-
},
|
|
87
|
-
"keepUnread": {
|
|
88
|
-
"type": "boolean",
|
|
89
|
-
"default": true
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
"additionalProperties": false
|
|
93
|
-
},
|
|
94
|
-
"channels": {
|
|
95
|
-
"type": "object",
|
|
96
|
-
"properties": {
|
|
97
|
-
"vscode": {
|
|
98
|
-
"type": "boolean",
|
|
99
|
-
"default": true
|
|
100
|
-
},
|
|
101
|
-
"tui": {
|
|
102
|
-
"type": "boolean",
|
|
103
|
-
"default": true
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"additionalProperties": false
|
|
107
|
-
},
|
|
108
|
-
"tui": {
|
|
109
|
-
"type": "object",
|
|
110
|
-
"properties": {
|
|
111
|
-
"toast": {
|
|
112
|
-
"type": "boolean",
|
|
113
|
-
"default": true
|
|
114
|
-
},
|
|
115
|
-
"appendPrompt": {
|
|
116
|
-
"type": "boolean",
|
|
117
|
-
"default": true
|
|
118
|
-
},
|
|
119
|
-
"idleDelayMs": {
|
|
120
|
-
"type": "integer",
|
|
121
|
-
"minimum": 0,
|
|
122
|
-
"maximum": 60000,
|
|
123
|
-
"default": 1500,
|
|
124
|
-
"description": "Delay in milliseconds after session.idle before idle-brief generation is attempted"
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
"additionalProperties": false
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
"additionalProperties": false
|
|
131
|
-
},
|
|
132
64
|
"checks": {
|
|
133
65
|
"type": "object",
|
|
134
66
|
"description": "Configuration for KB validation rules",
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type Dirent,
|
|
3
|
+
existsSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
readdirSync,
|
|
6
|
+
statSync,
|
|
7
|
+
} from "node:fs";
|
|
2
8
|
import * as path from "node:path";
|
|
3
9
|
import ignore from "ignore";
|
|
4
10
|
|
|
@@ -51,7 +57,7 @@ export function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy {
|
|
|
51
57
|
const nestedPatterns = new Map<string, string[]>();
|
|
52
58
|
|
|
53
59
|
function walk(dirAbs: string) {
|
|
54
|
-
let entries;
|
|
60
|
+
let entries: Dirent[];
|
|
55
61
|
try {
|
|
56
62
|
entries = readdirSync(dirAbs, { withFileTypes: true });
|
|
57
63
|
} catch {
|
|
@@ -95,7 +101,9 @@ export function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy {
|
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
// Prepare nested directories sorted by specificity (longest first)
|
|
98
|
-
const nestedDirsSorted = Array.from(nestedIgnoreMap.keys()).sort(
|
|
104
|
+
const nestedDirsSorted = Array.from(nestedIgnoreMap.keys()).sort(
|
|
105
|
+
(a, b) => b.length - a.length,
|
|
106
|
+
);
|
|
99
107
|
|
|
100
108
|
function isPathOutsideWorkspace(absPath: string): boolean {
|
|
101
109
|
const rel = path.relative(root, absPath);
|
|
@@ -111,9 +119,14 @@ export function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy {
|
|
|
111
119
|
return false;
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
function isIgnoredInternal(inputPath: string): {
|
|
122
|
+
function isIgnoredInternal(inputPath: string): {
|
|
123
|
+
ignored: boolean;
|
|
124
|
+
reason?: string;
|
|
125
|
+
} {
|
|
115
126
|
// Resolve to absolute and relative path inside workspace
|
|
116
|
-
const abs = path.isAbsolute(inputPath)
|
|
127
|
+
const abs = path.isAbsolute(inputPath)
|
|
128
|
+
? path.resolve(inputPath)
|
|
129
|
+
: path.resolve(root, inputPath);
|
|
117
130
|
|
|
118
131
|
if (path.isAbsolute(inputPath) && isPathOutsideWorkspace(abs)) {
|
|
119
132
|
return { ignored: true, reason: "outside_workspace" };
|
|
@@ -123,7 +136,8 @@ export function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy {
|
|
|
123
136
|
const relPosix = toPosix(rel);
|
|
124
137
|
|
|
125
138
|
// Hard denylist always wins
|
|
126
|
-
if (matchesHardDeny(relPosix))
|
|
139
|
+
if (matchesHardDeny(relPosix))
|
|
140
|
+
return { ignored: true, reason: "hard_deny" };
|
|
127
141
|
|
|
128
142
|
// Root .gitignore
|
|
129
143
|
try {
|
|
@@ -147,11 +161,13 @@ export function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy {
|
|
|
147
161
|
for (const dirRel of nestedDirsSorted) {
|
|
148
162
|
// dirRel is '.' for nested at root which we skipped, so dirRel will be like 'docs'
|
|
149
163
|
if (dirRel === ".") continue;
|
|
150
|
-
if (relPosix === dirRel || relPosix.startsWith(dirRel
|
|
151
|
-
const sub =
|
|
152
|
-
|
|
164
|
+
if (relPosix === dirRel || relPosix.startsWith(`${dirRel}/`)) {
|
|
165
|
+
const sub =
|
|
166
|
+
relPosix === dirRel ? "." : relPosix.slice(dirRel.length + 1);
|
|
167
|
+
const ig = nestedIgnoreMap.get(dirRel);
|
|
168
|
+
if (!ig) continue;
|
|
153
169
|
try {
|
|
154
|
-
if (ig
|
|
170
|
+
if (ig.ignores(sub)) return { ignored: true, reason: "gitignored" };
|
|
155
171
|
} catch (e) {
|
|
156
172
|
// noop
|
|
157
173
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export function isOperationalArtifactPath(pathLike: string): boolean {
|
|
1
|
+
export function isOperationalArtifactPath(pathLike: string): boolean {
|
|
2
|
+
// implements REQ-001
|
|
2
3
|
const normalized = pathLike.replaceAll("\\", "/");
|
|
3
4
|
|
|
4
5
|
return /(^|\/)\.sisyphus\//.test(normalized);
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
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
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Kibi Usage
|
|
20
|
+
|
|
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.
|
|
22
|
+
|
|
23
|
+
## MCP-Only Rules
|
|
24
|
+
|
|
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.
|
|
26
|
+
|
|
27
|
+
## Discovery-First Workflow
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
## Relationship Directions
|
|
34
|
+
|
|
35
|
+
Relationship direction is fixed and semantic. Getting it wrong breaks traceability queries and validation.
|
|
36
|
+
|
|
37
|
+
| Relationship | Direction | Meaning |
|
|
38
|
+
|-------------|-----------|---------|
|
|
39
|
+
| `implements` | symbol -> req | Symbol owns or implements requirement behavior |
|
|
40
|
+
| `specified_by` | req -> scenario | Requirement is specified by a scenario |
|
|
41
|
+
| `verified_by` | req/scenario -> test | Requirement or scenario is verified by a test |
|
|
42
|
+
| `validates` | test -> req/scenario | Test validates a requirement or scenario |
|
|
43
|
+
| `executable_for` | symbol -> test | Symbol is executable test code for a test entity |
|
|
44
|
+
| `constrains` | req -> fact(subject) | Requirement constrains a domain fact |
|
|
45
|
+
| `requires_property` | req -> fact(property_value) | Requirement requires a property value |
|
|
46
|
+
| `supersedes` | old-req -> new-req | Old requirement is replaced by new requirement |
|
|
47
|
+
| `covered_by` | symbol -> test | Production symbol has coverage evidence from a test |
|
|
48
|
+
|
|
49
|
+
See `resources/relationship-directions.md` for detailed payload examples.
|
|
50
|
+
|
|
51
|
+
## Symbol-First Traceability
|
|
52
|
+
|
|
53
|
+
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.
|
|
54
|
+
|
|
55
|
+
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.
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
# Preferred traceability model
|
|
59
|
+
symbol:
|
|
60
|
+
id: SYM-admin-billing-policy
|
|
61
|
+
title: Admin billing policy check
|
|
62
|
+
status: active
|
|
63
|
+
relationships:
|
|
64
|
+
- type: implements
|
|
65
|
+
from: SYM-admin-billing-policy
|
|
66
|
+
to: REQ-ADMIN-BILLING-POLICY
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Strict Fact Lane
|
|
70
|
+
|
|
71
|
+
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`.
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
# Fact entity
|
|
75
|
+
id: FACT-USER-ROLE
|
|
76
|
+
title: User Role Assignment
|
|
77
|
+
status: active
|
|
78
|
+
fact_kind: subject
|
|
79
|
+
subject_key: user.role_assignment
|
|
80
|
+
|
|
81
|
+
# Requirement entity
|
|
82
|
+
id: REQ-019
|
|
83
|
+
title: Users can have up to 3 roles
|
|
84
|
+
status: open
|
|
85
|
+
relationships:
|
|
86
|
+
- type: constrains
|
|
87
|
+
from: REQ-019
|
|
88
|
+
to: FACT-USER-ROLE
|
|
89
|
+
- type: requires_property
|
|
90
|
+
from: REQ-019
|
|
91
|
+
to: FACT-LIMIT-3
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
See `resources/fact-lanes.md` for the full strict vs observation lane comparison.
|
|
95
|
+
|
|
96
|
+
### Granular fact examples for coherence checks
|
|
97
|
+
|
|
98
|
+
Model one semantic claim per strict `property_value` fact. Reusing the same `subject_key` and `property_key` lets `domain-contradictions` compare requirements mechanically.
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
subject:
|
|
104
|
+
id: FACT-USER-ROLES
|
|
105
|
+
fact_kind: subject
|
|
106
|
+
subject_key: user.roles
|
|
107
|
+
|
|
108
|
+
property_values:
|
|
109
|
+
- id: FACT-USER-ROLES-ALLOWED-2
|
|
110
|
+
fact_kind: property_value
|
|
111
|
+
subject_key: user.roles
|
|
112
|
+
property_key: user.roles.allowed_set
|
|
113
|
+
operator: eq
|
|
114
|
+
value_type: list
|
|
115
|
+
value_json: '["user", "admin"]'
|
|
116
|
+
- id: FACT-USER-ROLES-ALLOWED-3
|
|
117
|
+
fact_kind: property_value
|
|
118
|
+
subject_key: user.roles
|
|
119
|
+
property_key: user.roles.allowed_set
|
|
120
|
+
operator: eq
|
|
121
|
+
value_type: list
|
|
122
|
+
value_json: '["user", "admin", "superadmin"]'
|
|
123
|
+
|
|
124
|
+
requirements:
|
|
125
|
+
- id: REQ-ROLE-SET-2
|
|
126
|
+
relationships:
|
|
127
|
+
- { type: constrains, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES }
|
|
128
|
+
- { type: requires_property, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES-ALLOWED-2 }
|
|
129
|
+
- id: REQ-ROLE-SET-3
|
|
130
|
+
relationships:
|
|
131
|
+
- { type: constrains, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES }
|
|
132
|
+
- { type: requires_property, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES-ALLOWED-3 }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
property_values:
|
|
139
|
+
- id: FACT-BILLING-MANAGE-ACTOR-ADMIN
|
|
140
|
+
fact_kind: property_value
|
|
141
|
+
subject_key: billing.manage
|
|
142
|
+
property_key: billing.manage.allowed_actor
|
|
143
|
+
operator: eq
|
|
144
|
+
value_type: string
|
|
145
|
+
value_string: admin
|
|
146
|
+
- id: FACT-BILLING-MANAGE-ACTOR-SUPERADMIN
|
|
147
|
+
fact_kind: property_value
|
|
148
|
+
subject_key: billing.manage
|
|
149
|
+
property_key: billing.manage.allowed_actor
|
|
150
|
+
operator: eq
|
|
151
|
+
value_type: string
|
|
152
|
+
value_string: superadmin
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
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.
|
|
156
|
+
|
|
157
|
+
## Fact vs Flag
|
|
158
|
+
|
|
159
|
+
Use `flag` for runtime or config gates only. Feature flags, kill-switches, and deferred capabilities are valid `flag` entities.
|
|
160
|
+
|
|
161
|
+
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.
|
|
162
|
+
|
|
163
|
+
Anti-example: do not create a `flag` named `BUG-123` to track a defect. Create a `fact` with `fact_kind: observation` instead.
|
|
164
|
+
|
|
165
|
+
## Create-Before-Link
|
|
166
|
+
|
|
167
|
+
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.
|
|
168
|
+
|
|
169
|
+
## Sequential Upserts
|
|
170
|
+
|
|
171
|
+
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.
|
|
172
|
+
|
|
173
|
+
## Targeted and Final Checks
|
|
174
|
+
|
|
175
|
+
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.
|
|
176
|
+
|
|
177
|
+
## Domain Contradictions and Evolution
|
|
178
|
+
|
|
179
|
+
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.
|
|
180
|
+
|
|
181
|
+
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.
|
|
182
|
+
|
|
183
|
+
## Stale or Dirty KB Handling
|
|
184
|
+
|
|
185
|
+
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.
|
|
186
|
+
|
|
187
|
+
## Anti-Patterns and Remediation
|
|
188
|
+
|
|
189
|
+
| Anti-Pattern | Problem | Remediation |
|
|
190
|
+
|-------------|---------|-------------|
|
|
191
|
+
| Reversed relationship direction | Traceability queries break | Verify direction against the relationship table above |
|
|
192
|
+
| Legacy implements comments | Comments are not durable queryable symbols | Create or update a `symbol` entity and link it to the requirement |
|
|
193
|
+
| Bug-as-flag | `flag` misused for defect tracking | Use `fact` with `fact_kind: observation` or `meta` |
|
|
194
|
+
| Parallel upserts | Lock contention and nondeterminism | Execute `kb_upsert` calls sequentially |
|
|
195
|
+
| Embedded scenarios in reqs | Violates canonical traceability chain | Create separate `req`, `scen`, and `test` entities |
|
|
196
|
+
| Missing `kb_check` | Undetected dangling refs and violations | Run targeted checks during work, full check at completion |
|
|
197
|
+
| Tags as multi-ID lookup | Tags are metadata, not identifiers | Use `kb_query` with explicit `id` values |
|
|
198
|
+
| `relates_to` for strict modeling | Loses contradiction safety | Use `constrains` and `requires_property` instead |
|
|
199
|
+
|
|
200
|
+
Before/after for reversed direction:
|
|
201
|
+
|
|
202
|
+
- Wrong: `relationships: [{ type: "implements", from: "REQ-001", to: "SYM-001" }]`
|
|
203
|
+
- Right: `relationships: [{ type: "implements", from: "SYM-001", to: "REQ-001" }]`
|
|
204
|
+
|
|
205
|
+
See `resources/workflows.md` for the golden-path discovery to validation sequence.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Fact Lanes
|
|
2
|
+
|
|
3
|
+
## Strict Lane (Contradiction-Safe)
|
|
4
|
+
|
|
5
|
+
### fact_kind: subject
|
|
6
|
+
```yaml
|
|
7
|
+
id: FACT-USER-ROLE
|
|
8
|
+
title: User Role Assignment
|
|
9
|
+
status: active
|
|
10
|
+
fact_kind: subject
|
|
11
|
+
subject_key: user.role_assignment
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### fact_kind: property_value
|
|
15
|
+
```yaml
|
|
16
|
+
id: FACT-LIMIT-3
|
|
17
|
+
title: Maximum of Three Roles
|
|
18
|
+
status: active
|
|
19
|
+
fact_kind: property_value
|
|
20
|
+
subject_key: user.role_assignment
|
|
21
|
+
property_key: max_roles
|
|
22
|
+
operator: lte
|
|
23
|
+
value_type: int
|
|
24
|
+
value_int: 3
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Granular Facts for Coherence Checks
|
|
28
|
+
|
|
29
|
+
Granular strict facts work best when each `property_value` represents one semantic claim about one `subject_key` and one `property_key`. This lets `domain-contradictions` compare current requirements that constrain the same subject and require incompatible values.
|
|
30
|
+
|
|
31
|
+
### Role set conflict
|
|
32
|
+
|
|
33
|
+
`REQ-ROLE-SET-2` and `REQ-ROLE-SET-3` are incoherent if both are current: they each define the exact allowed role set, but one allows two roles and the other allows three.
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
subject:
|
|
37
|
+
id: FACT-USER-ROLES
|
|
38
|
+
title: User roles
|
|
39
|
+
status: active
|
|
40
|
+
fact_kind: subject
|
|
41
|
+
subject_key: user.roles
|
|
42
|
+
|
|
43
|
+
property_values:
|
|
44
|
+
- id: FACT-USER-ROLES-ALLOWED-2
|
|
45
|
+
title: User and admin roles only
|
|
46
|
+
status: active
|
|
47
|
+
fact_kind: property_value
|
|
48
|
+
subject_key: user.roles
|
|
49
|
+
property_key: user.roles.allowed_set
|
|
50
|
+
operator: eq
|
|
51
|
+
value_type: list
|
|
52
|
+
value_json: '["user", "admin"]'
|
|
53
|
+
- id: FACT-USER-ROLES-ALLOWED-3
|
|
54
|
+
title: User, admin, and superadmin roles
|
|
55
|
+
status: active
|
|
56
|
+
fact_kind: property_value
|
|
57
|
+
subject_key: user.roles
|
|
58
|
+
property_key: user.roles.allowed_set
|
|
59
|
+
operator: eq
|
|
60
|
+
value_type: list
|
|
61
|
+
value_json: '["user", "admin", "superadmin"]'
|
|
62
|
+
|
|
63
|
+
relationships:
|
|
64
|
+
- { type: constrains, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES }
|
|
65
|
+
- { type: requires_property, from: REQ-ROLE-SET-2, to: FACT-USER-ROLES-ALLOWED-2 }
|
|
66
|
+
- { type: constrains, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES }
|
|
67
|
+
- { type: requires_property, from: REQ-ROLE-SET-3, to: FACT-USER-ROLES-ALLOWED-3 }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Permission actor conflict
|
|
71
|
+
|
|
72
|
+
`REQ-ADMIN-CAN-MANAGE-BILLING` and `REQ-ONLY-SUPERADMIN-MANAGES-BILLING` conflict when both define the exact allowed actor for the same permission.
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
subject:
|
|
76
|
+
id: FACT-BILLING-MANAGE
|
|
77
|
+
title: Billing management permission
|
|
78
|
+
status: active
|
|
79
|
+
fact_kind: subject
|
|
80
|
+
subject_key: billing.manage
|
|
81
|
+
|
|
82
|
+
property_values:
|
|
83
|
+
- id: FACT-BILLING-MANAGE-ACTOR-ADMIN
|
|
84
|
+
title: Admin can manage billing
|
|
85
|
+
status: active
|
|
86
|
+
fact_kind: property_value
|
|
87
|
+
subject_key: billing.manage
|
|
88
|
+
property_key: billing.manage.allowed_actor
|
|
89
|
+
operator: eq
|
|
90
|
+
value_type: string
|
|
91
|
+
value_string: admin
|
|
92
|
+
- id: FACT-BILLING-MANAGE-ACTOR-SUPERADMIN
|
|
93
|
+
title: Only superadmin can manage billing
|
|
94
|
+
status: active
|
|
95
|
+
fact_kind: property_value
|
|
96
|
+
subject_key: billing.manage
|
|
97
|
+
property_key: billing.manage.allowed_actor
|
|
98
|
+
operator: eq
|
|
99
|
+
value_type: string
|
|
100
|
+
value_string: superadmin
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When a contradiction is intentional evolution rather than a real conflict, link the replaced requirement to the replacement requirement with `supersedes`.
|
|
104
|
+
|
|
105
|
+
## Context Lane (Non-Blocking)
|
|
106
|
+
|
|
107
|
+
### fact_kind: observation
|
|
108
|
+
For bug records, incident notes, and observed behavior.
|
|
109
|
+
```yaml
|
|
110
|
+
id: FACT-BUG-123
|
|
111
|
+
title: Login fails on Safari 17
|
|
112
|
+
status: active
|
|
113
|
+
fact_kind: observation
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### fact_kind: meta
|
|
117
|
+
For governance notes, process commentary, and workaround documentation.
|
|
118
|
+
```yaml
|
|
119
|
+
id: FACT-WORKAROUND-456
|
|
120
|
+
title: Temporary cache bypass for v2 migration
|
|
121
|
+
status: active
|
|
122
|
+
fact_kind: meta
|
|
123
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
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
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
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. **Create endpoints**: `kb_upsert` for new entities (sequential)
|
|
11
|
+
5. **Link**: `kb_upsert` with relationship rows (sequential)
|
|
12
|
+
6. **Validate**: `kb_check` with targeted rules during work, full check at completion
|
|
13
|
+
|
|
14
|
+
## Creating a New Feature
|
|
15
|
+
```
|
|
16
|
+
1. kb_search to discover existing requirements and related knowledge
|
|
17
|
+
2. kb_query to confirm exact IDs and source-linked context
|
|
18
|
+
3. kb_upsert for new or updated requirements (include relationship rows)
|
|
19
|
+
4. kb_check with targeted rules
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Fixing a Traceability Gap
|
|
23
|
+
```
|
|
24
|
+
1. kb_query --sourceFile <code-file> to find linked entities
|
|
25
|
+
2. kb_find_gaps --type req --missing-rel specified_by to find orphan requirements
|
|
26
|
+
3. kb_upsert to add missing relationship rows (sequential)
|
|
27
|
+
4. kb_check with rules: ["no-dangling-refs", "symbol-traceability"]
|
|
28
|
+
```
|