memorix 1.1.13 → 1.2.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 (88) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +3 -2
  3. package/README.zh-CN.md +3 -2
  4. package/dist/cli/index.js +36313 -31189
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/dashboard/static/app.js +50 -30
  7. package/dist/index.js +5348 -674
  8. package/dist/index.js.map +1 -1
  9. package/dist/maintenance-runner.d.ts +1 -1
  10. package/dist/maintenance-runner.js +3661 -293
  11. package/dist/maintenance-runner.js.map +1 -1
  12. package/dist/memcode-runtime/CHANGELOG.md +19 -0
  13. package/dist/sdk.d.ts +1 -1
  14. package/dist/sdk.js +5346 -672
  15. package/dist/sdk.js.map +1 -1
  16. package/docs/1.2.0-CLAIM-LEDGER.md +72 -0
  17. package/docs/1.2.0-CODE-STATE.md +61 -0
  18. package/docs/1.2.0-DEVELOPMENT-CHARTER.md +255 -0
  19. package/docs/1.2.0-DYNAMIC-LIFECYCLE.md +71 -0
  20. package/docs/1.2.0-EVALUATION-HARNESS.md +51 -0
  21. package/docs/1.2.0-IMPLEMENTATION-PLAN.md +554 -0
  22. package/docs/1.2.0-KNOWLEDGE-WORKFLOW-RESEARCH.md +205 -0
  23. package/docs/1.2.0-KNOWLEDGE-WORKSPACE.md +68 -0
  24. package/docs/1.2.0-PRODUCT-STORY.md +234 -0
  25. package/docs/1.2.0-PROVIDER-QUALITY.md +189 -0
  26. package/docs/1.2.0-WORKFLOW-INHERITANCE.md +101 -0
  27. package/docs/1.2.0-WORKSET-RETRIEVAL.md +80 -0
  28. package/docs/AGENT_OPERATOR_PLAYBOOK.md +6 -3
  29. package/docs/API_REFERENCE.md +25 -6
  30. package/docs/CONFIGURATION.md +21 -3
  31. package/docs/README.md +17 -2
  32. package/docs/dev-log/progress.txt +120 -40
  33. package/llms-full.txt +16 -2
  34. package/llms.txt +9 -4
  35. package/package.json +3 -2
  36. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  37. package/src/cli/capability-map.ts +1 -0
  38. package/src/cli/commands/codegraph.ts +112 -9
  39. package/src/cli/commands/context.ts +2 -0
  40. package/src/cli/commands/doctor.ts +73 -4
  41. package/src/cli/commands/knowledge.ts +282 -0
  42. package/src/cli/commands/serve-http.ts +12 -1
  43. package/src/cli/index.ts +3 -1
  44. package/src/cli/tui/App.tsx +1 -1
  45. package/src/cli/tui/Panels.tsx +8 -8
  46. package/src/cli/tui/theme.ts +1 -1
  47. package/src/cli/tui/views/GraphView.tsx +8 -7
  48. package/src/cli/tui/views/KnowledgeView.tsx +9 -9
  49. package/src/codegraph/auto-context.ts +171 -9
  50. package/src/codegraph/code-state.ts +95 -0
  51. package/src/codegraph/context-pack.ts +82 -1
  52. package/src/codegraph/external-provider.ts +581 -0
  53. package/src/codegraph/lite-provider.ts +64 -19
  54. package/src/codegraph/project-context.ts +9 -1
  55. package/src/codegraph/store.ts +154 -6
  56. package/src/codegraph/types.ts +117 -0
  57. package/src/config/resolved-config.ts +28 -0
  58. package/src/config/toml-loader.ts +3 -0
  59. package/src/config/yaml-loader.ts +6 -0
  60. package/src/dashboard/server.ts +15 -1
  61. package/src/evaluation/workset-evaluation.ts +120 -0
  62. package/src/hooks/handler.ts +48 -6
  63. package/src/knowledge/claim-store.ts +267 -0
  64. package/src/knowledge/claims.ts +537 -0
  65. package/src/knowledge/markdown.ts +129 -0
  66. package/src/knowledge/types.ts +157 -0
  67. package/src/knowledge/wiki.ts +524 -0
  68. package/src/knowledge/workflow-store.ts +168 -0
  69. package/src/knowledge/workflow-types.ts +95 -0
  70. package/src/knowledge/workflows.ts +743 -0
  71. package/src/knowledge/workset.ts +515 -0
  72. package/src/knowledge/workspace-store.ts +220 -0
  73. package/src/knowledge/workspace-types.ts +106 -0
  74. package/src/knowledge/workspace.ts +220 -0
  75. package/src/memory/observations.ts +19 -0
  76. package/src/runtime/control-plane-maintenance.ts +5 -0
  77. package/src/runtime/isolated-maintenance.ts +5 -0
  78. package/src/runtime/lifecycle-status.ts +102 -0
  79. package/src/runtime/lifecycle.ts +107 -0
  80. package/src/runtime/maintenance-jobs.ts +5 -0
  81. package/src/runtime/project-maintenance.ts +190 -0
  82. package/src/server/tool-profile.ts +3 -2
  83. package/src/server.ts +354 -14
  84. package/src/store/file-lock.ts +24 -4
  85. package/src/store/sqlite-db.ts +307 -0
  86. package/src/wiki/generator.ts +4 -2
  87. package/src/wiki/knowledge-graph.ts +7 -4
  88. package/src/wiki/types.ts +16 -4
@@ -0,0 +1,168 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { getDatabase } from '../store/sqlite-db.js';
3
+ import type {
4
+ WorkflowRun,
5
+ WorkflowRunInput,
6
+ WorkflowRunOutcome,
7
+ WorkflowSpec,
8
+ WorkflowVerificationVerdict,
9
+ } from './workflow-types.js';
10
+
11
+ function parseJson<T>(value: unknown, fallback: T): T {
12
+ if (typeof value !== 'string' || !value) return fallback;
13
+ try {
14
+ return JSON.parse(value) as T;
15
+ } catch {
16
+ return fallback;
17
+ }
18
+ }
19
+
20
+ function optionalText(value: unknown): string | undefined {
21
+ return typeof value === 'string' && value.trim() ? value : undefined;
22
+ }
23
+
24
+ function rowToWorkflow(row: any): WorkflowSpec {
25
+ return parseJson<WorkflowSpec>(row.specJson, {
26
+ id: row.id,
27
+ workspaceId: row.workspaceId,
28
+ title: row.title,
29
+ description: '',
30
+ status: row.status,
31
+ version: row.version,
32
+ taskLenses: [],
33
+ triggers: [],
34
+ assumptions: [],
35
+ requiredContext: [],
36
+ guardrails: [],
37
+ allowedTools: [],
38
+ phases: [],
39
+ verificationGates: [],
40
+ claimIds: [],
41
+ evidenceRefs: [],
42
+ codeRefs: [],
43
+ compatibleAgents: [],
44
+ body: '',
45
+ sourcePath: row.sourcePath,
46
+ sourceHash: row.sourceHash,
47
+ contentHash: row.contentHash,
48
+ createdAt: row.createdAt,
49
+ updatedAt: row.updatedAt,
50
+ });
51
+ }
52
+
53
+ function rowToRun(row: any): WorkflowRun {
54
+ return {
55
+ id: row.id,
56
+ workflowId: row.workflowId,
57
+ projectId: row.projectId,
58
+ task: row.task,
59
+ ...(optionalText(row.startingSnapshotId) ? { startingSnapshotId: row.startingSnapshotId } : {}),
60
+ selectedEvidence: parseJson<string[]>(row.selectedEvidenceJson, []),
61
+ phaseState: parseJson<WorkflowRun['phaseState']>(row.phaseStateJson, {}),
62
+ outcome: row.outcome as WorkflowRunOutcome,
63
+ verificationVerdict: row.verificationVerdict as WorkflowVerificationVerdict,
64
+ ...(optionalText(row.failureReason) ? { failureReason: row.failureReason } : {}),
65
+ startedAt: row.startedAt,
66
+ ...(optionalText(row.completedAt) ? { completedAt: row.completedAt } : {}),
67
+ };
68
+ }
69
+
70
+ export class WorkflowStore {
71
+ private db: any = null;
72
+
73
+ async init(dataDir: string): Promise<void> {
74
+ this.db = getDatabase(dataDir);
75
+ }
76
+
77
+ upsertWorkflow(workflow: WorkflowSpec): WorkflowSpec {
78
+ this.db.prepare(
79
+ 'INSERT INTO knowledge_workflows (id, workspaceId, sourcePath, title, status, version, sourceHash, contentHash, specJson, importedFrom, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(workspaceId, sourcePath) DO UPDATE SET id = excluded.id, title = excluded.title, status = excluded.status, version = excluded.version, sourceHash = excluded.sourceHash, contentHash = excluded.contentHash, specJson = excluded.specJson, importedFrom = excluded.importedFrom, updatedAt = excluded.updatedAt',
80
+ ).run(
81
+ workflow.id,
82
+ workflow.workspaceId,
83
+ workflow.sourcePath,
84
+ workflow.title,
85
+ workflow.status,
86
+ workflow.version,
87
+ workflow.sourceHash,
88
+ workflow.contentHash,
89
+ JSON.stringify(workflow),
90
+ workflow.importedFrom ?? null,
91
+ workflow.createdAt,
92
+ workflow.updatedAt,
93
+ );
94
+ return this.getWorkflowByPath(workflow.workspaceId, workflow.sourcePath)!;
95
+ }
96
+
97
+ getWorkflow(id: string): WorkflowSpec | undefined {
98
+ const row = this.db.prepare('SELECT * FROM knowledge_workflows WHERE id = ?').get(id);
99
+ return row ? rowToWorkflow(row) : undefined;
100
+ }
101
+
102
+ getWorkflowByPath(workspaceId: string, sourcePath: string): WorkflowSpec | undefined {
103
+ const row = this.db.prepare('SELECT * FROM knowledge_workflows WHERE workspaceId = ? AND sourcePath = ?').get(workspaceId, sourcePath);
104
+ return row ? rowToWorkflow(row) : undefined;
105
+ }
106
+
107
+ listWorkflows(workspaceId: string, status?: WorkflowSpec['status']): WorkflowSpec[] {
108
+ const rows = status
109
+ ? this.db.prepare('SELECT * FROM knowledge_workflows WHERE workspaceId = ? AND status = ? ORDER BY title, id').all(workspaceId, status)
110
+ : this.db.prepare('SELECT * FROM knowledge_workflows WHERE workspaceId = ? ORDER BY title, id').all(workspaceId);
111
+ return rows.map(rowToWorkflow);
112
+ }
113
+
114
+ recordRun(input: WorkflowRunInput): WorkflowRun {
115
+ const run: WorkflowRun = {
116
+ id: randomUUID(),
117
+ workflowId: input.workflowId,
118
+ projectId: input.projectId,
119
+ task: input.task.trim(),
120
+ ...(input.startingSnapshotId ? { startingSnapshotId: input.startingSnapshotId } : {}),
121
+ selectedEvidence: [...new Set(input.selectedEvidence ?? [])],
122
+ phaseState: input.phaseState ?? {},
123
+ outcome: input.outcome,
124
+ verificationVerdict: input.verificationVerdict ?? (input.outcome === 'failed' ? 'failed' : 'not-run'),
125
+ ...(input.failureReason?.trim() ? { failureReason: input.failureReason.trim() } : {}),
126
+ startedAt: input.startedAt ?? new Date().toISOString(),
127
+ ...(input.completedAt ? { completedAt: input.completedAt } : input.outcome !== 'in-progress' ? { completedAt: new Date().toISOString() } : {}),
128
+ };
129
+ this.db.prepare(
130
+ 'INSERT INTO knowledge_workflow_runs (id, workflowId, projectId, task, startingSnapshotId, selectedEvidenceJson, phaseStateJson, outcome, verificationVerdict, failureReason, startedAt, completedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
131
+ ).run(
132
+ run.id,
133
+ run.workflowId,
134
+ run.projectId,
135
+ run.task,
136
+ run.startingSnapshotId ?? null,
137
+ JSON.stringify(run.selectedEvidence),
138
+ JSON.stringify(run.phaseState),
139
+ run.outcome,
140
+ run.verificationVerdict,
141
+ run.failureReason ?? null,
142
+ run.startedAt,
143
+ run.completedAt ?? null,
144
+ );
145
+ return this.getRun(run.id)!;
146
+ }
147
+
148
+ getRun(id: string): WorkflowRun | undefined {
149
+ const row = this.db.prepare('SELECT * FROM knowledge_workflow_runs WHERE id = ?').get(id);
150
+ return row ? rowToRun(row) : undefined;
151
+ }
152
+
153
+ listRuns(projectId: string, workflowId?: string, limit = 20): WorkflowRun[] {
154
+ const boundedLimit = Math.max(1, Math.min(Math.floor(limit), 100));
155
+ const rows = workflowId
156
+ ? this.db.prepare('SELECT * FROM knowledge_workflow_runs WHERE projectId = ? AND workflowId = ? ORDER BY startedAt DESC LIMIT ?').all(projectId, workflowId, boundedLimit)
157
+ : this.db.prepare('SELECT * FROM knowledge_workflow_runs WHERE projectId = ? ORDER BY startedAt DESC LIMIT ?').all(projectId, boundedLimit);
158
+ return rows.map(rowToRun);
159
+ }
160
+
161
+ recentFailureCautions(projectId: string, workflowId: string, limit = 2): string[] {
162
+ return this.listRuns(projectId, workflowId, limit)
163
+ .filter(run => run.outcome === 'failed' || run.verificationVerdict === 'failed')
164
+ .map(run => run.failureReason
165
+ ? 'Previous run failed: ' + run.failureReason
166
+ : 'Previous run has a failed verification gate.');
167
+ }
168
+ }
@@ -0,0 +1,95 @@
1
+ import type { AgentTarget } from '../types.js';
2
+
3
+ export type WorkflowStatus = 'draft' | 'active' | 'archived';
4
+ export type WorkflowRunOutcome = 'passed' | 'failed' | 'cancelled' | 'in-progress';
5
+ export type WorkflowVerificationVerdict = 'passed' | 'failed' | 'not-run';
6
+
7
+ export interface WorkflowPhase {
8
+ id: string;
9
+ title: string;
10
+ instructions: string;
11
+ branches: string[];
12
+ expectedOutputs: string[];
13
+ verificationGates: string[];
14
+ }
15
+
16
+ /**
17
+ * A canonical project workflow. The Markdown file is the readable source; the
18
+ * SQLite copy exists only to make selection, run history, and diagnostics fast.
19
+ */
20
+ export interface WorkflowSpec {
21
+ id: string;
22
+ workspaceId: string;
23
+ title: string;
24
+ description: string;
25
+ status: WorkflowStatus;
26
+ version: number;
27
+ taskLenses: string[];
28
+ triggers: string[];
29
+ assumptions: string[];
30
+ requiredContext: string[];
31
+ guardrails: string[];
32
+ allowedTools: string[];
33
+ phases: WorkflowPhase[];
34
+ verificationGates: string[];
35
+ claimIds: string[];
36
+ evidenceRefs: string[];
37
+ codeRefs: string[];
38
+ compatibleAgents: AgentTarget[];
39
+ body: string;
40
+ sourcePath: string;
41
+ sourceHash: string;
42
+ contentHash: string;
43
+ createdAt: string;
44
+ updatedAt: string;
45
+ importedFrom?: string;
46
+ }
47
+
48
+ export interface WorkflowRun {
49
+ id: string;
50
+ workflowId: string;
51
+ projectId: string;
52
+ task: string;
53
+ startingSnapshotId?: string;
54
+ selectedEvidence: string[];
55
+ phaseState: Record<string, 'pending' | 'active' | 'passed' | 'failed' | 'skipped'>;
56
+ outcome: WorkflowRunOutcome;
57
+ verificationVerdict: WorkflowVerificationVerdict;
58
+ failureReason?: string;
59
+ startedAt: string;
60
+ completedAt?: string;
61
+ }
62
+
63
+ export interface WorkflowRunInput {
64
+ workflowId: string;
65
+ projectId: string;
66
+ task: string;
67
+ startingSnapshotId?: string;
68
+ selectedEvidence?: string[];
69
+ phaseState?: WorkflowRun['phaseState'];
70
+ outcome: WorkflowRunOutcome;
71
+ verificationVerdict?: WorkflowVerificationVerdict;
72
+ failureReason?: string;
73
+ startedAt?: string;
74
+ completedAt?: string;
75
+ }
76
+
77
+ export interface WorkflowSelection {
78
+ workflow: WorkflowSpec;
79
+ score: number;
80
+ reasons: string[];
81
+ firstPhase: WorkflowPhase;
82
+ cautions: string[];
83
+ }
84
+
85
+ export type WorkflowAdapterTarget = Extract<AgentTarget, 'codex' | 'claude-code' | 'cursor' | 'windsurf'>;
86
+ export type WorkflowAdapterStatus = 'create' | 'update' | 'unchanged' | 'conflict' | 'unsupported';
87
+
88
+ export interface WorkflowAdapterPreview {
89
+ agent: AgentTarget;
90
+ workflowId: string;
91
+ targetPath?: string;
92
+ content?: string;
93
+ status: WorkflowAdapterStatus;
94
+ reason: string;
95
+ }