@plures/praxis 1.2.13 → 1.3.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.
- package/README.md +44 -0
- package/dist/browser/chunk-MJK3IYTJ.js +384 -0
- package/dist/browser/{chunk-K377RW4V.js → chunk-N63K4KWS.js} +1 -1
- package/dist/browser/{engine-YJZV4SLD.js → engine-YIEGSX7U.js} +1 -1
- package/dist/browser/index.d.ts +104 -2
- package/dist/browser/index.js +188 -7
- package/dist/browser/integrations/svelte.d.ts +2 -2
- package/dist/browser/integrations/svelte.js +2 -2
- package/dist/browser/{reactive-engine.svelte-9aS0kTa8.d.ts → reactive-engine.svelte-DjynI82A.d.ts} +139 -5
- package/dist/node/{chunk-PRPQO6R5.js → chunk-5JQJZADT.js} +1 -1
- package/dist/node/chunk-KMJWAFZV.js +389 -0
- package/dist/node/{chunk-5RH7UAQC.js → chunk-PTH6MD6P.js} +1 -0
- package/dist/node/cli/index.cjs +1553 -839
- package/dist/node/cli/index.js +39 -2
- package/dist/node/cloud/index.d.cts +1 -1
- package/dist/node/cloud/index.d.ts +1 -1
- package/dist/node/components/index.d.cts +2 -2
- package/dist/node/components/index.d.ts +2 -2
- package/dist/node/conversations-KQBXTP3N.js +596 -0
- package/dist/node/{engine-2DQBKBJC.js → engine-FEN5IYZ5.js} +1 -1
- package/dist/node/index.cjs +911 -43
- package/dist/node/index.d.cts +574 -7
- package/dist/node/index.d.ts +574 -7
- package/dist/node/index.js +672 -26
- package/dist/node/integrations/svelte.cjs +190 -3
- package/dist/node/integrations/svelte.d.cts +3 -3
- package/dist/node/integrations/svelte.d.ts +3 -3
- package/dist/node/integrations/svelte.js +2 -2
- package/dist/node/{protocol-Qek7ebBl.d.ts → protocol-DcyGMmWY.d.cts} +8 -1
- package/dist/node/{protocol-Qek7ebBl.d.cts → protocol-DcyGMmWY.d.ts} +8 -1
- package/dist/node/{reactive-engine.svelte-CRNqHlbv.d.ts → reactive-engine.svelte-Cg0Yc2Hs.d.cts} +145 -6
- package/dist/node/{reactive-engine.svelte-BFIZfawz.d.cts → reactive-engine.svelte-DekxqFu0.d.ts} +145 -6
- package/dist/node/{terminal-adapter-B-UK_Vdz.d.ts → terminal-adapter-CvIvgTo4.d.ts} +1 -1
- package/dist/node/{terminal-adapter-BQSIF5bf.d.cts → terminal-adapter-Db-snPJ3.d.cts} +1 -1
- package/dist/node/{validate-CNHUULQE.js → validate-EN3M4FUR.js} +1 -1
- package/dist/node/{verify-KLJRXVJS.js → verify-7VZRP2WS.js} +2 -2
- package/docs/BOT_UPDATE_POLICY.md +125 -0
- package/docs/DOGFOODING_CHECKLIST.md +254 -0
- package/docs/DOGFOODING_INDEX.md +169 -0
- package/docs/DOGFOODING_QUICK_START.md +140 -0
- package/docs/KNO_ENG_EXTRACTION_PLAN.md +577 -0
- package/docs/PLURES_TOOLS_INVENTORY.md +170 -0
- package/docs/README.md +12 -0
- package/docs/TESTING_BOT_WORKFLOWS.md +154 -0
- package/docs/conversations/INTEGRATION_POINTS.md +719 -0
- package/docs/conversations/README.md +168 -0
- package/docs/core/extending-praxis-core.md +604 -0
- package/docs/core/praxis-core-api.md +385 -0
- package/docs/decision-ledger/contract-index.json +2 -2
- package/docs/decision-ledger/decisions/2026-02-01-monorepo-organization.md +130 -0
- package/docs/examples/DOGFOODING_WORKFLOW_EXAMPLE.md +295 -0
- package/docs/examples/README.md +41 -0
- package/docs/workflows/pr-overlap-guard.md +50 -0
- package/package.json +8 -3
- package/src/__tests__/chronicle.test.ts +512 -0
- package/src/__tests__/conversations.test.ts +312 -0
- package/src/__tests__/edge-cases.test.ts +1 -1
- package/src/__tests__/engine-dx.test.ts +355 -0
- package/src/__tests__/engine-v2.test.ts +532 -0
- package/src/cli/commands/conversations.ts +252 -0
- package/src/cli/index.ts +73 -0
- package/src/conversations/README.md +230 -0
- package/src/conversations/candidate.schema.json +123 -0
- package/src/conversations/candidates.ts +114 -0
- package/src/conversations/capture.ts +56 -0
- package/src/conversations/classify.ts +110 -0
- package/src/conversations/conversation.schema.json +106 -0
- package/src/conversations/emitters/fs.ts +65 -0
- package/src/conversations/emitters/github.ts +115 -0
- package/src/conversations/gate.ts +102 -0
- package/src/conversations/index.ts +28 -0
- package/src/conversations/normalize.ts +51 -0
- package/src/conversations/redact.ts +57 -0
- package/src/conversations/types.ts +96 -0
- package/src/core/chronicle/chronicle.ts +227 -0
- package/src/core/chronicle/context.ts +80 -0
- package/src/core/chronicle/index.ts +53 -0
- package/src/core/chronicle/mcp.ts +135 -0
- package/src/core/chronicle/types.ts +61 -0
- package/src/core/completeness.ts +274 -0
- package/src/core/engine.ts +143 -3
- package/src/core/pluresdb/index.ts +22 -0
- package/src/core/pluresdb/store.ts +171 -8
- package/src/core/protocol.ts +7 -0
- package/src/core/rule-result.ts +130 -0
- package/src/core/rules.ts +24 -5
- package/src/core/ui-rules.ts +340 -0
- package/src/dsl/index.ts +6 -0
- package/src/index.ts +45 -0
- package/src/integrations/pluresdb.ts +22 -0
- package/src/vite/completeness-plugin.ts +72 -0
- package/dist/browser/chunk-VOMLVI6V.js +0 -197
- package/dist/node/chunk-VOMLVI6V.js +0 -197
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
# Integration Points: kno-eng → Praxis Conversations
|
|
2
|
+
|
|
3
|
+
**Document**: Integration Architecture
|
|
4
|
+
**Date**: 2026-02-01
|
|
5
|
+
**Status**: Planning
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This document defines the specific integration points for refactoring kno-eng into the Praxis framework as the `conversations` module, ensuring seamless integration with existing Praxis infrastructure.
|
|
10
|
+
|
|
11
|
+
## Integration Architecture
|
|
12
|
+
|
|
13
|
+
### High-Level Integration Map
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
17
|
+
│ Praxis Framework │
|
|
18
|
+
├─────────────────────────────────────────────────────────────┤
|
|
19
|
+
│ │
|
|
20
|
+
│ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │
|
|
21
|
+
│ │ Schema │ │ Logic │ │ Component │ │
|
|
22
|
+
│ │ System │ │ Engine │ │ Generator │ │
|
|
23
|
+
│ └─────┬──────┘ └─────┬──────┘ └───────┬──────┘ │
|
|
24
|
+
│ │ │ │ │
|
|
25
|
+
│ │ │ │ │
|
|
26
|
+
│ ┌─────▼───────────────▼──────────────────▼──────┐ │
|
|
27
|
+
│ │ Conversations Module (kno-eng) │ │
|
|
28
|
+
│ ├───────────────────────────────────────────────┤ │
|
|
29
|
+
│ │ Capture │ Knowledge │ Rules │ Sync │ │
|
|
30
|
+
│ └─────┬─────────────┬────────────┬───────┬──────┘ │
|
|
31
|
+
│ │ │ │ │ │
|
|
32
|
+
├────────┼─────────────┼────────────┼───────┼─────────────────┤
|
|
33
|
+
│ │ │ │ │ │
|
|
34
|
+
│ ┌─────▼──────┐ ┌────▼─────┐ ┌───▼────┐ ┌▼────────┐ │
|
|
35
|
+
│ │ PluresDB │ │ Unum │ │ Canvas │ │ Cloud │ │
|
|
36
|
+
│ └────────────┘ └──────────┘ └────────┘ └─────────┘ │
|
|
37
|
+
└─────────────────────────────────────────────────────────────┘
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 1. Data Layer Integration (PluresDB)
|
|
41
|
+
|
|
42
|
+
### 1.1 Schema Definition
|
|
43
|
+
|
|
44
|
+
**Integration Point**: Praxis Schema System → PluresDB Collections
|
|
45
|
+
|
|
46
|
+
**Location**: `/src/conversations/schema/knowledge.schema.ts`
|
|
47
|
+
|
|
48
|
+
**Purpose**: Define data models for knowledge entries, threads, and relationships using Praxis schema format.
|
|
49
|
+
|
|
50
|
+
**Implementation**:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// /src/conversations/schema/knowledge.schema.ts
|
|
54
|
+
import { definePraxisSchema } from '@plures/praxis/schema';
|
|
55
|
+
|
|
56
|
+
export const conversationsSchema = definePraxisSchema({
|
|
57
|
+
version: '1.0.0',
|
|
58
|
+
name: 'praxis-conversations',
|
|
59
|
+
|
|
60
|
+
models: [
|
|
61
|
+
{
|
|
62
|
+
name: 'KnowledgeEntry',
|
|
63
|
+
description: 'Individual knowledge capture entry',
|
|
64
|
+
fields: [
|
|
65
|
+
{ name: 'id', type: 'uuid', primary: true },
|
|
66
|
+
{ name: 'type', type: 'string', required: true },
|
|
67
|
+
{ name: 'title', type: 'string', required: true },
|
|
68
|
+
{ name: 'content', type: 'string', required: true },
|
|
69
|
+
{ name: 'tags', type: { array: 'string' }, default: [] },
|
|
70
|
+
|
|
71
|
+
// Code context
|
|
72
|
+
{ name: 'filePath', type: 'string', optional: true },
|
|
73
|
+
{ name: 'lineNumber', type: 'number', optional: true },
|
|
74
|
+
{ name: 'commitSha', type: 'string', optional: true },
|
|
75
|
+
|
|
76
|
+
// Metadata
|
|
77
|
+
{ name: 'createdBy', type: 'string', required: true },
|
|
78
|
+
{ name: 'createdAt', type: 'datetime', default: 'now' },
|
|
79
|
+
{ name: 'updatedAt', type: 'datetime', default: 'now' },
|
|
80
|
+
|
|
81
|
+
// Relationships
|
|
82
|
+
{ name: 'relatedTo', type: { array: 'string' }, default: [] },
|
|
83
|
+
{ name: 'threadId', type: 'string', optional: true },
|
|
84
|
+
],
|
|
85
|
+
indexes: [
|
|
86
|
+
{ fields: ['createdBy'], type: 'standard' },
|
|
87
|
+
{ fields: ['createdAt'], sort: 'desc' },
|
|
88
|
+
{ fields: ['tags'], type: 'multikey' },
|
|
89
|
+
{ fields: ['filePath'], type: 'standard' },
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
name: 'ConversationThread',
|
|
95
|
+
description: 'Threaded discussions around knowledge',
|
|
96
|
+
fields: [
|
|
97
|
+
{ name: 'id', type: 'uuid', primary: true },
|
|
98
|
+
{ name: 'topic', type: 'string', required: true },
|
|
99
|
+
{ name: 'participants', type: { array: 'string' }, default: [] },
|
|
100
|
+
{ name: 'entries', type: { array: 'string' }, default: [] },
|
|
101
|
+
{ name: 'status', type: 'string', default: 'active' },
|
|
102
|
+
{ name: 'createdAt', type: 'datetime', default: 'now' },
|
|
103
|
+
{ name: 'updatedAt', type: 'datetime', default: 'now' },
|
|
104
|
+
],
|
|
105
|
+
indexes: [
|
|
106
|
+
{ fields: ['status', 'updatedAt'], sort: 'desc' },
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
name: 'KnowledgeLink',
|
|
112
|
+
description: 'Relationships between knowledge entries',
|
|
113
|
+
fields: [
|
|
114
|
+
{ name: 'id', type: 'uuid', primary: true },
|
|
115
|
+
{ name: 'fromId', type: 'string', required: true },
|
|
116
|
+
{ name: 'toId', type: 'string', required: true },
|
|
117
|
+
{ name: 'type', type: 'string', required: true },
|
|
118
|
+
{ name: 'strength', type: 'number', default: 1.0 },
|
|
119
|
+
],
|
|
120
|
+
indexes: [
|
|
121
|
+
{ fields: ['fromId'], type: 'standard' },
|
|
122
|
+
{ fields: ['toId'], type: 'standard' },
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Integration Benefits**:
|
|
130
|
+
- Leverages PluresDB's local-first storage
|
|
131
|
+
- Automatic CRDT conflict resolution
|
|
132
|
+
- Reactive queries for UI updates
|
|
133
|
+
- Built-in indexing for fast search
|
|
134
|
+
|
|
135
|
+
### 1.2 Database Initialization
|
|
136
|
+
|
|
137
|
+
**Integration Point**: PluresDB Adapter → Conversations Engine
|
|
138
|
+
|
|
139
|
+
**Location**: `/src/conversations/core/db.ts`
|
|
140
|
+
|
|
141
|
+
**Implementation**:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// /src/conversations/core/db.ts
|
|
145
|
+
import { createPraxisLocalFirst } from '@plures/praxis';
|
|
146
|
+
import { conversationsSchema } from '../schema/knowledge.schema';
|
|
147
|
+
|
|
148
|
+
export async function createKnowledgeDB(options = {}) {
|
|
149
|
+
const db = await createPraxisLocalFirst({
|
|
150
|
+
mode: options.mode || 'auto',
|
|
151
|
+
dbName: options.dbName || 'praxis-knowledge',
|
|
152
|
+
schema: conversationsSchema,
|
|
153
|
+
sync: options.sync || { enabled: false },
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return db;
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## 2. Logic Engine Integration
|
|
161
|
+
|
|
162
|
+
### 2.1 Facts and Events
|
|
163
|
+
|
|
164
|
+
**Integration Point**: Praxis Logic Engine → Knowledge Processing
|
|
165
|
+
|
|
166
|
+
**Location**: `/src/conversations/core/facts.ts`
|
|
167
|
+
|
|
168
|
+
**Implementation**:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// /src/conversations/core/facts.ts
|
|
172
|
+
import { defineFact, defineEvent } from '@plures/praxis';
|
|
173
|
+
|
|
174
|
+
// Facts
|
|
175
|
+
export const KnowledgeCaptured = defineFact<'KnowledgeCaptured', {
|
|
176
|
+
entry: KnowledgeEntry;
|
|
177
|
+
}>('KnowledgeCaptured');
|
|
178
|
+
|
|
179
|
+
export const EntryTagged = defineFact<'EntryTagged', {
|
|
180
|
+
entryId: string;
|
|
181
|
+
tags: string[];
|
|
182
|
+
}>('EntryTagged');
|
|
183
|
+
|
|
184
|
+
export const EntriesLinked = defineFact<'EntriesLinked', {
|
|
185
|
+
fromId: string;
|
|
186
|
+
toId: string;
|
|
187
|
+
type: string;
|
|
188
|
+
strength: number;
|
|
189
|
+
}>('EntriesLinked');
|
|
190
|
+
|
|
191
|
+
// Events
|
|
192
|
+
export const CaptureKnowledge = defineEvent<'CAPTURE_KNOWLEDGE', {
|
|
193
|
+
type: string;
|
|
194
|
+
title: string;
|
|
195
|
+
content: string;
|
|
196
|
+
context?: CodeContext;
|
|
197
|
+
}>('CAPTURE_KNOWLEDGE');
|
|
198
|
+
|
|
199
|
+
export const SearchKnowledge = defineEvent<'SEARCH_KNOWLEDGE', {
|
|
200
|
+
query: string;
|
|
201
|
+
filters?: SearchFilters;
|
|
202
|
+
}>('SEARCH_KNOWLEDGE');
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 2.2 Processing Rules
|
|
206
|
+
|
|
207
|
+
**Integration Point**: Praxis Rules → Auto-tagging and Linking
|
|
208
|
+
|
|
209
|
+
**Location**: `/src/conversations/rules/`
|
|
210
|
+
|
|
211
|
+
**Implementation**:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// /src/conversations/rules/auto-tag.ts
|
|
215
|
+
import { defineRule } from '@plures/praxis';
|
|
216
|
+
import { KnowledgeCaptured, EntryTagged } from '../core/facts';
|
|
217
|
+
|
|
218
|
+
export const autoTagRule = defineRule({
|
|
219
|
+
id: 'conversations.auto-tag',
|
|
220
|
+
description: 'Automatically extract tags from knowledge content',
|
|
221
|
+
impl: (state, events) => {
|
|
222
|
+
const captured = events.find(KnowledgeCaptured.is);
|
|
223
|
+
if (!captured) return [];
|
|
224
|
+
|
|
225
|
+
const entry = captured.payload.entry;
|
|
226
|
+
const extractedTags = extractTags(entry.content, entry.title);
|
|
227
|
+
|
|
228
|
+
return [
|
|
229
|
+
EntryTagged.create({
|
|
230
|
+
entryId: entry.id,
|
|
231
|
+
tags: extractedTags,
|
|
232
|
+
})
|
|
233
|
+
];
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// /src/conversations/rules/smart-link.ts
|
|
238
|
+
import { defineRule } from '@plures/praxis';
|
|
239
|
+
import { KnowledgeCaptured, EntriesLinked } from '../core/facts';
|
|
240
|
+
|
|
241
|
+
export const smartLinkRule = defineRule({
|
|
242
|
+
id: 'conversations.smart-link',
|
|
243
|
+
description: 'Automatically detect and link related knowledge',
|
|
244
|
+
impl: (state, events) => {
|
|
245
|
+
const captured = events.find(KnowledgeCaptured.is);
|
|
246
|
+
if (!captured) return [];
|
|
247
|
+
|
|
248
|
+
const entry = captured.payload.entry;
|
|
249
|
+
const existingEntries = state.context.knowledgeEntries || [];
|
|
250
|
+
|
|
251
|
+
// Find related entries using similarity
|
|
252
|
+
const related = findRelatedEntries(entry, existingEntries);
|
|
253
|
+
|
|
254
|
+
return related.map(({ id, score }) =>
|
|
255
|
+
EntriesLinked.create({
|
|
256
|
+
fromId: entry.id,
|
|
257
|
+
toId: id,
|
|
258
|
+
type: 'relates-to',
|
|
259
|
+
strength: score,
|
|
260
|
+
})
|
|
261
|
+
);
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 2.3 Registry Integration
|
|
267
|
+
|
|
268
|
+
**Integration Point**: Praxis Registry → Conversations Rules
|
|
269
|
+
|
|
270
|
+
**Location**: `/src/conversations/core/registry.ts`
|
|
271
|
+
|
|
272
|
+
**Implementation**:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// /src/conversations/core/registry.ts
|
|
276
|
+
import { PraxisRegistry } from '@plures/praxis';
|
|
277
|
+
import { autoTagRule } from '../rules/auto-tag';
|
|
278
|
+
import { smartLinkRule } from '../rules/smart-link';
|
|
279
|
+
|
|
280
|
+
export function createConversationsRegistry(): PraxisRegistry {
|
|
281
|
+
const registry = new PraxisRegistry();
|
|
282
|
+
|
|
283
|
+
// Register all conversation rules
|
|
284
|
+
registry.registerRule(autoTagRule);
|
|
285
|
+
registry.registerRule(smartLinkRule);
|
|
286
|
+
// ... more rules
|
|
287
|
+
|
|
288
|
+
return registry;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## 3. UI Component Integration
|
|
293
|
+
|
|
294
|
+
### 3.1 Svelte Component Generation
|
|
295
|
+
|
|
296
|
+
**Integration Point**: Praxis Component Generator → Conversations UI
|
|
297
|
+
|
|
298
|
+
**Location**: `/src/conversations/components/`
|
|
299
|
+
|
|
300
|
+
**Implementation**:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
// Generate components from schema
|
|
304
|
+
import { generateComponents } from '@plures/praxis/component';
|
|
305
|
+
import { conversationsSchema } from '../schema/knowledge.schema';
|
|
306
|
+
|
|
307
|
+
const components = generateComponents({
|
|
308
|
+
schema: conversationsSchema,
|
|
309
|
+
target: 'svelte5',
|
|
310
|
+
theme: 'praxis-default',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Generated components:
|
|
314
|
+
// - KnowledgeEntryEditor.svelte
|
|
315
|
+
// - ConversationThreadView.svelte
|
|
316
|
+
// - KnowledgeSearchBar.svelte
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 3.2 Custom Components
|
|
320
|
+
|
|
321
|
+
**Location**: `/src/conversations/components/`
|
|
322
|
+
|
|
323
|
+
**Custom Components** (not auto-generated):
|
|
324
|
+
|
|
325
|
+
```svelte
|
|
326
|
+
<!-- /src/conversations/components/QuickCapture.svelte -->
|
|
327
|
+
<script lang="ts">
|
|
328
|
+
import { createEventDispatcher } from 'svelte';
|
|
329
|
+
import type { KnowledgeCaptureEngine } from '../core/engine';
|
|
330
|
+
|
|
331
|
+
export let engine: KnowledgeCaptureEngine;
|
|
332
|
+
|
|
333
|
+
let title = '';
|
|
334
|
+
let content = '';
|
|
335
|
+
let type = 'note';
|
|
336
|
+
|
|
337
|
+
const dispatch = createEventDispatcher();
|
|
338
|
+
|
|
339
|
+
async function capture() {
|
|
340
|
+
const entry = await engine.capture({
|
|
341
|
+
type,
|
|
342
|
+
title,
|
|
343
|
+
content,
|
|
344
|
+
context: await extractCurrentContext(),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
dispatch('captured', entry);
|
|
348
|
+
// Reset form
|
|
349
|
+
title = '';
|
|
350
|
+
content = '';
|
|
351
|
+
}
|
|
352
|
+
</script>
|
|
353
|
+
|
|
354
|
+
<div class="quick-capture">
|
|
355
|
+
<select bind:value={type}>
|
|
356
|
+
<option value="note">Note</option>
|
|
357
|
+
<option value="decision">Decision</option>
|
|
358
|
+
<option value="pattern">Pattern</option>
|
|
359
|
+
<option value="bug">Bug</option>
|
|
360
|
+
</select>
|
|
361
|
+
|
|
362
|
+
<input
|
|
363
|
+
bind:value={title}
|
|
364
|
+
placeholder="Title..."
|
|
365
|
+
/>
|
|
366
|
+
|
|
367
|
+
<textarea
|
|
368
|
+
bind:value={content}
|
|
369
|
+
placeholder="Capture your thoughts..."
|
|
370
|
+
/>
|
|
371
|
+
|
|
372
|
+
<button on:click={capture}>Capture</button>
|
|
373
|
+
</div>
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## 4. CLI Integration
|
|
377
|
+
|
|
378
|
+
### 4.1 Command Registration
|
|
379
|
+
|
|
380
|
+
**Integration Point**: Praxis CLI → Knowledge Commands
|
|
381
|
+
|
|
382
|
+
**Location**: `/src/cli/commands/knowledge.ts`
|
|
383
|
+
|
|
384
|
+
**Implementation**:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
// /src/cli/commands/knowledge.ts
|
|
388
|
+
import { Command } from 'commander';
|
|
389
|
+
import { createKnowledgeDB, KnowledgeCaptureEngine } from '../../conversations';
|
|
390
|
+
|
|
391
|
+
export function registerKnowledgeCommands(program: Command) {
|
|
392
|
+
const knowledge = program
|
|
393
|
+
.command('knowledge')
|
|
394
|
+
.description('Knowledge capture and management');
|
|
395
|
+
|
|
396
|
+
knowledge
|
|
397
|
+
.command('capture <content>')
|
|
398
|
+
.option('-t, --title <title>', 'Entry title')
|
|
399
|
+
.option('--type <type>', 'Entry type (note, decision, pattern, bug)', 'note')
|
|
400
|
+
.option('--tags <tags>', 'Comma-separated tags')
|
|
401
|
+
.action(async (content, options) => {
|
|
402
|
+
const db = await createKnowledgeDB();
|
|
403
|
+
const engine = new KnowledgeCaptureEngine({ db });
|
|
404
|
+
|
|
405
|
+
const entry = await engine.capture({
|
|
406
|
+
type: options.type,
|
|
407
|
+
title: options.title || content.substring(0, 50),
|
|
408
|
+
content,
|
|
409
|
+
tags: options.tags ? options.tags.split(',') : [],
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
console.log(`Captured: ${entry.id}`);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
knowledge
|
|
416
|
+
.command('search <query>')
|
|
417
|
+
.option('--type <type>', 'Filter by type')
|
|
418
|
+
.option('--tags <tags>', 'Filter by tags')
|
|
419
|
+
.action(async (query, options) => {
|
|
420
|
+
const db = await createKnowledgeDB();
|
|
421
|
+
const engine = new KnowledgeCaptureEngine({ db });
|
|
422
|
+
|
|
423
|
+
const results = await engine.search(query, {
|
|
424
|
+
type: options.type,
|
|
425
|
+
tags: options.tags ? options.tags.split(',') : undefined,
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
console.log(`Found ${results.length} entries:`);
|
|
429
|
+
results.forEach(r => console.log(` ${r.title} (${r.type})`));
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
knowledge
|
|
433
|
+
.command('export')
|
|
434
|
+
.option('-f, --format <format>', 'Export format (json, markdown, html)', 'json')
|
|
435
|
+
.option('-o, --output <path>', 'Output path')
|
|
436
|
+
.action(async (options) => {
|
|
437
|
+
const db = await createKnowledgeDB();
|
|
438
|
+
const engine = new KnowledgeCaptureEngine({ db });
|
|
439
|
+
|
|
440
|
+
await engine.export({
|
|
441
|
+
format: options.format,
|
|
442
|
+
outputPath: options.output,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
console.log(`Exported to ${options.output}`);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 4.2 CLI Entry Point
|
|
451
|
+
|
|
452
|
+
**Integration Point**: Main CLI → Knowledge Commands
|
|
453
|
+
|
|
454
|
+
**Location**: `/src/cli/index.ts`
|
|
455
|
+
|
|
456
|
+
**Implementation**:
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
// /src/cli/index.ts
|
|
460
|
+
import { Command } from 'commander';
|
|
461
|
+
import { registerKnowledgeCommands } from './commands/knowledge';
|
|
462
|
+
|
|
463
|
+
const program = new Command();
|
|
464
|
+
|
|
465
|
+
// ... existing commands
|
|
466
|
+
|
|
467
|
+
// Register knowledge commands
|
|
468
|
+
registerKnowledgeCommands(program);
|
|
469
|
+
|
|
470
|
+
program.parse();
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## 5. Sync Integration
|
|
474
|
+
|
|
475
|
+
### 5.1 PluresDB Sync Configuration
|
|
476
|
+
|
|
477
|
+
**Integration Point**: PluresDB Sync → Praxis Cloud
|
|
478
|
+
|
|
479
|
+
**Location**: `/src/conversations/sync/adapter.ts`
|
|
480
|
+
|
|
481
|
+
**Implementation**:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// /src/conversations/sync/adapter.ts
|
|
485
|
+
import { createPluresDBAdapter } from '@plures/praxis/adapters';
|
|
486
|
+
|
|
487
|
+
export async function createConversationsSyncAdapter(db, options = {}) {
|
|
488
|
+
return createPluresDBAdapter({
|
|
489
|
+
db,
|
|
490
|
+
collections: ['KnowledgeEntry', 'ConversationThread', 'KnowledgeLink'],
|
|
491
|
+
sync: {
|
|
492
|
+
enabled: options.enabled !== false,
|
|
493
|
+
endpoint: options.endpoint || process.env.PRAXIS_CLOUD_URL,
|
|
494
|
+
authToken: options.authToken || process.env.PRAXIS_AUTH_TOKEN,
|
|
495
|
+
autoSync: options.autoSync !== false,
|
|
496
|
+
syncInterval: options.syncInterval || 5000,
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 5.2 Conflict Resolution
|
|
503
|
+
|
|
504
|
+
**Integration Point**: PluresDB CRDT → Knowledge Merging
|
|
505
|
+
|
|
506
|
+
**Implementation**:
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
// Use PluresDB's built-in CRDT resolution
|
|
510
|
+
// No custom code needed - PluresDB handles it automatically
|
|
511
|
+
|
|
512
|
+
// For custom merge logic (if needed):
|
|
513
|
+
const db = await createKnowledgeDB({
|
|
514
|
+
sync: {
|
|
515
|
+
conflictResolution: 'custom',
|
|
516
|
+
resolveConflict: (local, remote, base) => {
|
|
517
|
+
// Custom merge logic for knowledge entries
|
|
518
|
+
return {
|
|
519
|
+
...base,
|
|
520
|
+
...remote,
|
|
521
|
+
...local,
|
|
522
|
+
// Merge tags (union)
|
|
523
|
+
tags: [...new Set([...local.tags, ...remote.tags])],
|
|
524
|
+
// Merge relatedTo (union)
|
|
525
|
+
relatedTo: [...new Set([...local.relatedTo, ...remote.relatedTo])],
|
|
526
|
+
mergedAt: new Date(),
|
|
527
|
+
};
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
## 6. IDE Extension Integration
|
|
534
|
+
|
|
535
|
+
### 6.1 VS Code Extension Architecture
|
|
536
|
+
|
|
537
|
+
**Integration Point**: VS Code Extension API → Praxis Conversations Engine
|
|
538
|
+
|
|
539
|
+
**Location**: `/extensions/vscode/`
|
|
540
|
+
|
|
541
|
+
**Implementation**:
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
// /extensions/vscode/src/extension.ts
|
|
545
|
+
import * as vscode from 'vscode';
|
|
546
|
+
import { createKnowledgeDB, KnowledgeCaptureEngine } from '@plures/praxis/conversations';
|
|
547
|
+
|
|
548
|
+
let engine: KnowledgeCaptureEngine;
|
|
549
|
+
|
|
550
|
+
export async function activate(context: vscode.ExtensionContext) {
|
|
551
|
+
// Initialize Praxis knowledge database
|
|
552
|
+
const db = await createKnowledgeDB({
|
|
553
|
+
mode: 'auto',
|
|
554
|
+
dbName: 'vscode-praxis-knowledge',
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
engine = new KnowledgeCaptureEngine({ db });
|
|
558
|
+
|
|
559
|
+
// Register command: Quick Capture
|
|
560
|
+
const captureCommand = vscode.commands.registerCommand(
|
|
561
|
+
'praxis.captureKnowledge',
|
|
562
|
+
async () => {
|
|
563
|
+
const editor = vscode.window.activeTextEditor;
|
|
564
|
+
|
|
565
|
+
const title = await vscode.window.showInputBox({
|
|
566
|
+
prompt: 'Knowledge entry title',
|
|
567
|
+
placeHolder: 'Enter a title...',
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
if (!title) return;
|
|
571
|
+
|
|
572
|
+
const content = await vscode.window.showInputBox({
|
|
573
|
+
prompt: 'Content',
|
|
574
|
+
placeHolder: 'Capture your thoughts...',
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
if (!content) return;
|
|
578
|
+
|
|
579
|
+
const entry = await engine.capture({
|
|
580
|
+
type: 'note',
|
|
581
|
+
title,
|
|
582
|
+
content,
|
|
583
|
+
context: editor ? {
|
|
584
|
+
filePath: editor.document.fileName,
|
|
585
|
+
lineNumber: editor.selection.active.line + 1,
|
|
586
|
+
selectedCode: editor.document.getText(editor.selection),
|
|
587
|
+
} : undefined,
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
vscode.window.showInformationMessage(`Captured: ${entry.title}`);
|
|
591
|
+
}
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
// Register command: Search
|
|
595
|
+
const searchCommand = vscode.commands.registerCommand(
|
|
596
|
+
'praxis.searchKnowledge',
|
|
597
|
+
async () => {
|
|
598
|
+
const query = await vscode.window.showInputBox({
|
|
599
|
+
prompt: 'Search knowledge',
|
|
600
|
+
placeHolder: 'Enter search query...',
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
if (!query) return;
|
|
604
|
+
|
|
605
|
+
const results = await engine.search(query);
|
|
606
|
+
|
|
607
|
+
// Show results in Quick Pick
|
|
608
|
+
const selected = await vscode.window.showQuickPick(
|
|
609
|
+
results.map(r => ({
|
|
610
|
+
label: r.title,
|
|
611
|
+
description: r.type,
|
|
612
|
+
detail: r.content.substring(0, 100),
|
|
613
|
+
entry: r,
|
|
614
|
+
})),
|
|
615
|
+
{ placeHolder: `Found ${results.length} entries` }
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
if (selected) {
|
|
619
|
+
// Open entry editor or navigate to code location
|
|
620
|
+
if (selected.entry.context?.filePath) {
|
|
621
|
+
const doc = await vscode.workspace.openTextDocument(
|
|
622
|
+
selected.entry.context.filePath
|
|
623
|
+
);
|
|
624
|
+
const editor = await vscode.window.showTextDocument(doc);
|
|
625
|
+
if (selected.entry.context.lineNumber) {
|
|
626
|
+
const line = selected.entry.context.lineNumber - 1;
|
|
627
|
+
editor.selection = new vscode.Selection(line, 0, line, 0);
|
|
628
|
+
editor.revealRange(new vscode.Range(line, 0, line, 0));
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
context.subscriptions.push(captureCommand, searchCommand);
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
## 7. Testing Integration
|
|
640
|
+
|
|
641
|
+
### 7.1 Test Infrastructure
|
|
642
|
+
|
|
643
|
+
**Integration Point**: Praxis Test Utils → Conversations Tests
|
|
644
|
+
|
|
645
|
+
**Location**: `/src/conversations/__tests__/`
|
|
646
|
+
|
|
647
|
+
**Implementation**:
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
// /src/conversations/__tests__/capture.test.ts
|
|
651
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
652
|
+
import { createKnowledgeDB, KnowledgeCaptureEngine } from '../core';
|
|
653
|
+
|
|
654
|
+
describe('KnowledgeCaptureEngine', () => {
|
|
655
|
+
let db;
|
|
656
|
+
let engine;
|
|
657
|
+
|
|
658
|
+
beforeEach(async () => {
|
|
659
|
+
db = await createKnowledgeDB({ mode: 'memory' }); // In-memory for tests
|
|
660
|
+
engine = new KnowledgeCaptureEngine({ db });
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('should capture knowledge with context', async () => {
|
|
664
|
+
const entry = await engine.capture({
|
|
665
|
+
type: 'decision',
|
|
666
|
+
title: 'Test decision',
|
|
667
|
+
content: 'Test content',
|
|
668
|
+
context: {
|
|
669
|
+
filePath: '/test.ts',
|
|
670
|
+
lineNumber: 42,
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
expect(entry.id).toBeDefined();
|
|
675
|
+
expect(entry.title).toBe('Test decision');
|
|
676
|
+
expect(entry.context.filePath).toBe('/test.ts');
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('should search knowledge by content', async () => {
|
|
680
|
+
await engine.capture({
|
|
681
|
+
type: 'note',
|
|
682
|
+
title: 'React patterns',
|
|
683
|
+
content: 'Using hooks for state management',
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
const results = await engine.search('hooks');
|
|
687
|
+
|
|
688
|
+
expect(results).toHaveLength(1);
|
|
689
|
+
expect(results[0].title).toBe('React patterns');
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
## Summary: Integration Points
|
|
695
|
+
|
|
696
|
+
| Component | Integration Point | Location | Status |
|
|
697
|
+
|-----------|------------------|----------|--------|
|
|
698
|
+
| Data Storage | PluresDB collections | `/src/conversations/schema/` | Planned |
|
|
699
|
+
| Logic Processing | Praxis rules & events | `/src/conversations/rules/` | Planned |
|
|
700
|
+
| UI Components | Svelte 5 components | `/src/conversations/components/` | Planned |
|
|
701
|
+
| CLI Commands | Praxis CLI | `/src/cli/commands/knowledge.ts` | Planned |
|
|
702
|
+
| Sync | PluresDB + Praxis Cloud | `/src/conversations/sync/` | Planned |
|
|
703
|
+
| IDE Extension | VS Code extension | `/extensions/vscode/` | Planned |
|
|
704
|
+
| Testing | Vitest tests | `/src/conversations/__tests__/` | Planned |
|
|
705
|
+
|
|
706
|
+
## Next Steps
|
|
707
|
+
|
|
708
|
+
1. **Phase 1**: Implement data layer (PluresDB schemas)
|
|
709
|
+
2. **Phase 2**: Implement logic layer (rules and events)
|
|
710
|
+
3. **Phase 3**: Implement CLI commands
|
|
711
|
+
4. **Phase 4**: Build VS Code extension
|
|
712
|
+
5. **Phase 5**: Generate UI components
|
|
713
|
+
6. **Phase 6**: Integration testing
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
**Document Version**: 1.0
|
|
718
|
+
**Last Updated**: 2026-02-01
|
|
719
|
+
**Review Status**: Pending stakeholder approval
|