memorix 1.1.13 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/README.md +6 -3
- package/README.zh-CN.md +6 -3
- package/dist/cli/index.js +36639 -31279
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/app.js +50 -30
- package/dist/index.js +6636 -1778
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +3775 -302
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +33 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js +6634 -1776
- package/dist/sdk.js.map +1 -1
- package/docs/1.2.0-CLAIM-LEDGER.md +72 -0
- package/docs/1.2.0-CODE-STATE.md +61 -0
- package/docs/1.2.0-DEVELOPMENT-CHARTER.md +255 -0
- package/docs/1.2.0-DYNAMIC-LIFECYCLE.md +71 -0
- package/docs/1.2.0-EVALUATION-HARNESS.md +51 -0
- package/docs/1.2.0-IMPLEMENTATION-PLAN.md +554 -0
- package/docs/1.2.0-KNOWLEDGE-WORKFLOW-RESEARCH.md +205 -0
- package/docs/1.2.0-KNOWLEDGE-WORKSPACE.md +68 -0
- package/docs/1.2.0-PRODUCT-STORY.md +234 -0
- package/docs/1.2.0-PROVIDER-QUALITY.md +189 -0
- package/docs/1.2.0-WORKFLOW-INHERITANCE.md +101 -0
- package/docs/1.2.0-WORKSET-RETRIEVAL.md +80 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +6 -3
- package/docs/API_REFERENCE.md +27 -6
- package/docs/CONFIGURATION.md +21 -3
- package/docs/DEVELOPMENT.md +4 -0
- package/docs/README.md +17 -2
- package/docs/SETUP.md +7 -1
- package/docs/dev-log/progress.txt +120 -40
- package/docs/knowledge/workflows/memorix-release.md +57 -0
- package/llms-full.txt +16 -2
- package/llms.txt +9 -4
- package/package.json +3 -2
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/cli/capability-map.ts +1 -0
- package/src/cli/commands/codegraph.ts +111 -9
- package/src/cli/commands/context.ts +2 -0
- package/src/cli/commands/doctor.ts +73 -4
- package/src/cli/commands/knowledge.ts +322 -0
- package/src/cli/commands/serve-http.ts +26 -42
- package/src/cli/commands/setup.ts +9 -3
- package/src/cli/index.ts +3 -1
- package/src/cli/tui/App.tsx +1 -1
- package/src/cli/tui/Panels.tsx +8 -8
- package/src/cli/tui/theme.ts +1 -1
- package/src/cli/tui/views/GraphView.tsx +8 -7
- package/src/cli/tui/views/KnowledgeView.tsx +9 -9
- package/src/codegraph/auto-context.ts +169 -19
- package/src/codegraph/code-state.ts +95 -0
- package/src/codegraph/context-pack.ts +82 -1
- package/src/codegraph/current-facts.ts +19 -1
- package/src/codegraph/external-provider.ts +581 -0
- package/src/codegraph/lite-provider.ts +64 -19
- package/src/codegraph/project-context.ts +9 -1
- package/src/codegraph/store.ts +154 -6
- package/src/codegraph/task-lens.ts +49 -5
- package/src/codegraph/types.ts +117 -0
- package/src/config/resolved-config.ts +28 -0
- package/src/config/toml-loader.ts +3 -0
- package/src/config/yaml-loader.ts +6 -0
- package/src/dashboard/server.ts +30 -47
- package/src/evaluation/workset-evaluation.ts +120 -0
- package/src/hooks/handler.ts +48 -6
- package/src/knowledge/claim-store.ts +267 -0
- package/src/knowledge/claims.ts +587 -0
- package/src/knowledge/markdown.ts +129 -0
- package/src/knowledge/types.ts +158 -0
- package/src/knowledge/wiki.ts +524 -0
- package/src/knowledge/workflow-store.ts +168 -0
- package/src/knowledge/workflow-types.ts +95 -0
- package/src/knowledge/workflows.ts +774 -0
- package/src/knowledge/workset.ts +515 -0
- package/src/knowledge/workspace-store.ts +220 -0
- package/src/knowledge/workspace-types.ts +106 -0
- package/src/knowledge/workspace.ts +220 -0
- package/src/memory/auto-relations.ts +21 -0
- package/src/memory/graph-scope.ts +46 -0
- package/src/memory/observations.ts +19 -0
- package/src/orchestrate/verify-gate.ts +33 -10
- package/src/runtime/control-plane-maintenance.ts +5 -0
- package/src/runtime/isolated-maintenance.ts +5 -0
- package/src/runtime/lifecycle-status.ts +102 -0
- package/src/runtime/lifecycle.ts +107 -0
- package/src/runtime/maintenance-jobs.ts +5 -0
- package/src/runtime/project-maintenance.ts +190 -0
- package/src/server/tool-profile.ts +3 -2
- package/src/server.ts +424 -22
- package/src/store/file-lock.ts +24 -4
- package/src/store/sqlite-db.ts +307 -0
- package/src/wiki/generator.ts +4 -2
- package/src/wiki/knowledge-graph.ts +7 -4
- package/src/wiki/types.ts +16 -4
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { sanitizeCredentials } from '../memory/secret-filter.js';
|
|
3
|
+
import { getDatabase } from '../store/sqlite-db.js';
|
|
4
|
+
import type {
|
|
5
|
+
ClaimConflict,
|
|
6
|
+
ClaimEvent,
|
|
7
|
+
ClaimEvidenceRef,
|
|
8
|
+
KnowledgeClaim,
|
|
9
|
+
KnowledgeClaimStatus,
|
|
10
|
+
} from './types.js';
|
|
11
|
+
|
|
12
|
+
function optionalText(value: unknown): string | undefined {
|
|
13
|
+
return typeof value === 'string' && value ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function rowToClaim(row: any): KnowledgeClaim {
|
|
17
|
+
return {
|
|
18
|
+
id: row.id,
|
|
19
|
+
projectId: row.projectId,
|
|
20
|
+
subject: row.subject,
|
|
21
|
+
predicate: row.predicate,
|
|
22
|
+
objectValue: row.objectValue,
|
|
23
|
+
scope: row.scope,
|
|
24
|
+
claimKey: row.claimKey,
|
|
25
|
+
conflictKey: row.conflictKey,
|
|
26
|
+
status: row.status,
|
|
27
|
+
confidence: Number(row.confidence),
|
|
28
|
+
observedAt: row.observedAt,
|
|
29
|
+
...(optionalText(row.validFrom) ? { validFrom: row.validFrom } : {}),
|
|
30
|
+
...(optionalText(row.validTo) ? { validTo: row.validTo } : {}),
|
|
31
|
+
...(optionalText(row.supersededBy) ? { supersededBy: row.supersededBy } : {}),
|
|
32
|
+
reviewState: row.reviewState,
|
|
33
|
+
origin: row.origin,
|
|
34
|
+
createdAt: row.createdAt,
|
|
35
|
+
updatedAt: row.updatedAt,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function rowToEvidence(row: any): ClaimEvidenceRef {
|
|
40
|
+
return {
|
|
41
|
+
id: row.id,
|
|
42
|
+
claimId: row.claimId,
|
|
43
|
+
evidenceKind: row.evidenceKind,
|
|
44
|
+
evidenceId: row.evidenceId,
|
|
45
|
+
relation: row.relation,
|
|
46
|
+
...(optionalText(row.snapshotId) ? { snapshotId: row.snapshotId } : {}),
|
|
47
|
+
...(optionalText(row.locator) ? { locator: row.locator } : {}),
|
|
48
|
+
...(optionalText(row.capturedHash) ? { capturedHash: row.capturedHash } : {}),
|
|
49
|
+
createdAt: row.createdAt,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function rowToEvent(row: any): ClaimEvent {
|
|
54
|
+
return {
|
|
55
|
+
id: row.id,
|
|
56
|
+
projectId: row.projectId,
|
|
57
|
+
claimId: row.claimId,
|
|
58
|
+
kind: row.kind,
|
|
59
|
+
...(optionalText(row.fromStatus) ? { fromStatus: row.fromStatus } : {}),
|
|
60
|
+
...(optionalText(row.toStatus) ? { toStatus: row.toStatus } : {}),
|
|
61
|
+
...(optionalText(row.relatedClaimId) ? { relatedClaimId: row.relatedClaimId } : {}),
|
|
62
|
+
...(optionalText(row.detail) ? { detail: row.detail } : {}),
|
|
63
|
+
createdAt: row.createdAt,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function evidenceKey(input: Omit<ClaimEvidenceRef, 'id' | 'claimId' | 'createdAt'>): string {
|
|
68
|
+
return createHash('sha256').update(JSON.stringify([
|
|
69
|
+
input.evidenceKind,
|
|
70
|
+
input.evidenceId,
|
|
71
|
+
input.relation,
|
|
72
|
+
input.snapshotId ?? '',
|
|
73
|
+
input.locator ?? '',
|
|
74
|
+
input.capturedHash ?? '',
|
|
75
|
+
])).digest('hex');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* SQLite access for the claim ledger. Domain policy belongs in claims.ts; this
|
|
80
|
+
* class only preserves records and their audit trail atomically.
|
|
81
|
+
*/
|
|
82
|
+
export class ClaimStore {
|
|
83
|
+
private db: any = null;
|
|
84
|
+
|
|
85
|
+
async init(dataDir: string): Promise<void> {
|
|
86
|
+
this.db = getDatabase(dataDir);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
transaction<T>(fn: () => T): T {
|
|
90
|
+
return this.db.transaction(fn)();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getClaim(id: string): KnowledgeClaim | undefined {
|
|
94
|
+
const row = this.db.prepare('SELECT * FROM knowledge_claims WHERE id = ?').get(id);
|
|
95
|
+
return row ? rowToClaim(row) : undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
listClaims(
|
|
99
|
+
projectId: string,
|
|
100
|
+
options: { statuses?: readonly KnowledgeClaimStatus[]; limit?: number } = {},
|
|
101
|
+
): KnowledgeClaim[] {
|
|
102
|
+
const limit = Math.max(1, Math.min(1_000, Math.floor(options.limit ?? 500)));
|
|
103
|
+
if (options.statuses && options.statuses.length > 0) {
|
|
104
|
+
return this.db.prepare(`
|
|
105
|
+
SELECT * FROM knowledge_claims
|
|
106
|
+
WHERE projectId = ? AND status IN (SELECT value FROM json_each(?))
|
|
107
|
+
ORDER BY updatedAt DESC, id
|
|
108
|
+
LIMIT ?
|
|
109
|
+
`).all(projectId, JSON.stringify([...new Set(options.statuses)]), limit).map(rowToClaim);
|
|
110
|
+
}
|
|
111
|
+
return this.db.prepare(`
|
|
112
|
+
SELECT * FROM knowledge_claims
|
|
113
|
+
WHERE projectId = ?
|
|
114
|
+
ORDER BY updatedAt DESC, id
|
|
115
|
+
LIMIT ?
|
|
116
|
+
`).all(projectId, limit).map(rowToClaim);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
findReusableClaim(projectId: string, claimKey: string): KnowledgeClaim | undefined {
|
|
120
|
+
const row = this.db.prepare(`
|
|
121
|
+
SELECT * FROM knowledge_claims
|
|
122
|
+
WHERE projectId = ? AND claimKey = ? AND status IN ('active', 'disputed')
|
|
123
|
+
ORDER BY updatedAt DESC
|
|
124
|
+
LIMIT 1
|
|
125
|
+
`).get(projectId, claimKey);
|
|
126
|
+
return row ? rowToClaim(row) : undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
listClaimsByConflictKey(projectId: string, conflictKey: string): KnowledgeClaim[] {
|
|
130
|
+
return this.db.prepare(`
|
|
131
|
+
SELECT * FROM knowledge_claims
|
|
132
|
+
WHERE projectId = ? AND conflictKey = ?
|
|
133
|
+
ORDER BY createdAt ASC, id
|
|
134
|
+
`).all(projectId, conflictKey).map(rowToClaim);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
listConflicts(projectId: string): ClaimConflict[] {
|
|
138
|
+
const rows = this.db.prepare(`
|
|
139
|
+
SELECT conflictKey
|
|
140
|
+
FROM knowledge_claims
|
|
141
|
+
WHERE projectId = ? AND status IN ('active', 'disputed') AND reviewState = 'approved'
|
|
142
|
+
GROUP BY conflictKey
|
|
143
|
+
HAVING COUNT(DISTINCT claimKey) > 1
|
|
144
|
+
ORDER BY conflictKey
|
|
145
|
+
`).all(projectId) as Array<{ conflictKey: string }>;
|
|
146
|
+
return rows.map(({ conflictKey }) => ({
|
|
147
|
+
conflictKey,
|
|
148
|
+
claims: this.listClaimsByConflictKey(projectId, conflictKey)
|
|
149
|
+
.filter(claim => claim.status === 'active' || claim.status === 'disputed'),
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
insertClaim(claim: KnowledgeClaim): void {
|
|
154
|
+
this.db.prepare(`
|
|
155
|
+
INSERT INTO knowledge_claims (
|
|
156
|
+
id, projectId, subject, predicate, objectValue, scope, claimKey, conflictKey,
|
|
157
|
+
status, confidence, observedAt, validFrom, validTo, supersededBy,
|
|
158
|
+
reviewState, origin, createdAt, updatedAt
|
|
159
|
+
) VALUES (
|
|
160
|
+
@id, @projectId, @subject, @predicate, @objectValue, @scope, @claimKey, @conflictKey,
|
|
161
|
+
@status, @confidence, @observedAt, @validFrom, @validTo, @supersededBy,
|
|
162
|
+
@reviewState, @origin, @createdAt, @updatedAt
|
|
163
|
+
)
|
|
164
|
+
`).run({
|
|
165
|
+
...claim,
|
|
166
|
+
validFrom: claim.validFrom ?? null,
|
|
167
|
+
validTo: claim.validTo ?? null,
|
|
168
|
+
supersededBy: claim.supersededBy ?? null,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
updateClaim(claim: KnowledgeClaim): void {
|
|
173
|
+
this.db.prepare(`
|
|
174
|
+
UPDATE knowledge_claims SET
|
|
175
|
+
subject = @subject,
|
|
176
|
+
predicate = @predicate,
|
|
177
|
+
objectValue = @objectValue,
|
|
178
|
+
scope = @scope,
|
|
179
|
+
claimKey = @claimKey,
|
|
180
|
+
conflictKey = @conflictKey,
|
|
181
|
+
status = @status,
|
|
182
|
+
confidence = @confidence,
|
|
183
|
+
observedAt = @observedAt,
|
|
184
|
+
validFrom = @validFrom,
|
|
185
|
+
validTo = @validTo,
|
|
186
|
+
supersededBy = @supersededBy,
|
|
187
|
+
reviewState = @reviewState,
|
|
188
|
+
origin = @origin,
|
|
189
|
+
updatedAt = @updatedAt
|
|
190
|
+
WHERE id = @id
|
|
191
|
+
`).run({
|
|
192
|
+
...claim,
|
|
193
|
+
validFrom: claim.validFrom ?? null,
|
|
194
|
+
validTo: claim.validTo ?? null,
|
|
195
|
+
supersededBy: claim.supersededBy ?? null,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
touchClaim(id: string, updatedAt: string): void {
|
|
200
|
+
this.db.prepare('UPDATE knowledge_claims SET updatedAt = ? WHERE id = ?').run(updatedAt, id);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
insertEvidence(input: Omit<ClaimEvidenceRef, 'id' | 'createdAt'> & { createdAt?: string }): boolean {
|
|
204
|
+
const createdAt = input.createdAt ?? new Date().toISOString();
|
|
205
|
+
const key = evidenceKey(input);
|
|
206
|
+
const result = this.db.prepare(`
|
|
207
|
+
INSERT OR IGNORE INTO knowledge_claim_evidence (
|
|
208
|
+
id, claimId, evidenceKind, evidenceId, relation, snapshotId,
|
|
209
|
+
locator, capturedHash, evidenceKey, createdAt
|
|
210
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
211
|
+
`).run(
|
|
212
|
+
randomUUID(),
|
|
213
|
+
input.claimId,
|
|
214
|
+
input.evidenceKind,
|
|
215
|
+
input.evidenceId,
|
|
216
|
+
input.relation,
|
|
217
|
+
input.snapshotId ?? null,
|
|
218
|
+
input.locator ? sanitizeCredentials(input.locator) : null,
|
|
219
|
+
input.capturedHash ?? null,
|
|
220
|
+
key,
|
|
221
|
+
createdAt,
|
|
222
|
+
);
|
|
223
|
+
return Number(result.changes ?? 0) > 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
listEvidence(claimId: string): ClaimEvidenceRef[] {
|
|
227
|
+
return this.db.prepare(`
|
|
228
|
+
SELECT * FROM knowledge_claim_evidence
|
|
229
|
+
WHERE claimId = ?
|
|
230
|
+
ORDER BY createdAt ASC, id
|
|
231
|
+
`).all(claimId).map(rowToEvidence);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
recordEvent(input: Omit<ClaimEvent, 'id' | 'createdAt'> & { createdAt?: string }): ClaimEvent {
|
|
235
|
+
const event: ClaimEvent = {
|
|
236
|
+
id: randomUUID(),
|
|
237
|
+
...input,
|
|
238
|
+
...(input.detail ? { detail: sanitizeCredentials(input.detail) } : {}),
|
|
239
|
+
createdAt: input.createdAt ?? new Date().toISOString(),
|
|
240
|
+
};
|
|
241
|
+
this.db.prepare(`
|
|
242
|
+
INSERT INTO knowledge_claim_events (
|
|
243
|
+
id, projectId, claimId, kind, fromStatus, toStatus,
|
|
244
|
+
relatedClaimId, detail, createdAt
|
|
245
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
246
|
+
`).run(
|
|
247
|
+
event.id,
|
|
248
|
+
event.projectId,
|
|
249
|
+
event.claimId,
|
|
250
|
+
event.kind,
|
|
251
|
+
event.fromStatus ?? null,
|
|
252
|
+
event.toStatus ?? null,
|
|
253
|
+
event.relatedClaimId ?? null,
|
|
254
|
+
event.detail ?? null,
|
|
255
|
+
event.createdAt,
|
|
256
|
+
);
|
|
257
|
+
return event;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
listEvents(claimId: string): ClaimEvent[] {
|
|
261
|
+
return this.db.prepare(`
|
|
262
|
+
SELECT * FROM knowledge_claim_events
|
|
263
|
+
WHERE claimId = ?
|
|
264
|
+
ORDER BY createdAt ASC, id
|
|
265
|
+
`).all(claimId).map(rowToEvent);
|
|
266
|
+
}
|
|
267
|
+
}
|