@cakemail-org/cakemail-cli 1.7.0 → 2.0.0

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.
Files changed (198) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +41 -37
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/client.js +1 -1
  9. package/dist/client.js.map +1 -1
  10. package/dist/commands/account.js +1 -1
  11. package/dist/commands/account.js.map +1 -1
  12. package/dist/commands/attributes.js +1 -1
  13. package/dist/commands/attributes.js.map +1 -1
  14. package/dist/commands/campaigns.js +1 -1
  15. package/dist/commands/campaigns.js.map +1 -1
  16. package/dist/commands/contacts.js +1 -1
  17. package/dist/commands/contacts.js.map +1 -1
  18. package/dist/commands/emails.js +1 -1
  19. package/dist/commands/emails.js.map +1 -1
  20. package/dist/commands/interests.js +1 -1
  21. package/dist/commands/interests.js.map +1 -1
  22. package/dist/commands/lists.js +1 -1
  23. package/dist/commands/lists.js.map +1 -1
  24. package/dist/commands/logs.js +1 -1
  25. package/dist/commands/logs.js.map +1 -1
  26. package/dist/commands/reports.js +1 -1
  27. package/dist/commands/reports.js.map +1 -1
  28. package/dist/commands/segments.js +1 -1
  29. package/dist/commands/segments.js.map +1 -1
  30. package/dist/commands/senders.js +1 -1
  31. package/dist/commands/senders.js.map +1 -1
  32. package/dist/commands/suppressed.js +1 -1
  33. package/dist/commands/suppressed.js.map +1 -1
  34. package/dist/commands/tags.js +1 -1
  35. package/dist/commands/tags.js.map +1 -1
  36. package/dist/commands/templates.js +1 -1
  37. package/dist/commands/templates.js.map +1 -1
  38. package/dist/commands/transactional-templates.js +1 -1
  39. package/dist/commands/transactional-templates.js.map +1 -1
  40. package/dist/commands/webhooks.js +1 -1
  41. package/dist/commands/webhooks.js.map +1 -1
  42. package/dist/utils/config.js +2 -2
  43. package/dist/utils/config.js.map +1 -1
  44. package/dist/utils/errors.js +1 -1
  45. package/dist/utils/errors.js.map +1 -1
  46. package/dist/utils/progress.d.ts.map +1 -1
  47. package/dist/utils/progress.js +32 -4
  48. package/dist/utils/progress.js.map +1 -1
  49. package/dist/utils/spinner.d.ts +17 -0
  50. package/dist/utils/spinner.d.ts.map +1 -0
  51. package/dist/utils/spinner.js +43 -0
  52. package/dist/utils/spinner.js.map +1 -0
  53. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  54. package/docs/README.md +161 -0
  55. package/docs/developer/ARCHITECTURE.md +516 -0
  56. package/docs/developer/AUTH.md +204 -0
  57. package/docs/developer/CONTRIBUTING.md +227 -0
  58. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  59. package/docs/developer/PROJECT_INDEX.md +365 -0
  60. package/docs/planning/API_COVERAGE.md +1045 -0
  61. package/docs/planning/BACKLOG.md +1159 -0
  62. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  63. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  64. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  65. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  66. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  67. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  68. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  69. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  70. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  71. package/docs/user-manual/.obsidian/app.json +1 -0
  72. package/docs/user-manual/.obsidian/appearance.json +1 -0
  73. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  74. package/docs/user-manual/.obsidian/workspace.json +167 -0
  75. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  76. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  77. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  78. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  79. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  80. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  81. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  82. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  83. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  84. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  85. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  86. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  87. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  88. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  89. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  90. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  91. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  92. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  93. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  94. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  95. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  96. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  97. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  98. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  99. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  100. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  101. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  102. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  103. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  104. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  105. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  106. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  107. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  108. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  109. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  110. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  111. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  112. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  113. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  114. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  115. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  116. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  117. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  118. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  119. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  120. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  121. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  122. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  123. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  124. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  125. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  126. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  127. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  128. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  129. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  130. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  131. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  132. package/docs/user-manual/README.md +0 -0
  133. package/package.json +13 -61
  134. package/src/cli.ts +125 -0
  135. package/src/client.ts +16 -0
  136. package/src/commands/account.ts +267 -0
  137. package/src/commands/accounts.ts +78 -0
  138. package/src/commands/actions.ts +249 -0
  139. package/src/commands/attributes.ts +139 -0
  140. package/src/commands/campaign-blueprints.ts +106 -0
  141. package/src/commands/campaigns.ts +469 -0
  142. package/src/commands/config.ts +77 -0
  143. package/src/commands/contacts.ts +612 -0
  144. package/src/commands/custom-attributes.ts +127 -0
  145. package/src/commands/dkims.ts +117 -0
  146. package/src/commands/domains.ts +82 -0
  147. package/src/commands/email-apis.ts +569 -0
  148. package/src/commands/emails.ts +197 -0
  149. package/src/commands/forms.ts +283 -0
  150. package/src/commands/interests.ts +155 -0
  151. package/src/commands/links.ts +38 -0
  152. package/src/commands/lists.ts +406 -0
  153. package/src/commands/logos.ts +71 -0
  154. package/src/commands/logs.ts +386 -0
  155. package/src/commands/reports.ts +306 -0
  156. package/src/commands/segments.ts +158 -0
  157. package/src/commands/senders.ts +204 -0
  158. package/src/commands/sub-accounts.ts +271 -0
  159. package/src/commands/suppressed-emails.ts +234 -0
  160. package/src/commands/suppressed.ts +198 -0
  161. package/src/commands/system-emails.ts +85 -0
  162. package/src/commands/tags.ts +146 -0
  163. package/src/commands/tasks.ts +116 -0
  164. package/src/commands/templates.ts +189 -0
  165. package/src/commands/tokens.ts +83 -0
  166. package/src/commands/transactional-emails.ts +374 -0
  167. package/src/commands/transactional-templates.ts +385 -0
  168. package/src/commands/users.ts +506 -0
  169. package/src/commands/webhooks.ts +172 -0
  170. package/src/commands/workflow-blueprints.ts +123 -0
  171. package/src/commands/workflows.ts +265 -0
  172. package/src/types/profile.ts +93 -0
  173. package/src/utils/auth.ts +272 -0
  174. package/src/utils/config-file.ts +96 -0
  175. package/src/utils/config.ts +134 -0
  176. package/src/utils/confirm.ts +32 -0
  177. package/src/utils/defaults.ts +99 -0
  178. package/src/utils/errors.ts +116 -0
  179. package/src/utils/interactive.ts +91 -0
  180. package/src/utils/list-defaults.ts +74 -0
  181. package/src/utils/output.ts +190 -0
  182. package/src/utils/progress.ts +320 -0
  183. package/src/utils/spinner.ts +22 -0
  184. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  185. package/tests/PTY_SETUP.md +118 -0
  186. package/tests/PTY_TESTING_GUIDE.md +507 -0
  187. package/tests/README.md +244 -0
  188. package/tests/fixtures/api-responses/campaigns.json +34 -0
  189. package/tests/fixtures/test-config.json +13 -0
  190. package/tests/helpers/cli-runner.ts +128 -0
  191. package/tests/helpers/mock-server.ts +301 -0
  192. package/tests/helpers/pty-runner.ts +181 -0
  193. package/tests/integration/campaigns-real-api.test.ts +196 -0
  194. package/tests/integration/setup-integration.ts +50 -0
  195. package/tests/pty/campaigns.test.ts +241 -0
  196. package/tests/setup.ts +34 -0
  197. package/tsconfig.json +15 -0
  198. package/vitest.config.ts +28 -0
@@ -0,0 +1,1369 @@
1
+ # Kenogami: Multi-Source Truth Reconciliation System
2
+
3
+ ## Executive Summary
4
+
5
+ The fundamental challenge: **Truth exists in multiple places**, each with different authority and purpose. The knowledge graph is not the ultimate source of truth—it's a **reconciliation layer** that harmonizes truths from multiple authoritative sources, detects conflicts, identifies gaps, and maintains coherence across the entire system.
6
+
7
+ **Core Insight:** Don't force a single source of truth. Instead, recognize that truth is **distributed** and **context-dependent**, then build systems to **reconcile**, **validate**, and **synthesize** these distributed truths.
8
+
9
+ ---
10
+
11
+ ## The Reality: Distributed Sources of Truth
12
+
13
+ ### Source 1: Product Code (Implementation Truth)
14
+
15
+ **What it represents:** What the system *actually does*
16
+
17
+ ```typescript
18
+ // cakemail-cli/src/commands/campaigns.ts
19
+ export function createCampaignsCommand() {
20
+ return new Command('campaigns')
21
+ .command('list')
22
+ .option('-s, --status <status>', 'Filter by status')
23
+ .option('-l, --limit <number>', 'Limit results')
24
+ .action(async (options) => {
25
+ // Implementation details
26
+ });
27
+ }
28
+ ```
29
+
30
+ **Authority Level:** 🔴 **HIGHEST** - This is objective reality
31
+ **Characteristics:**
32
+ - Definitive for "what is implemented"
33
+ - Changes through code commits
34
+ - Version controlled
35
+ - Can be analyzed programmatically (AST parsing, type inference)
36
+
37
+ **Limitations:**
38
+ - Doesn't explain *why*
39
+ - Doesn't document *intent*
40
+ - Doesn't describe *workflows* or *best practices*
41
+ - Doesn't capture *user perspective*
42
+
43
+ ### Source 2: API/OpenAPI Specification (Contract Truth)
44
+
45
+ **What it represents:** What the system *promises to do*
46
+
47
+ ```yaml
48
+ # Cakemail API OpenAPI spec
49
+ /campaigns:
50
+ get:
51
+ parameters:
52
+ - name: status
53
+ in: query
54
+ schema:
55
+ type: string
56
+ enum: [draft, sent, scheduled]
57
+ ```
58
+
59
+ **Authority Level:** 🟠 **HIGH** - This is the contract
60
+ **Characteristics:**
61
+ - Authoritative for API behavior
62
+ - Version controlled
63
+ - Machine-readable
64
+ - Can drift from implementation (bug or spec issue)
65
+
66
+ **Limitations:**
67
+ - May lag behind implementation
68
+ - Doesn't include CLI-specific features
69
+ - Doesn't describe user journeys
70
+
71
+ ### Source 3: Original Documentation (Intent Truth)
72
+
73
+ **What it represents:** What the product team *intended* to communicate
74
+
75
+ ```markdown
76
+ # Creating Campaigns
77
+
78
+ To create a campaign, use the `campaigns create` command.
79
+ You'll need a list ID and sender ID...
80
+ ```
81
+
82
+ **Authority Level:** 🟡 **MEDIUM** - This is the official narrative
83
+ **Characteristics:**
84
+ - Captures product team's intent
85
+ - Includes context, rationale, workflows
86
+ - Human-written, human-optimized
87
+ - May drift from reality over time
88
+
89
+ **Limitations:**
90
+ - Can become outdated
91
+ - May have inconsistencies
92
+ - Subjective writing style
93
+
94
+ ### Source 4: User Behavior Data (Usage Truth)
95
+
96
+ **What it represents:** How users *actually use* the product
97
+
98
+ ```json
99
+ {
100
+ "command": "cakemail campaigns list --status sent",
101
+ "frequency": 1247,
102
+ "success_rate": 0.94,
103
+ "common_next_command": "cakemail campaigns get <id>"
104
+ }
105
+ ```
106
+
107
+ **Authority Level:** 🟡 **MEDIUM** - This is behavioral reality
108
+ **Characteristics:**
109
+ - Shows actual usage patterns
110
+ - Reveals what users care about
111
+ - Indicates what works / doesn't work
112
+ - Data-driven insights
113
+
114
+ **Limitations:**
115
+ - Doesn't explain intent
116
+ - May show workarounds, not ideal usage
117
+ - Includes both correct and incorrect usage
118
+
119
+ ### Source 5: Customer Support Tickets (Problem Truth)
120
+
121
+ **What it represents:** Where users *struggle*
122
+
123
+ ```
124
+ Ticket #4521: "I tried 'campaigns list --status sending' but got an error.
125
+ The docs say 'sending' is a valid status, but it doesn't work."
126
+
127
+ Root Cause: Docs outdated. Status 'sending' was replaced with 'in_progress' in v1.5
128
+ ```
129
+
130
+ **Authority Level:** 🟢 **LOW-MEDIUM** - This is the pain point signal
131
+ **Characteristics:**
132
+ - Identifies documentation gaps
133
+ - Shows common misconceptions
134
+ - Reveals UX problems
135
+ - Indicates priority areas
136
+
137
+ **Limitations:**
138
+ - Biased toward problems (not successes)
139
+ - May include user error
140
+ - Needs human interpretation
141
+
142
+ ### Source 6: Chatbot Conversations (Learning Truth)
143
+
144
+ **What it represents:** What users *ask about* and how they *learn*
145
+
146
+ ```
147
+ User: "How do I create a campaign?"
148
+ Bot: "Use 'cakemail campaigns create --name "My Campaign" --list-id 123'"
149
+ User: "What's a list ID?"
150
+ Bot: "A list ID is the unique identifier for your contact list..."
151
+ ```
152
+
153
+ **Authority Level:** 🟢 **LOW** - This is the learning journey
154
+ **Characteristics:**
155
+ - Shows knowledge gaps
156
+ - Reveals terminology confusion
157
+ - Indicates documentation clarity issues
158
+ - Captures natural language queries
159
+
160
+ **Limitations:**
161
+ - Conversational, not canonical
162
+ - May include bot hallucinations
163
+ - Context-dependent
164
+
165
+ ### Source 7: Test Results (Validation Truth)
166
+
167
+ **What it represents:** What has been *verified* to work
168
+
169
+ ```json
170
+ {
171
+ "test": "campaigns list with status filter",
172
+ "status": "PASS",
173
+ "actual_output": {...},
174
+ "matches_documentation": true,
175
+ "matches_implementation": true
176
+ }
177
+ ```
178
+
179
+ **Authority Level:** 🔵 **VALIDATION** - This is verification
180
+ **Characteristics:**
181
+ - Proves what works
182
+ - Detects regressions
183
+ - Validates consistency
184
+ - Objective measurement
185
+
186
+ **Limitations:**
187
+ - Only tests what we think to test
188
+ - Can have bugs in tests themselves
189
+ - Doesn't capture intent
190
+
191
+ ---
192
+
193
+ ## The Problem: Truth Conflicts & Gaps
194
+
195
+ ### Conflict Types
196
+
197
+ **Type 1: Code vs Documentation**
198
+ ```
199
+ Code: Parameter 'status' accepts: ['draft', 'sent', 'scheduled', 'failed']
200
+ Docs: Parameter 'status' accepts: ['draft', 'sent', 'sending', 'scheduled']
201
+ Conflict: 'failed' missing from docs, 'sending' doesn't exist in code
202
+ ```
203
+
204
+ **Type 2: API Spec vs Implementation**
205
+ ```
206
+ Spec: Max limit is 100
207
+ CLI Code: No max limit enforced (accepts any number)
208
+ API Code: Max limit is 50
209
+ Conflict: Three different truths!
210
+ ```
211
+
212
+ **Type 3: Documentation Inconsistency**
213
+ ```
214
+ Tutorial: "Use --format json to get JSON output"
215
+ Reference: "JSON is the default format"
216
+ Quick Start: "Use -f table for readable output"
217
+ Conflict: What's actually the default?
218
+ ```
219
+
220
+ **Type 4: Usage vs Intent**
221
+ ```
222
+ Intended: Users should use 'campaigns create' with all parameters
223
+ Actual: 80% of users use interactive mode (no parameters)
224
+ Conflict: Documentation focuses on non-interactive, users prefer interactive
225
+ ```
226
+
227
+ **Type 5: Support vs Documentation**
228
+ ```
229
+ Docs: "Authentication is automatic"
230
+ Tickets: 50 tickets about "How do I authenticate?"
231
+ Conflict: Documentation assumption doesn't match user understanding
232
+ ```
233
+
234
+ ### Gap Types
235
+
236
+ **Type 1: Undocumented Features**
237
+ ```
238
+ Code: Supports '--batch' flag for non-interactive mode
239
+ Docs: No mention of batch mode
240
+ Gap: Feature exists but not documented
241
+ ```
242
+
243
+ **Type 2: Documented but Not Implemented**
244
+ ```
245
+ Docs: "Use --template-id to create campaign from template"
246
+ Code: --template-id option doesn't exist yet
247
+ Gap: Documentation ahead of implementation (planned feature?)
248
+ ```
249
+
250
+ **Type 3: Missing Workflows**
251
+ ```
252
+ Commands: campaigns create, campaigns schedule, campaigns send
253
+ Docs: Each command documented separately
254
+ Gap: Complete workflow not documented
255
+ Usage Data: Users struggle to understand the sequence
256
+ ```
257
+
258
+ **Type 4: Hidden Knowledge**
259
+ ```
260
+ Support: "First confirm your sender before creating campaigns"
261
+ Docs: No mention of sender confirmation requirement
262
+ Code: Checks for confirmed sender, returns cryptic error if not
263
+ Gap: Domain knowledge only in support team's heads
264
+ ```
265
+
266
+ ---
267
+
268
+ ## The Solution: Multi-Layer Truth Reconciliation
269
+
270
+ ### Architecture Overview
271
+
272
+ ```
273
+ ┌─────────────────────────────────────────────────────────────────┐
274
+ │ TRUTH SOURCES (Multiple) │
275
+ └─────────────────────────────────────────────────────────────────┘
276
+ │ │ │ │ │ │ │
277
+ │Product │ API │Original │ Usage │Support │ Chatbot │
278
+ │ Code │ Spec │ Docs │ Data │Tickets │ Logs │
279
+ │ │ │ │ │ │ │
280
+ └────┬────┴────┬────┴────┬────┴────┬────┴────┬────┴────┬────┘
281
+ │ │ │ │ │ │
282
+ └─────────┴─────────┴─────────┴─────────┴─────────┘
283
+
284
+
285
+ ┌────────────────────────────────────────────────┐
286
+ │ EXTRACTION & INGESTION LAYER │
287
+ │ - Code AST Parser │
288
+ │ - OpenAPI Parser │
289
+ │ - Markdown Parser │
290
+ │ - Analytics Aggregator │
291
+ │ - Ticket Classifier │
292
+ │ - Conversation Analyzer │
293
+ └────────────────┬───────────────────────────────┘
294
+
295
+
296
+ ┌────────────────────────────────────────────────┐
297
+ │ RECONCILIATION ENGINE │
298
+ │ - Conflict Detection │
299
+ │ - Gap Analysis │
300
+ │ - Truth Scoring │
301
+ │ - Canonical Resolution │
302
+ └────────────────┬───────────────────────────────┘
303
+
304
+
305
+ ┌────────────────────────────────────────────────┐
306
+ │ KNOWLEDGE GRAPH (Reconciled) │
307
+ │ │
308
+ │ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
309
+ │ │ Facts │ │Conflicts │ │ Gaps │ │
310
+ │ │ (Nodes) │ │ (Edges) │ │ (Nodes) │ │
311
+ │ └──────────┘ └──────────┘ └─────────┘ │
312
+ │ │
313
+ │ Each fact has provenance: │
314
+ │ - source: [code, spec, docs, usage, ...] │
315
+ │ - confidence: 0.0-1.0 │
316
+ │ - last_verified: timestamp │
317
+ │ - conflicts_with: [other facts] │
318
+ └────────────────┬───────────────────────────────┘
319
+
320
+ ┌───────────┴──────────┐
321
+ │ │
322
+ ▼ ▼
323
+ ┌──────────────────┐ ┌──────────────────┐
324
+ │ OUTPUT LAYER │ │ FEEDBACK LAYER │
325
+ │ - Articles │ │ - CI/CD Alerts │
326
+ │ - Tests │ │ - Dashboards │
327
+ │ - API Docs │ │ - GitHub Issues │
328
+ │ - Chatbot KB │ │ - Slack Notifs │
329
+ └──────────────────┘ └──────────────────┘
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Truth Reconciliation Strategies
335
+
336
+ ### Strategy 1: Hierarchical Authority
337
+
338
+ Different sources have different authority for different questions:
339
+
340
+ ```typescript
341
+ interface TruthAuthority {
342
+ question: string;
343
+ primarySource: Source;
344
+ validationSources: Source[];
345
+ tieBreaker: Source;
346
+ }
347
+
348
+ const authorityRules: TruthAuthority[] = [
349
+ {
350
+ question: "What parameters does this command accept?",
351
+ primarySource: "product_code", // Code is ground truth
352
+ validationSources: ["api_spec", "test_results"],
353
+ tieBreaker: "test_results" // If code and spec conflict, tests prove reality
354
+ },
355
+ {
356
+ question: "What is the recommended workflow?",
357
+ primarySource: "documentation", // Product team's intent
358
+ validationSources: ["usage_data"],
359
+ tieBreaker: "usage_data" // But if users do something different, consider it
360
+ },
361
+ {
362
+ question: "What terminology should we use?",
363
+ primarySource: "documentation", // Canonical terms
364
+ validationSources: ["chatbot_logs"],
365
+ tieBreaker: "chatbot_logs" // Users' natural language reveals confusion
366
+ },
367
+ {
368
+ question: "Is this feature working correctly?",
369
+ primarySource: "test_results", // Tests prove it works
370
+ validationSources: ["support_tickets"],
371
+ tieBreaker: "support_tickets" // Tickets reveal edge cases tests missed
372
+ }
373
+ ];
374
+ ```
375
+
376
+ ### Strategy 2: Temporal Consensus
377
+
378
+ Truth can change over time. Track when each source was last updated:
379
+
380
+ ```typescript
381
+ interface TemporalFact {
382
+ fact: "campaigns list supports --format parameter";
383
+ sources: [
384
+ {
385
+ source: "code",
386
+ value: true,
387
+ timestamp: "2025-01-15T10:00:00Z",
388
+ version: "v1.5.0"
389
+ },
390
+ {
391
+ source: "documentation",
392
+ value: true,
393
+ timestamp: "2025-01-20T14:30:00Z", // Updated 5 days later
394
+ version: "docs-rev-234"
395
+ },
396
+ {
397
+ source: "test_results",
398
+ value: true,
399
+ timestamp: "2025-01-15T10:05:00Z", // Tested immediately
400
+ lastRun: "2025-10-26T08:00:00Z"
401
+ }
402
+ ];
403
+ }
404
+
405
+ // Reconciliation logic
406
+ function reconcile(fact: TemporalFact): Resolution {
407
+ const newestSource = maxBy(fact.sources, s => s.timestamp);
408
+ const outdatedSources = fact.sources.filter(s =>
409
+ s.timestamp < newestSource.timestamp - STALENESS_THRESHOLD
410
+ );
411
+
412
+ if (outdatedSources.length > 0) {
413
+ return {
414
+ status: "NEEDS_UPDATE",
415
+ canonical: newestSource.value,
416
+ stale: outdatedSources,
417
+ action: `Update ${outdatedSources.map(s => s.source).join(', ')}`
418
+ };
419
+ }
420
+
421
+ return { status: "CONSISTENT" };
422
+ }
423
+ ```
424
+
425
+ ### Strategy 3: Confidence Scoring
426
+
427
+ Not all statements are equal. Score confidence based on multiple factors:
428
+
429
+ ```typescript
430
+ interface ConfidenceScore {
431
+ fact: string;
432
+ confidence: number; // 0.0 - 1.0
433
+ factors: {
434
+ sourceAuthority: number; // How authoritative is the source?
435
+ sourceFreshness: number; // How recent is the information?
436
+ sourceConsensus: number; // How many sources agree?
437
+ validationStatus: number; // Has it been tested/verified?
438
+ userConfirmation: number; // Do users' actions confirm it?
439
+ supportEvidence: number; // Do tickets confirm or contradict?
440
+ };
441
+ }
442
+
443
+ function calculateConfidence(fact: Fact): ConfidenceScore {
444
+ const scores = {
445
+ sourceAuthority: calculateAuthorityScore(fact.sources),
446
+ sourceFreshness: calculateFreshnessScore(fact.sources),
447
+ sourceConsensus: calculateConsensusScore(fact.sources),
448
+ validationStatus: fact.testResults?.passed ? 1.0 : 0.5,
449
+ userConfirmation: calculateUsageAlignment(fact, usageData),
450
+ supportEvidence: calculateTicketAlignment(fact, tickets)
451
+ };
452
+
453
+ // Weighted average
454
+ const weights = {
455
+ sourceAuthority: 0.3,
456
+ sourceFreshness: 0.2,
457
+ sourceConsensus: 0.2,
458
+ validationStatus: 0.15,
459
+ userConfirmation: 0.10,
460
+ supportEvidence: 0.05
461
+ };
462
+
463
+ const confidence = Object.entries(scores).reduce(
464
+ (sum, [key, score]) => sum + score * weights[key],
465
+ 0
466
+ );
467
+
468
+ return { fact: fact.statement, confidence, factors: scores };
469
+ }
470
+ ```
471
+
472
+ ### Strategy 4: Gap Detection Patterns
473
+
474
+ Systematically identify gaps using cross-source analysis:
475
+
476
+ ```typescript
477
+ class GapDetector {
478
+ async detectGaps(): Promise<Gap[]> {
479
+ const gaps: Gap[] = [];
480
+
481
+ // Gap Type 1: Code features not documented
482
+ const undocumentedFeatures = await this.findUndocumentedFeatures();
483
+ gaps.push(...undocumentedFeatures.map(f => ({
484
+ type: 'undocumented_feature',
485
+ severity: 'high',
486
+ description: `Feature '${f.name}' exists in code but not documented`,
487
+ sources: { has: ['code'], missing: ['documentation'] },
488
+ action: 'Document this feature'
489
+ })));
490
+
491
+ // Gap Type 2: Documentation references non-existent features
492
+ const ghostFeatures = await this.findGhostFeatures();
493
+ gaps.push(...ghostFeatures.map(f => ({
494
+ type: 'ghost_feature',
495
+ severity: 'critical',
496
+ description: `Documentation mentions '${f.name}' but it doesn't exist in code`,
497
+ sources: { has: ['documentation'], missing: ['code'] },
498
+ action: 'Remove from docs OR implement feature'
499
+ })));
500
+
501
+ // Gap Type 3: High usage features not well documented
502
+ const underdocumentedFeatures = await this.findUnderdocumented();
503
+ gaps.push(...underdocumentedFeatures.map(f => ({
504
+ type: 'underdocumented',
505
+ severity: 'medium',
506
+ description: `Feature '${f.name}' is heavily used (${f.usageCount} times) but docs are minimal`,
507
+ sources: { has: ['code', 'usage_data'], insufficient: ['documentation'] },
508
+ action: 'Expand documentation with examples and best practices'
509
+ })));
510
+
511
+ // Gap Type 4: Common support questions not in docs
512
+ const faqGaps = await this.findFAQGaps();
513
+ gaps.push(...faqGaps.map(q => ({
514
+ type: 'missing_faq',
515
+ severity: 'medium',
516
+ description: `Common question: "${q.question}" (${q.ticketCount} tickets)`,
517
+ sources: { has: ['support_tickets'], missing: ['documentation'] },
518
+ action: 'Add FAQ entry or improve relevant documentation'
519
+ })));
520
+
521
+ // Gap Type 5: Workflows implied but not documented
522
+ const workflowGaps = await this.findWorkflowGaps();
523
+ gaps.push(...workflowGaps.map(w => ({
524
+ type: 'missing_workflow',
525
+ severity: 'high',
526
+ description: `Common sequence: ${w.steps.join(' → ')} (${w.frequency} occurrences)`,
527
+ sources: { has: ['usage_data'], missing: ['documentation'] },
528
+ action: 'Document this workflow as a tutorial'
529
+ })));
530
+
531
+ return gaps;
532
+ }
533
+
534
+ async findUndocumentedFeatures(): Promise<Feature[]> {
535
+ // Find features in code
536
+ const codeFeatures = await this.extractFeaturesFromCode();
537
+
538
+ // Find features in docs
539
+ const docFeatures = await this.extractFeaturesFromDocs();
540
+
541
+ // Features in code but not in docs
542
+ return codeFeatures.filter(cf =>
543
+ !docFeatures.some(df => df.name === cf.name)
544
+ );
545
+ }
546
+
547
+ async findWorkflowGaps(): Promise<Workflow[]> {
548
+ // Analyze command sequences from usage data
549
+ const sequences = await this.analyzeCommandSequences(usageData);
550
+
551
+ // Find common patterns (e.g., "create → schedule → send")
552
+ const commonWorkflows = sequences.filter(s =>
553
+ s.frequency > WORKFLOW_THRESHOLD
554
+ );
555
+
556
+ // Check if documented
557
+ const documentedWorkflows = await this.getDocumentedWorkflows();
558
+
559
+ return commonWorkflows.filter(cw =>
560
+ !documentedWorkflows.some(dw => dw.matches(cw))
561
+ );
562
+ }
563
+ }
564
+ ```
565
+
566
+ ### Strategy 5: Conflict Resolution Pipeline
567
+
568
+ When sources conflict, use a systematic resolution process:
569
+
570
+ ```typescript
571
+ class ConflictResolver {
572
+ async resolve(conflict: Conflict): Promise<Resolution> {
573
+ // Step 1: Identify conflict type
574
+ const conflictType = this.classifyConflict(conflict);
575
+
576
+ // Step 2: Apply appropriate resolution strategy
577
+ switch (conflictType) {
578
+ case 'code_vs_docs':
579
+ return this.resolveCodeVsDocs(conflict);
580
+
581
+ case 'spec_vs_implementation':
582
+ return this.resolveSpecVsImpl(conflict);
583
+
584
+ case 'intent_vs_usage':
585
+ return this.resolveIntentVsUsage(conflict);
586
+
587
+ case 'multiple_doc_versions':
588
+ return this.resolveDocInconsistency(conflict);
589
+
590
+ default:
591
+ return this.escalateToHuman(conflict);
592
+ }
593
+ }
594
+
595
+ async resolveCodeVsDocs(conflict: Conflict): Promise<Resolution> {
596
+ // Code is authoritative for "what is"
597
+ // But check if code might be the bug
598
+
599
+ // Run tests
600
+ const testResult = await this.runTests(conflict.codeVersion);
601
+
602
+ if (!testResult.passed) {
603
+ // Code is broken, docs might be right
604
+ return {
605
+ canonical: conflict.docsVersion,
606
+ action: 'FIX_CODE',
607
+ reason: 'Code fails tests, documentation describes correct behavior',
608
+ evidence: testResult
609
+ };
610
+ }
611
+
612
+ // Code works, check if it matches API spec
613
+ const specCheck = await this.checkAgainstSpec(conflict.codeVersion);
614
+
615
+ if (!specCheck.matches) {
616
+ // Code works but doesn't match spec - need decision
617
+ return {
618
+ canonical: null,
619
+ action: 'DECISION_REQUIRED',
620
+ reason: 'Code works but deviates from API spec',
621
+ options: [
622
+ { action: 'UPDATE_SPEC', rationale: 'Code is better' },
623
+ { action: 'UPDATE_CODE', rationale: 'Spec is the contract' }
624
+ ]
625
+ };
626
+ }
627
+
628
+ // Code is correct, update docs
629
+ return {
630
+ canonical: conflict.codeVersion,
631
+ action: 'UPDATE_DOCS',
632
+ reason: 'Code is tested and matches spec'
633
+ };
634
+ }
635
+
636
+ async resolveIntentVsUsage(conflict: Conflict): Promise<Resolution> {
637
+ // Product intent says one thing, users do another
638
+
639
+ const usageStrength = conflict.usageData.frequency;
640
+ const intentClarity = conflict.documentation.clarity_score;
641
+
642
+ if (usageStrength > HIGH_USAGE_THRESHOLD && intentClarity < LOW_CLARITY_THRESHOLD) {
643
+ // Users found a better way despite poor docs
644
+ return {
645
+ canonical: 'HYBRID',
646
+ action: 'DOCUMENT_BOTH',
647
+ reason: 'Users prefer alternative approach, both should be documented',
648
+ recommendation: {
649
+ primary: conflict.usageData.approach,
650
+ alternative: conflict.documentation.approach
651
+ }
652
+ };
653
+ }
654
+
655
+ if (conflict.supportTickets.count > TICKET_THRESHOLD) {
656
+ // Intent is confusing users
657
+ return {
658
+ canonical: conflict.usageData.approach,
659
+ action: 'UPDATE_INTENT',
660
+ reason: 'User behavior reveals better UX',
661
+ evidence: conflict.supportTickets
662
+ };
663
+ }
664
+
665
+ // Intent is clear, users just need guidance
666
+ return {
667
+ canonical: conflict.documentation.approach,
668
+ action: 'IMPROVE_DOCS',
669
+ reason: 'Add examples showing intended usage pattern'
670
+ };
671
+ }
672
+ }
673
+ ```
674
+
675
+ ---
676
+
677
+ ## Knowledge Graph Schema: Multi-Source Model
678
+
679
+ ### Enhanced Node Schema
680
+
681
+ ```typescript
682
+ interface FactNode {
683
+ id: string;
684
+ type: 'command' | 'parameter' | 'concept' | 'workflow' | 'error';
685
+
686
+ // The canonical fact (reconciled truth)
687
+ canonicalValue: any;
688
+ confidence: number; // 0.0 - 1.0
689
+
690
+ // Provenance: where did this fact come from?
691
+ sources: SourceEvidence[];
692
+
693
+ // Temporal tracking
694
+ firstSeen: Date;
695
+ lastUpdated: Date;
696
+ lastVerified: Date;
697
+
698
+ // Conflict tracking
699
+ hasConflicts: boolean;
700
+ conflicts?: Conflict[];
701
+
702
+ // Gap tracking
703
+ hasGaps: boolean;
704
+ gaps?: Gap[];
705
+
706
+ // Metadata
707
+ tags: string[];
708
+ version: string;
709
+ }
710
+
711
+ interface SourceEvidence {
712
+ source: 'code' | 'spec' | 'docs' | 'usage' | 'support' | 'chatbot' | 'tests';
713
+ value: any;
714
+ confidence: number;
715
+ timestamp: Date;
716
+ version?: string;
717
+
718
+ // Provenance details
719
+ location?: string; // File path, URL, ticket ID, etc.
720
+ extractedBy?: string; // Parser, human, AI, etc.
721
+ validatedBy?: string[]; // What validated this?
722
+
723
+ // Metadata
724
+ metadata?: {
725
+ commit?: string;
726
+ author?: string;
727
+ reviewers?: string[];
728
+ [key: string]: any;
729
+ };
730
+ }
731
+
732
+ interface Conflict {
733
+ id: string;
734
+ type: 'value_mismatch' | 'presence_mismatch' | 'intent_mismatch';
735
+ severity: 'low' | 'medium' | 'high' | 'critical';
736
+
737
+ sources: [SourceEvidence, SourceEvidence]; // Conflicting sources
738
+ description: string;
739
+
740
+ // Resolution
741
+ status: 'detected' | 'analyzing' | 'resolved' | 'escalated';
742
+ resolution?: Resolution;
743
+ resolvedAt?: Date;
744
+ resolvedBy?: string; // 'ai' | 'human' | 'test'
745
+ }
746
+
747
+ interface Gap {
748
+ id: string;
749
+ type: 'undocumented' | 'unimplemented' | 'undertested' | 'underused' | 'faq_missing';
750
+ severity: 'low' | 'medium' | 'high' | 'critical';
751
+
752
+ description: string;
753
+ evidence: SourceEvidence[];
754
+
755
+ // Impact
756
+ affectedUsers?: number;
757
+ supportTicketCount?: number;
758
+ usageFrequency?: number;
759
+
760
+ // Resolution
761
+ status: 'detected' | 'planned' | 'in_progress' | 'resolved';
762
+ assignedTo?: string;
763
+ dueDate?: Date;
764
+ }
765
+ ```
766
+
767
+ ### Graph Relationships with Provenance
768
+
769
+ ```cypher
770
+ // Command with multiple source evidence
771
+ CREATE (c:Command {
772
+ id: 'cmd-campaigns-list',
773
+ canonicalValue: {
774
+ name: 'campaigns list',
775
+ parameters: ['status', 'limit', 'page']
776
+ },
777
+ confidence: 0.95
778
+ })
779
+
780
+ // Source evidence from code
781
+ CREATE (e1:Evidence {
782
+ source: 'code',
783
+ location: 'src/commands/campaigns.ts:45',
784
+ extractedAt: datetime('2025-10-26T10:00:00Z'),
785
+ value: {
786
+ parameters: ['status', 'limit', 'page', 'sort'] // Note: has 'sort'!
787
+ }
788
+ })
789
+
790
+ // Source evidence from docs
791
+ CREATE (e2:Evidence {
792
+ source: 'documentation',
793
+ location: 'docs/commands/campaigns.md',
794
+ extractedAt: datetime('2025-10-20T14:00:00Z'),
795
+ value: {
796
+ parameters: ['status', 'limit', 'page'] // Note: missing 'sort'!
797
+ }
798
+ })
799
+
800
+ // Source evidence from tests
801
+ CREATE (e3:Evidence {
802
+ source: 'test_results',
803
+ location: 'tests/campaigns.test.ts',
804
+ lastRun: datetime('2025-10-26T08:00:00Z'),
805
+ value: {
806
+ parameters: ['status', 'limit', 'page', 'sort'], // Confirms 'sort' exists
807
+ allPassed: true
808
+ }
809
+ })
810
+
811
+ // Relationships
812
+ CREATE (c)-[:HAS_EVIDENCE {confidence: 0.9}]->(e1)
813
+ CREATE (c)-[:HAS_EVIDENCE {confidence: 0.7}]->(e2)
814
+ CREATE (c)-[:HAS_EVIDENCE {confidence: 1.0}]->(e3)
815
+
816
+ // Conflict detected
817
+ CREATE (conflict:Conflict {
818
+ type: 'value_mismatch',
819
+ description: 'Code and tests show sort parameter exists, docs missing it',
820
+ severity: 'medium'
821
+ })
822
+ CREATE (e1)-[:CONFLICTS_WITH]->(e2)
823
+ CREATE (c)-[:HAS_CONFLICT]->(conflict)
824
+
825
+ // Gap detected
826
+ CREATE (gap:Gap {
827
+ type: 'undocumented',
828
+ description: 'sort parameter not documented',
829
+ severity: 'medium'
830
+ })
831
+ CREATE (c)-[:HAS_GAP]->(gap)
832
+ ```
833
+
834
+ ---
835
+
836
+ ## Operational Workflows
837
+
838
+ ### Workflow 1: Continuous Reconciliation (Automated)
839
+
840
+ ```typescript
841
+ // Runs continuously in CI/CD pipeline
842
+ class ContinuousReconciliation {
843
+ async reconcile() {
844
+ // 1. Extract truth from all sources
845
+ const codeExtract = await this.extractFromCode();
846
+ const specExtract = await this.extractFromSpec();
847
+ const docsExtract = await this.extractFromDocs();
848
+ const usageExtract = await this.extractFromUsage();
849
+ const supportExtract = await this.extractFromSupport();
850
+ const chatExtract = await this.extractFromChatbot();
851
+ const testExtract = await this.extractFromTests();
852
+
853
+ // 2. Ingest into graph
854
+ await this.ingestEvidence([
855
+ codeExtract,
856
+ specExtract,
857
+ docsExtract,
858
+ usageExtract,
859
+ supportExtract,
860
+ chatExtract,
861
+ testExtract
862
+ ]);
863
+
864
+ // 3. Detect conflicts
865
+ const conflicts = await this.detectConflicts();
866
+
867
+ // 4. Detect gaps
868
+ const gaps = await this.detectGaps();
869
+
870
+ // 5. Auto-resolve what we can
871
+ const autoResolved = await this.autoResolve(conflicts);
872
+
873
+ // 6. Escalate what we can't
874
+ const escalated = conflicts.filter(c => !autoResolved.includes(c));
875
+ await this.createGitHubIssues(escalated);
876
+
877
+ // 7. Generate reports
878
+ await this.generateReport({
879
+ conflicts: { total: conflicts.length, resolved: autoResolved.length, escalated: escalated.length },
880
+ gaps: { total: gaps.length, byType: groupBy(gaps, 'type') },
881
+ confidence: this.calculateOverallConfidence()
882
+ });
883
+
884
+ // 8. Update outputs (docs, tests)
885
+ if (autoResolved.length > 0) {
886
+ await this.regenerateAffectedOutputs(autoResolved);
887
+ }
888
+ }
889
+
890
+ async extractFromCode(): Promise<SourceEvidence[]> {
891
+ // Use AST parsing to extract command structure
892
+ const ast = await parseTypeScript('src/commands/**/*.ts');
893
+
894
+ const commands = ast.findAll('Command')
895
+ .map(node => ({
896
+ source: 'code',
897
+ type: 'command',
898
+ value: {
899
+ name: node.name,
900
+ parameters: node.options.map(o => ({
901
+ name: o.name,
902
+ type: inferType(o.type),
903
+ required: o.required,
904
+ default: o.default
905
+ }))
906
+ },
907
+ location: `${node.file}:${node.line}`,
908
+ timestamp: node.lastModified,
909
+ metadata: {
910
+ commit: node.commit,
911
+ author: node.author
912
+ }
913
+ }));
914
+
915
+ return commands;
916
+ }
917
+
918
+ async extractFromUsage(): Promise<SourceEvidence[]> {
919
+ // Query analytics database for command usage
920
+ const usageData = await analytics.query(`
921
+ SELECT
922
+ command,
923
+ COUNT(*) as frequency,
924
+ AVG(success::int) as success_rate,
925
+ MODE() WITHIN GROUP (ORDER BY next_command) as common_next_command
926
+ FROM command_logs
927
+ WHERE timestamp > NOW() - INTERVAL '30 days'
928
+ GROUP BY command
929
+ HAVING COUNT(*) > 10
930
+ `);
931
+
932
+ return usageData.map(row => ({
933
+ source: 'usage',
934
+ type: 'command_usage',
935
+ value: {
936
+ command: row.command,
937
+ frequency: row.frequency,
938
+ successRate: row.success_rate,
939
+ commonNextCommand: row.common_next_command
940
+ },
941
+ timestamp: new Date(),
942
+ confidence: row.frequency > 100 ? 0.9 : 0.7
943
+ }));
944
+ }
945
+
946
+ async extractFromSupport(): Promise<SourceEvidence[]> {
947
+ // Analyze support tickets with NLP
948
+ const tickets = await supportSystem.getRecentTickets(30);
949
+
950
+ const classified = await Promise.all(
951
+ tickets.map(async ticket => {
952
+ const analysis = await this.llm.analyze(`
953
+ Classify this support ticket:
954
+
955
+ Title: ${ticket.title}
956
+ Description: ${ticket.description}
957
+ Resolution: ${ticket.resolution}
958
+
959
+ Extract:
960
+ 1. What feature/command is this about?
961
+ 2. What was the user's confusion?
962
+ 3. Is this a bug, doc issue, or UX issue?
963
+ 4. What's the root cause?
964
+ `);
965
+
966
+ return {
967
+ source: 'support',
968
+ type: analysis.issueType,
969
+ value: {
970
+ feature: analysis.feature,
971
+ confusion: analysis.confusion,
972
+ rootCause: analysis.rootCause
973
+ },
974
+ location: ticket.id,
975
+ timestamp: ticket.created_at,
976
+ confidence: 0.6 // Human verification recommended
977
+ };
978
+ })
979
+ );
980
+
981
+ return classified;
982
+ }
983
+
984
+ async detectConflicts(): Promise<Conflict[]> {
985
+ // Query graph for facts with multiple conflicting sources
986
+ const query = `
987
+ MATCH (f:Fact)-[:HAS_EVIDENCE]->(e1:Evidence)
988
+ MATCH (f)-[:HAS_EVIDENCE]->(e2:Evidence)
989
+ WHERE e1.value <> e2.value
990
+ AND e1.source <> e2.source
991
+ AND NOT exists((e1)-[:CONFLICTS_WITH]->(e2))
992
+ RETURN f, e1, e2
993
+ `;
994
+
995
+ const results = await this.graph.query(query);
996
+
997
+ return results.map(({ f, e1, e2 }) => ({
998
+ id: generateId(),
999
+ type: this.classifyConflictType(e1, e2),
1000
+ severity: this.assessSeverity(e1, e2, f),
1001
+ sources: [e1, e2],
1002
+ description: this.describeConflict(f, e1, e2),
1003
+ status: 'detected'
1004
+ }));
1005
+ }
1006
+ }
1007
+ ```
1008
+
1009
+ ### Workflow 2: Human-Driven Resolution
1010
+
1011
+ ```typescript
1012
+ // Interactive dashboard for resolving conflicts and gaps
1013
+ class ReconciliationDashboard {
1014
+ async showDashboard() {
1015
+ const conflicts = await this.graph.getUnresolvedConflicts();
1016
+ const gaps = await this.graph.getUnresolvedGaps();
1017
+
1018
+ console.log(`
1019
+ ┌───────────────────────────────────────────────────────────┐
1020
+ │ Kenogami Reconciliation Dashboard │
1021
+ └───────────────────────────────────────────────────────────┘
1022
+
1023
+ 📊 Status:
1024
+ ├─ Overall Confidence: ${this.calculateConfidence()}%
1025
+ ├─ Unresolved Conflicts: ${conflicts.length}
1026
+ ├─ Unresolved Gaps: ${gaps.length}
1027
+ └─ Last Sync: ${this.lastSyncTime}
1028
+
1029
+ 🚨 Critical Conflicts (${conflicts.filter(c => c.severity === 'critical').length}):
1030
+ ${this.renderConflicts(conflicts.filter(c => c.severity === 'critical'))}
1031
+
1032
+ 📝 High-Priority Gaps (${gaps.filter(g => g.severity === 'high').length}):
1033
+ ${this.renderGaps(gaps.filter(g => g.severity === 'high'))}
1034
+
1035
+ 🔍 Actions:
1036
+ 1. Review conflicts
1037
+ 2. Review gaps
1038
+ 3. Run reconciliation
1039
+ 4. Generate report
1040
+ 5. Update sources
1041
+
1042
+ Choice:
1043
+ `);
1044
+ }
1045
+
1046
+ async reviewConflict(conflict: Conflict) {
1047
+ console.log(`
1048
+ ┌───────────────────────────────────────────────────────────┐
1049
+ │ Conflict: ${conflict.description} │
1050
+ │ Severity: ${conflict.severity} │
1051
+ └───────────────────────────────────────────────────────────┘
1052
+
1053
+ Source 1: ${conflict.sources[0].source}
1054
+ Location: ${conflict.sources[0].location}
1055
+ Value: ${JSON.stringify(conflict.sources[0].value, null, 2)}
1056
+ Confidence: ${conflict.sources[0].confidence}
1057
+ Last Updated: ${conflict.sources[0].timestamp}
1058
+
1059
+ Source 2: ${conflict.sources[1].source}
1060
+ Location: ${conflict.sources[1].location}
1061
+ Value: ${JSON.stringify(conflict.sources[1].value, null, 2)}
1062
+ Confidence: ${conflict.sources[1].confidence}
1063
+ Last Updated: ${conflict.sources[1].timestamp}
1064
+
1065
+ 🤖 AI Recommendation: ${await this.getAIRecommendation(conflict)}
1066
+
1067
+ 🔧 Resolution Options:
1068
+ 1. Use Source 1 (${conflict.sources[0].source})
1069
+ 2. Use Source 2 (${conflict.sources[1].source})
1070
+ 3. Merge both
1071
+ 4. Create new canonical value
1072
+ 5. Escalate to product team
1073
+ 6. Run tests to verify
1074
+
1075
+ Choice:
1076
+ `);
1077
+
1078
+ const choice = await this.prompt();
1079
+ return this.applyResolution(conflict, choice);
1080
+ }
1081
+ }
1082
+ ```
1083
+
1084
+ ### Workflow 3: Feedback Loop from Outputs
1085
+
1086
+ ```typescript
1087
+ // Outputs (docs, tests) feed back findings to the graph
1088
+ class OutputFeedbackLoop {
1089
+ async processTestResults(results: TestResult[]) {
1090
+ for (const result of results) {
1091
+ if (!result.passed) {
1092
+ // Test failed - reality doesn't match expectation
1093
+ await this.analyzeTestFailure(result);
1094
+ } else if (result.actualOutput !== result.expectedOutput) {
1095
+ // Test passed but output different - possible drift
1096
+ await this.flagPotentialDrift(result);
1097
+ }
1098
+ }
1099
+ }
1100
+
1101
+ async analyzeTestFailure(result: TestResult) {
1102
+ // Use AI to determine what's wrong
1103
+ const analysis = await this.llm.analyze(`
1104
+ Test failed:
1105
+
1106
+ Test: ${result.testName}
1107
+ Command: ${result.command}
1108
+ Expected: ${result.expectedOutput}
1109
+ Actual: ${result.actualOutput}
1110
+ Error: ${result.error}
1111
+
1112
+ Analyze:
1113
+ 1. Is the test wrong (expected output incorrect)?
1114
+ 2. Is the code wrong (bug in implementation)?
1115
+ 3. Is the documentation wrong (describes non-existent behavior)?
1116
+ 4. Is the API spec wrong?
1117
+
1118
+ Provide recommendation.
1119
+ `);
1120
+
1121
+ if (analysis.rootCause === 'documentation_wrong') {
1122
+ // Update graph with correct information from test
1123
+ await this.updateGraph({
1124
+ source: 'test_results',
1125
+ value: result.actualOutput,
1126
+ confidence: 0.9,
1127
+ evidence: result,
1128
+ suggestedAction: 'UPDATE_DOCS'
1129
+ });
1130
+
1131
+ // Create conflict between docs and reality
1132
+ await this.createConflict({
1133
+ type: 'docs_vs_reality',
1134
+ sources: ['documentation', 'test_results'],
1135
+ recommendation: 'Update documentation to match actual behavior'
1136
+ });
1137
+ } else if (analysis.rootCause === 'code_bug') {
1138
+ // Create GitHub issue for bug
1139
+ await this.createGitHubIssue({
1140
+ title: `Bug: ${result.testName} fails`,
1141
+ labels: ['bug', 'test-failure'],
1142
+ body: `Test expects: ${result.expectedOutput}\nActual: ${result.actualOutput}\n\n${analysis.explanation}`
1143
+ });
1144
+ }
1145
+ }
1146
+
1147
+ async processUserFeedback(feedback: UserFeedback) {
1148
+ // User reports: "The docs say X but when I tried it, Y happened"
1149
+ await this.createConflict({
1150
+ type: 'user_reported_mismatch',
1151
+ sources: ['documentation', 'user_feedback'],
1152
+ severity: 'medium',
1153
+ description: feedback.description,
1154
+ evidence: feedback
1155
+ });
1156
+
1157
+ // Track this for analysis
1158
+ await this.graph.createNode('UserReport', {
1159
+ source: 'user_feedback',
1160
+ type: feedback.type,
1161
+ description: feedback.description,
1162
+ timestamp: new Date(),
1163
+ user: feedback.userId
1164
+ });
1165
+ }
1166
+ }
1167
+ ```
1168
+
1169
+ ---
1170
+
1171
+ ## Metrics & Monitoring
1172
+
1173
+ ### Health Metrics
1174
+
1175
+ ```typescript
1176
+ interface SystemHealth {
1177
+ // Confidence metrics
1178
+ overallConfidence: number; // 0-100%
1179
+ confidenceBySource: {
1180
+ code: number;
1181
+ spec: number;
1182
+ documentation: number;
1183
+ tests: number;
1184
+ usage: number;
1185
+ };
1186
+
1187
+ // Conflict metrics
1188
+ totalConflicts: number;
1189
+ conflictsBySeverity: {
1190
+ critical: number;
1191
+ high: number;
1192
+ medium: number;
1193
+ low: number;
1194
+ };
1195
+ conflictResolutionRate: number; // % resolved
1196
+ averageTimeToResolve: number; // hours
1197
+
1198
+ // Gap metrics
1199
+ totalGaps: number;
1200
+ gapsByType: {
1201
+ undocumented: number;
1202
+ unimplemented: number;
1203
+ undertested: number;
1204
+ faq_missing: number;
1205
+ };
1206
+ gapClosureRate: number; // % closed per week
1207
+
1208
+ // Freshness metrics
1209
+ averageSourceAge: {
1210
+ code: number; // days since last update
1211
+ documentation: number;
1212
+ tests: number;
1213
+ };
1214
+ staleSourcesCount: number; // sources older than threshold
1215
+
1216
+ // Coverage metrics
1217
+ documentationCoverage: number; // % of code features documented
1218
+ testCoverage: number; // % of documented features tested
1219
+ usageAlignment: number; // % of documented features actually used
1220
+ }
1221
+
1222
+ // Alert thresholds
1223
+ const ALERTS = {
1224
+ overallConfidence: { critical: 60, warning: 75 },
1225
+ criticalConflicts: { critical: 5, warning: 2 },
1226
+ documentationCoverage: { critical: 70, warning: 85 },
1227
+ staleDocumentation: { critical: 90, warning: 60 } // days
1228
+ };
1229
+ ```
1230
+
1231
+ ### Dashboard Visualization
1232
+
1233
+ ```
1234
+ ┌─────────────────────────────────────────────────────────────┐
1235
+ │ Kenogami System Health Dashboard │
1236
+ └─────────────────────────────────────────────────────────────┘
1237
+
1238
+ 📊 Overall Health: 87% ████████░░ GOOD
1239
+
1240
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1241
+
1242
+ 🎯 Confidence Scores:
1243
+
1244
+ Code: 95% █████████░ Excellent
1245
+ Spec: 88% ████████░░ Good
1246
+ Documentation: 72% ███████░░░ Needs Attention ⚠️
1247
+ Tests: 91% █████████░ Good
1248
+ Usage Data: 85% ████████░░ Good
1249
+
1250
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1251
+
1252
+ 🚨 Conflicts:
1253
+
1254
+ Total: 23
1255
+ Critical: 2 🔴
1256
+ High: 5 🟠
1257
+ Medium: 12 🟡
1258
+ Low: 4 🟢
1259
+
1260
+ Resolution Rate: 78% (18/23 resolved this week)
1261
+ Avg Time to Resolve: 4.2 hours
1262
+
1263
+ Top Conflicts:
1264
+ 1. API spec vs implementation (authentication flow)
1265
+ 2. Documentation inconsistency (default output format)
1266
+
1267
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1268
+
1269
+ 📝 Gaps:
1270
+
1271
+ Total: 47
1272
+ Critical: 3 🔴 Fix immediately
1273
+ High: 12 🟠 Plan this sprint
1274
+ Medium: 21 🟡 Backlog
1275
+ Low: 11 🟢 Nice to have
1276
+
1277
+ Top Gaps:
1278
+ 1. Workflow: Create → Schedule → Send (45 users, 0 docs)
1279
+ 2. Parameter --batch not documented (12 support tickets)
1280
+ 3. FAQ: "How do I authenticate?" (23 tickets)
1281
+
1282
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1283
+
1284
+ 📈 Coverage:
1285
+
1286
+ Documentation: 82% ████████░░ (112/136 commands)
1287
+ Testing: 94% █████████░ (128/136 commands)
1288
+ Usage: 76% ███████░░░ (104/136 commands used)
1289
+
1290
+ Undocumented but used: 8 features ⚠️
1291
+ Documented but unused: 24 features ℹ️
1292
+
1293
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1294
+
1295
+ ⏰ Freshness:
1296
+
1297
+ Code: 2 days ago ✅
1298
+ Documentation: 14 days ago ⚠️
1299
+ Tests: 1 day ago ✅
1300
+
1301
+ Stale sources: 3 (docs older than 30 days)
1302
+
1303
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1304
+
1305
+ 🎬 Actions:
1306
+
1307
+ ⚡ Immediate:
1308
+ • Resolve 2 critical conflicts
1309
+ • Document 3 critical gaps
1310
+
1311
+ 📅 This Week:
1312
+ • Update stale documentation (3 articles)
1313
+ • Close 5 high-priority gaps
1314
+ • Review 12 medium conflicts
1315
+
1316
+ 🔮 Trends:
1317
+ • Confidence improving (+5% this week) ↗️
1318
+ • Conflicts decreasing (-3 resolved) ↘️
1319
+ • Gaps increasing (+7 detected) ⚠️
1320
+ ```
1321
+
1322
+ ---
1323
+
1324
+ ## Summary: Philosophical Shift
1325
+
1326
+ ### Old Mental Model: Single Source of Truth
1327
+
1328
+ ```
1329
+ "The code is the truth" ❌
1330
+ "The docs are the truth" ❌
1331
+ "The spec is the truth" ❌
1332
+ ```
1333
+
1334
+ **Problem:** No single source captures the full truth. Each source has partial truth.
1335
+
1336
+ ### New Mental Model: Distributed Truth with Reconciliation
1337
+
1338
+ ```
1339
+ "Truth is distributed across multiple authoritative sources,
1340
+ each with different authority for different questions.
1341
+ The knowledge graph reconciles these truths,
1342
+ detects conflicts and gaps,
1343
+ and synthesizes a coherent understanding
1344
+ that serves all stakeholders."
1345
+ ```
1346
+
1347
+ **Reality:**
1348
+ - **Code** tells us what IS implemented
1349
+ - **Spec** tells us what SHOULD be implemented
1350
+ - **Documentation** tells us what we INTEND users to understand
1351
+ - **Usage** tells us what users ACTUALLY do
1352
+ - **Support** tells us where users STRUGGLE
1353
+ - **Tests** tell us what we've VERIFIED
1354
+ - **Chatbot** tells us how users LEARN
1355
+
1356
+ **Kenogami's Role:**
1357
+ Not to pick one truth, but to:
1358
+ 1. **Capture** all truths with provenance
1359
+ 2. **Detect** when truths conflict
1360
+ 3. **Analyze** why conflicts exist
1361
+ 4. **Resolve** conflicts using appropriate strategies
1362
+ 5. **Identify** gaps where truth is missing
1363
+ 6. **Synthesize** coherent output for each audience
1364
+ 7. **Evolve** as all sources evolve
1365
+
1366
+ **Key Insight:**
1367
+ The knowledge graph is not the source of truth—it's the **reconciliation layer** that makes sense of distributed, evolving, sometimes-conflicting truths, maintaining coherence and surfacing problems for human decision-making.
1368
+
1369
+ This is fundamentally a **distributed systems problem** applied to knowledge management.