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
@@ -4,43 +4,123 @@
4
4
  > older notes when they conflict.
5
5
 
6
6
  ## Current State
7
- - Phase: 1.1.13 ready to publish
8
- - Branch: `codex/1.1.13-release-contract`
9
- - Last updated: 2026-07-17
10
- - Goal: make Codex global setup diagnosable end to end, remove the accidental
11
- workspace publish lane, restore the Star History chart, then publish a clean
12
- 1.1.13 before beginning 1.2 work.
13
-
14
- ## Completed Recently
15
- - Released `memorix@1.1.12`, tagged `v1.1.12`, with native Codex lifecycle
16
- hooks, Windows-safe OpenCode hook resolution, scope-isolated setup, and
17
- cache-first semantic-vector hydration.
18
- - `memorix setup --agent codex --global` now stamps the copied plugin manifest
19
- with the running Memorix version instead of leaving the template version.
20
- - `memorix doctor agents --agent codex --scope global` now reports four
21
- independently useful facts: the local bundle and declared hook contract, the
22
- Personal marketplace entry, Codex's installed/enabled plugin state, and the
23
- trusted state for each Codex lifecycle hook.
24
- - Repair only refreshes Memorix-owned files. A disabled plugin or untrusted
25
- hook remains an explicit user action in Codex's plugin/hook UI.
26
- - `@memorix/ai`, `@memorix/agent-core`, `@memorix/tui`, and
27
- `@memorix/memcode` are explicitly internal workspaces. The public release
28
- contract is the bundled root `memorix` package.
29
- - Restored the AVIDS2/memorix Star History chart at the bottom of both READMEs.
30
-
31
- ## Verification Snapshot
32
- - Focused Codex setup, hook, doctor, and release-contract regressions pass.
33
- - `npm run lint`, `npm run build`, and the full serial `npm test` suite pass.
34
- - `npm pack --dry-run` includes the root runtime, plugin templates, hooks,
35
- READMEs, and docs at `memorix@1.1.13`.
36
- - A clean normal npm installation of the tarball completed a real stdio MCP
37
- store/search call against an isolated Git repository and exposed the expected
38
- seven-tool micro profile.
39
- - An isolated real Codex CLI setup installed and enabled `memorix@personal`,
40
- stamped the manifest at `1.1.13`, and let doctor verify the bundle,
41
- marketplace, runtime state, and pending first-use hook trust separately.
42
- - The Star History embed uses Star History's current `/image` README endpoint.
43
-
44
- ## Next Steps
45
- - Push/merge/tag/publish `v1.1.13`, then create the 1.2 development baseline
46
- from the released main branch.
7
+ - Phase: 1.2 release validation and publication
8
+ - Branch: `codex/1.2.0-multidimensional-memory`
9
+ - Last updated: 2026-07-18
10
+ - Released baseline: `memorix@1.1.13`, tag `v1.1.13`, PR #129 merged as
11
+ `7e8077f`.
12
+ - Goal: turn Memorix from a useful narrative-memory layer into a task-ready
13
+ working-context layer where code state, change evidence, verification,
14
+ source-backed project knowledge, workflows, and durable decisions are ranked
15
+ together.
16
+
17
+ ## 1.1.13 Closeout
18
+ - Codex setup now stamps plugin versions and doctor distinguishes bundle,
19
+ marketplace, installed/enabled state, declared hooks, and hook trust.
20
+ - Root package publishing is isolated from internal `@memorix/*` workspaces.
21
+ - Full tests, build, pack inspection, isolated MCP smoke, isolated Codex smoke,
22
+ and Ubuntu/Windows CI all passed before release.
23
+
24
+ ## 1.2 Accepted Direction
25
+ - The [1.2 Product Story](../1.2.0-PRODUCT-STORY.md) is the canonical
26
+ user-facing narrative; the Development Charter is its implementation
27
+ contract.
28
+ - The [Knowledge and Workflow Research](../1.2.0-KNOWLEDGE-WORKFLOW-RESEARCH.md)
29
+ establishes Knowledge Workspace and Workflow Inheritance as 1.2 core product
30
+ layers, with an explicit boundary against claiming the existing memory map is
31
+ already a semantic graph or maintained LLM Wiki.
32
+ - The [1.2 Implementation Plan](../1.2.0-IMPLEMENTATION-PLAN.md) is the
33
+ execution contract for the single complete 1.2 goal. All phases are internal
34
+ gates in one continuous delivery path, not separate user approval points.
35
+ - Use the [1.2 Development Charter](../1.2.0-DEVELOPMENT-CHARTER.md) as the
36
+ working product contract.
37
+ - Keep the current SQLite CodeGraph tables and incremental refresh as the base;
38
+ do not discard working 1.1 Code Memory.
39
+ - Add versioned Code State and evidence-quality semantics before new parsers,
40
+ external providers, or user-visible tool surfaces.
41
+ - Treat natural-language `memorix_project_context` as the product surface;
42
+ internal graph/provider complexity must stay behind it.
43
+
44
+ ## Phase 0 Evaluation Foundation
45
+ - Existing UI/API projections now identify themselves honestly as a read-only
46
+ Memory Overview and deterministic Memory Map. They are not presented as a
47
+ maintained wiki or semantic graph.
48
+ - The Workset evaluation harness has fixture repositories for TypeScript,
49
+ Python, Go, docs-only, dirty worktree, deleted-symbol, and incomplete-scan
50
+ cases. Its seed manifest covers observations, Git facts, test evidence,
51
+ mini-skills, and explicit graph relations.
52
+ - The harness compares memory-only, current-context, and candidate Worksets
53
+ against source/evidence/caution requirements and variant token ceilings.
54
+ - The current Auto Context path is smoke-tested against real local TypeScript
55
+ and dirty-worktree fixtures with embeddings disabled. The candidate budget is
56
+ 180 tokens; the current baseline budget is 320 tokens.
57
+ - The former memory map remains separate from the formal Claim Ledger. Phase 2
58
+ owns claim provenance, conflict, and supersession semantics; Phase 0 only
59
+ prevents the old views from being mislabeled as those capabilities.
60
+
61
+ ## Phase 1 Code State
62
+ - Lite refresh now appends a Code State Snapshot with bounded Git revision and
63
+ worktree metadata, a source epoch, a prior-snapshot link, and explicit scan
64
+ completeness.
65
+ - Current files, symbols, edges, and current observation-code refs are marked
66
+ with the latest completed snapshot. Existing CodeGraph rows survive the
67
+ additive schema migration.
68
+ - Project Context, the CodeGraph MCP status payload, and the codegraph CLI
69
+ status output expose the latest snapshot. A non-Git directory reports
70
+ unavailable instead of clean.
71
+
72
+ ## Phase 2 Claim Ledger
73
+ - SQLite now has additive, transactional tables for claims, evidence
74
+ references, and lifecycle events. Every stored claim requires at least one
75
+ source reference and credential values are sanitized before durable writes.
76
+ - Exact normalized assertions reuse their record and attach more evidence;
77
+ competing approved assertions remain disputed rather than being overwritten.
78
+ Evidence-aware supersession preserves an audit trail.
79
+ - Explicit memories and Git-ingested facts can derive conservative claims.
80
+ Hook/model output does not become approved knowledge automatically.
81
+ - Observation code references inherit the latest Code State Snapshot when they
82
+ are created. CodeGraph refresh requalifies bound claims: changed or deleted
83
+ symbols become unknown, and incomplete scans force review instead of false
84
+ certainty.
85
+ - Unit and integration tests cover evidence validation, redaction, conflict,
86
+ supersession, model-review policy, snapshot binding, changed-symbol
87
+ requalification, and compact task selection.
88
+
89
+ ## Phase 3 Knowledge Workspace
90
+ - Memorix now initializes a private local Markdown workspace by default. A
91
+ versioned workspace requires an explicit absolute path inside the Git project
92
+ and refuses ignored or unsafe target directories.
93
+ - Approved active claims compile into Markdown proposals with frontmatter,
94
+ source claim ids, evidence references, snapshot context, a catalog, and an
95
+ append-only change log. Proposed pages are not silently published.
96
+ - The knowledge init, status, compile, apply, and lint commands provide the
97
+ operator path. Applying a proposal protects a manual page edit by default;
98
+ an explicit force flag is the only overwrite path and is logged.
99
+ - Workspace lint detects malformed frontmatter, broken links, orphan pages,
100
+ missing claims/evidence, superseded claims, unresolved conflicts, stale code
101
+ snapshots, and protected manual edits.
102
+ - The compiled CLI was smoke-tested in an isolated Git project through init,
103
+ compile, apply, and lint with a source-backed claim.
104
+
105
+ ## 1.2 Delivery Complete, Release Checks In Progress
106
+ - Phase 4 added canonical Markdown workflows, safe adapter preview/apply, import,
107
+ selection, and verification receipts. Agent instruction files are render
108
+ targets, not the workflow source of truth.
109
+ - Phase 5 routes Project Context and Context Pack through one bounded Workset
110
+ assembler. It ranks current facts, claims, knowledge pages, workflows, and
111
+ cautions instead of dumping unrelated narrative memory.
112
+ - Phase 6 makes refresh, claim derivation/requalification, knowledge
113
+ compile/lint, workflow indexing, retention, and consolidation durable
114
+ maintenance work. Interactive MCP requests do not scan an entire corpus.
115
+ - Phase 7 adds an optional local semantic CodeGraph boundary. Lite remains the
116
+ durable local fallback; external output is used only from a healthy existing
117
+ `.codegraph` index, is validated, bounded, and never persisted as raw code.
118
+ - The advanced `memorix_knowledge` MCP action tool now exposes explicit
119
+ workspace/proposal/workflow management only in `team` and `full` profiles.
120
+ - Completed local release gates: lint, full test suite, production build,
121
+ package-content audit, isolated Windows npm install, stdio MCP smoke, and
122
+ HTTP dashboard/lifecycle smoke.
123
+ - Release audit also incorporated #130 before publication: the optional SQLite
124
+ runtime now uses the Node-26-compatible `better-sqlite3` 12.x line, with a
125
+ dedicated Node 26 CI smoke that opens an in-memory database.
126
+ - Remaining remote gates: GitHub CI, npm publish, tag, and GitHub release.
package/llms-full.txt CHANGED
@@ -2,10 +2,23 @@
2
2
 
3
3
  > Local-first shared memory layer for AI coding agents.
4
4
 
5
- Memorix is a TypeScript/Node.js project that gives AI coding agents persistent, project-aware memory. It targets software development workflows, not generic chat. It works across Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, Pi, Kiro, Antigravity, Trae, and any agent that can speak MCP over stdio or HTTP. Integrations usually start with `memorix setup --agent <agent> --global`, which installs the recommended user-level package or config for that agent: plugin packages when supported, package or extension entries, MCP config, generated guidance, hooks, skills, or the bundled terminal agent.
5
+ Memorix is a TypeScript/Node.js project that gives AI coding agents persistent, project-aware memory. It targets software development workflows, not generic chat. It works across Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, OpenClaw, Hermes Agent, Oh-my-Pi, Pi, Kiro, Antigravity, Trae, and any agent that can speak MCP over stdio or HTTP. Integrations usually start with `memorix setup --agent <agent> --global`, which installs the recommended user-level package or config for that agent: plugin packages when supported, package or extension entries, MCP config, generated guidance, hooks, skills, or the bundled terminal agent.
6
6
 
7
7
  If you are an AI coding agent helping a user install, operate, or troubleshoot Memorix, read `docs/AGENT_OPERATOR_PLAYBOOK.md` before taking action. It is the main reference for install, runtime selection, Git/project binding, MCP integration, hooks, and troubleshooting.
8
8
 
9
+ ## 1.2 Multi-Dimensional Memory Model
10
+
11
+ Memorix is not a transcript dump. The normal agent path is `memorix_project_context` or `memorix context --task "..."`, which assembles a bounded task Workset: current Git/package facts, selected observations and reasoning, Code State freshness, source-backed claims, matching knowledge/workflow starts, cautions, and verification hints.
12
+
13
+ - **Observation, Reasoning, and Git Memory** preserve durable engineering facts.
14
+ - **Code State** records versioned local file, symbol, import, and memory-to-code links so prior evidence can be requalified when code moves.
15
+ - **Claim Ledger** keeps provenance, confidence, conflicts, and lifecycle state separate from prose.
16
+ - **Knowledge Workspace** compiles claims into reviewable Markdown proposals; it does not silently overwrite manually edited pages.
17
+ - **Canonical Workflows** represent project process once and render conservative agent-specific adapters only on explicit request.
18
+ - **Lifecycle maintenance** uses durable, resumable jobs so indexing, claim requalification, knowledge compile/lint, retention, and consolidation do not turn an interactive MCP request into a corpus-sized foreground job.
19
+
20
+ The built-in CodeGraph Lite provider is a structural local fallback, not a complete semantic graph. If a project already has a healthy local CodeGraph index, `[codegraph].external_context = "auto"` can add a small validated semantic outline. Memorix never runs `codegraph init`, `index`, or `sync`, does not transmit the repository, and does not persist raw external code output.
21
+
9
22
  ## Entry Points
10
23
 
11
24
  ### Setup package
@@ -348,7 +361,7 @@ Docker is for the HTTP service. The container must have access to the repositori
348
361
 
349
362
  ## Supported Clients
350
363
 
351
- Memorix supports Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, Pi, Kiro, Antigravity, Trae, memcode, and other stdio or HTTP MCP clients.
364
+ Memorix supports Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, OpenClaw, Hermes Agent, Oh-my-Pi, Pi, Kiro, Antigravity, Trae, memcode, and other stdio or HTTP MCP clients.
352
365
 
353
366
  Support depth differs by client:
354
367
 
@@ -356,6 +369,7 @@ Support depth differs by client:
356
369
  - MCP is the common integration layer.
357
370
  - Claude Code, Codex, and GitHub Copilot CLI receive local plugin packages.
358
371
  - Pi receives a user-level package when setup runs with `--global`; Gemini CLI receives a local extension package.
372
+ - OpenClaw receives a compatible bundle; Hermes Agent receives a plugin package; Oh-my-Pi receives a package/extension entry.
359
373
  - Project instructions and rules include AGENTS.md, GEMINI.md, Cursor rules, Windsurf rules, Kiro steering, and Trae rules.
360
374
  - Hooks are generated for agents that expose usable hook events.
361
375
  - OpenCode receives a local plugin file at `.opencode/plugins/memorix.js`, an OpenCode skill at `.opencode/skills/memorix-memory/SKILL.md`, plus `opencode.json` MCP config.
package/llms.txt CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Local-first shared memory layer for AI coding agents.
4
4
 
5
- Memorix gives coding agents persistent, project-aware memory across sessions, IDEs, terminals, and MCP clients. It stores project knowledge once so multiple agents can retrieve it through plugin packages, MCP, CLI, SDK, generated rules/instructions, hooks, skills, local plugins, or the bundled terminal agent. It works with Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, Pi, Kiro, Antigravity, Trae, and other MCP-capable agents.
5
+ Memorix gives coding agents persistent, project-aware memory across sessions, IDEs, terminals, and MCP clients. It stores project knowledge once so multiple agents can retrieve it through plugin packages, MCP, CLI, SDK, generated rules/instructions, hooks, skills, local plugins, or the bundled terminal agent. It works with Claude Code, Codex, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenCode, OpenClaw, Hermes Agent, Oh-my-Pi, Pi, Kiro, Antigravity, Trae, and other MCP-capable agents.
6
6
 
7
7
  ## Entry Points
8
8
 
@@ -10,20 +10,25 @@ Memorix gives coding agents persistent, project-aware memory across sessions, ID
10
10
  - `memorix setup --list` lists supported agent entry points.
11
11
  - `memorix serve` starts the manual stdio MCP server for IDEs and agents.
12
12
  - `memorix background start` starts the HTTP MCP service and dashboard.
13
- - `memorix memory`, `reasoning`, `session`, `team`, `task`, `handoff`, `poll`, `receipt`, `sync`, `ingest`, and `orchestrate` expose the CLI command set.
13
+ - `memorix memory`, `codegraph`, `knowledge`, `reasoning`, `session`, `team`, `task`, `handoff`, `poll`, `receipt`, `sync`, `ingest`, and `orchestrate` expose the CLI command set.
14
14
  - `memorix integrate --agent <agent>` and `memorix hooks install --agent <agent>` are manual/fallback generation commands.
15
15
  - `memorix` and `memcode` open memcode, the bundled terminal agent that uses the same project memory pool.
16
16
  - `memorix dashboard` opens the local read-mostly dashboard.
17
17
 
18
18
  ## Memory Model
19
19
 
20
- Memorix combines three layers:
20
+ Memorix combines durable memory with a bounded task Workset:
21
21
 
22
22
  - **Observation Memory**: facts, gotchas, fixes, implementation notes, what changed
23
23
  - **Reasoning Memory**: why decisions were made, alternatives, constraints, risks
24
24
  - **Git Memory**: commit-derived engineering facts with source provenance
25
+ - **Code State**: versioned local file/symbol/import facts and freshness links that keep memory tied to the current checkout
26
+ - **Claim Ledger and Knowledge Workspace**: source-backed claims compiled into reviewable Markdown proposals, never silent overwrites
27
+ - **Canonical Workflows**: project workflows with safe per-agent adapters and recorded verification outcomes
25
28
 
26
- Search is project-scoped by default. Use global scope only when cross-project recall is intentional.
29
+ For non-trivial coding work, agents normally call `memorix_project_context` (or `memorix context --task "...")`. It selects a small task Workset with current facts, relevant evidence, start files, cautions, and verification hints instead of dumping all old text memory. Search is project-scoped by default. Use global scope only when cross-project recall is intentional.
30
+
31
+ The built-in CodeGraph Lite index is structural and intentionally not presented as a complete semantic graph. A project that already has a healthy local CodeGraph index can contribute a small validated semantic outline through `[codegraph].external_context = "auto"`; Memorix never initializes, syncs, exports, or remotely uploads that index.
27
32
 
28
33
  ## memcode
29
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.1.13",
3
+ "version": "1.2.0",
4
4
  "description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -61,6 +61,7 @@
61
61
  "test:watch": "vitest",
62
62
  "test:llm-live": "MEMORIX_RUN_LIVE_LLM_TESTS=1 vitest run tests/integration/formation-llm-quality.test.ts",
63
63
  "test:e2e": "vitest run tests/e2e/",
64
+ "benchmark:codegraph": "node scripts/benchmark-codegraph-provider.cjs",
64
65
  "lint": "tsc --noEmit",
65
66
  "prepublishOnly": "npm run build && npm test"
66
67
  },
@@ -137,7 +138,7 @@
137
138
  },
138
139
  "optionalDependencies": {
139
140
  "@huggingface/transformers": "^3.0.0",
140
- "better-sqlite3": "^11.0.0"
141
+ "better-sqlite3": "^12.11.1"
141
142
  },
142
143
  "overrides": {
143
144
  "tar": "^7.5.16",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.1.13",
3
+ "version": "1.2.0",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -6,6 +6,7 @@ export const CLI_NATIVE_PARITY: Record<string, string> = Object.freeze({
6
6
  memorix_project_context: 'memorix context',
7
7
  memorix_context_pack: 'memorix codegraph context-pack',
8
8
  memorix_codegraph_status: 'memorix codegraph status',
9
+ memorix_knowledge: 'memorix knowledge init|status|compile|lint|apply|workflow',
9
10
  memorix_resolve: 'memorix memory resolve',
10
11
  memorix_timeline: 'memorix memory timeline',
11
12
  memorix_suggest_topic_key: 'memorix memory suggest-topic-key',
@@ -1,20 +1,54 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import { CodeGraphStore } from '../../codegraph/store.js';
3
3
  import { refreshProjectLite } from '../../codegraph/lite-provider.js';
4
- import { assembleContextPackForTask, buildContextPackPrompt } from '../../codegraph/context-pack.js';
4
+ import { assembleContextPackForTask, attachTaskWorkset, buildContextPackPrompt } from '../../codegraph/context-pack.js';
5
5
  import { backfillMissingObservationCodeRefs } from '../../codegraph/binder.js';
6
+ import { collectCurrentProjectFacts } from '../../codegraph/current-facts.js';
7
+ import { resolveTaskLens } from '../../codegraph/task-lens.js';
8
+ import { getExternalCodeGraphContext, inspectExternalCodeGraph } from '../../codegraph/external-provider.js';
9
+ import type { CodeGraphProviderQuality } from '../../codegraph/types.js';
6
10
  import { getResolvedConfig } from '../../config/resolved-config.js';
7
11
  import { getAllObservations } from '../../memory/observations.js';
8
12
  import { emitError, emitResult, getCliProjectContext, parsePositiveInt } from './operator-shared.js';
9
13
 
10
- function formatStatus(status: ReturnType<CodeGraphStore['status']>): string {
14
+ function formatSnapshotStatus(status: ReturnType<CodeGraphStore['status']>): string[] {
15
+ const snapshot = status.latestSnapshot;
16
+ if (!snapshot) return ['- Code state: no completed snapshot yet'];
17
+ const revision = snapshot.baseRevision ? snapshot.baseRevision.slice(0, 12) : 'Git unavailable';
18
+ const completeness = snapshot.completeness;
19
+ const scanState = completeness.skippedOversizedFiles > 0
20
+ || (completeness.unreadableFiles ?? 0) > 0
21
+ || completeness.removalScanDeferred
22
+ ? 'incomplete'
23
+ : 'complete';
11
24
  return [
25
+ '- Code state: ' + revision
26
+ + ', ' + snapshot.worktreeState + ' worktree'
27
+ + ', ' + snapshot.changedPathCount + ' changed path(s)'
28
+ + ', epoch ' + snapshot.sourceEpoch,
29
+ '- Scan completeness: ' + scanState
30
+ + ' (' + completeness.scannedFiles + '/' + completeness.maxFiles + ' paths'
31
+ + ', ' + completeness.skippedOversizedFiles + ' oversized skipped'
32
+ + ', ' + (completeness.unreadableFiles ?? 0) + ' unreadable)',
33
+ ];
34
+ }
35
+
36
+ function formatStatus(status: ReturnType<CodeGraphStore['status']>, quality?: CodeGraphProviderQuality): string {
37
+ return [
38
+ ...formatSnapshotStatus(status),
12
39
  `CodeGraph Memory: ${status.provider}`,
13
40
  `- Files: ${status.files}`,
14
41
  `- Symbols: ${status.symbols}`,
15
42
  `- Edges: ${status.edges}`,
16
43
  `- Memory refs: ${status.refs}`,
17
44
  status.indexedAt ? `- Indexed at: ${status.indexedAt}` : '- Indexed at: never',
45
+ ...(quality
46
+ ? [
47
+ `- Persistent provider: ${status.provider} (heuristic local index)`,
48
+ `- External semantic CodeGraph: ${quality.external.state}`
49
+ + (quality.external.reason ? ` (${quality.external.reason})` : ''),
50
+ ]
51
+ : []),
18
52
  ].join('\n');
19
53
  }
20
54
 
@@ -29,6 +63,19 @@ function formatUsageHint(): string {
29
63
  ].join('\n');
30
64
  }
31
65
 
66
+ function compactFacts(project: { rootPath: string }): { facts: string[]; dirty: boolean } {
67
+ const current = collectCurrentProjectFacts({ project, now: new Date() });
68
+ const facts: string[] = [];
69
+ if (current.packageVersion) facts.push('Package version: ' + current.packageVersion);
70
+ if (current.latestChangelog) {
71
+ facts.push('Latest changelog: ' + current.latestChangelog.version
72
+ + (current.latestChangelog.date ? ' (' + current.latestChangelog.date + ')' : ''));
73
+ }
74
+ facts.push('Git: ' + (current.git.branch ? 'branch ' + current.git.branch + ', ' : '')
75
+ + (current.git.dirty ? 'dirty worktree' : 'clean worktree'));
76
+ return { facts, dirty: current.git.dirty };
77
+ }
78
+
32
79
  export default defineCommand({
33
80
  meta: {
34
81
  name: 'codegraph',
@@ -56,10 +103,16 @@ export default defineCommand({
56
103
  switch (action) {
57
104
  case 'status': {
58
105
  const status = store.status(project.id);
106
+ const providerQuality = await inspectExternalCodeGraph({
107
+ projectRoot: project.rootPath,
108
+ mode: codegraphConfig.externalContext,
109
+ command: codegraphConfig.externalCommand,
110
+ timeoutMs: codegraphConfig.externalTimeoutMs,
111
+ });
59
112
  const text = explicitAction || asJson
60
- ? formatStatus(status)
61
- : `${formatStatus(status)}\n\n${formatUsageHint()}`;
62
- emitResult({ project, status }, text, asJson);
113
+ ? formatStatus(status, providerQuality.quality)
114
+ : `${formatStatus(status, providerQuality.quality)}\n\n${formatUsageHint()}`;
115
+ emitResult({ project, status, providerQuality: providerQuality.quality }, text, asJson);
63
116
  return;
64
117
  }
65
118
 
@@ -73,12 +126,25 @@ export default defineCommand({
73
126
  const activeObservations = getAllObservations()
74
127
  .filter(obs => obs.projectId === project.id && (obs.status ?? 'active') === 'active');
75
128
  const backfill = await backfillMissingObservationCodeRefs(store, activeObservations);
129
+ const { enqueueClaimRequalification } = await import('../../runtime/lifecycle.js');
130
+ enqueueClaimRequalification({
131
+ dataDir,
132
+ projectId: project.id,
133
+ source: 'manual-codegraph-refresh',
134
+ snapshotId: refresh.snapshot.id,
135
+ });
76
136
  const status = store.status(project.id);
137
+ const providerQuality = await inspectExternalCodeGraph({
138
+ projectRoot: project.rootPath,
139
+ mode: codegraphConfig.externalContext,
140
+ command: codegraphConfig.externalCommand,
141
+ timeoutMs: codegraphConfig.externalTimeoutMs,
142
+ });
77
143
  emitResult(
78
- { project, status, refresh, backfill },
144
+ { project, status, providerQuality: providerQuality.quality, refresh, backfill },
79
145
  [
80
146
  'CodeGraph Memory refreshed.',
81
- formatStatus(status),
147
+ formatStatus(status, providerQuality.quality),
82
148
  `- Files: ${refresh.changedFiles} changed, ${refresh.unchangedFiles} unchanged, ${refresh.removedFiles} removed`,
83
149
  `- Backfilled memories: ${backfill.observationsBackfilled}`,
84
150
  `- Backfilled refs: ${backfill.refsBackfilled}`,
@@ -98,7 +164,7 @@ export default defineCommand({
98
164
  const observations = getAllObservations()
99
165
  .filter(obs => obs.projectId === project.id && (obs.status ?? 'active') === 'active')
100
166
  .reverse();
101
- const pack = assembleContextPackForTask({
167
+ const basePack = assembleContextPackForTask({
102
168
  store,
103
169
  projectId: project.id,
104
170
  task,
@@ -106,7 +172,44 @@ export default defineCommand({
106
172
  limit,
107
173
  exclude,
108
174
  });
109
- emitResult({ project, pack }, buildContextPackPrompt(pack), asJson);
175
+ const status = store.status(project.id);
176
+ const facts = compactFacts(project);
177
+ const snapshot = status.latestSnapshot;
178
+ const external = await getExternalCodeGraphContext({
179
+ projectRoot: project.rootPath,
180
+ task,
181
+ exclude,
182
+ mode: codegraphConfig.externalContext,
183
+ command: codegraphConfig.externalCommand,
184
+ timeoutMs: codegraphConfig.externalTimeoutMs,
185
+ });
186
+ const pack = await attachTaskWorkset({
187
+ pack: basePack,
188
+ projectId: project.id,
189
+ dataDir,
190
+ lens: resolveTaskLens(task).id,
191
+ worktreeDirty: facts.dirty,
192
+ currentFacts: facts.facts,
193
+ codeState: formatSnapshotStatus(status).join(' '),
194
+ ...(snapshot
195
+ ? {
196
+ snapshot: {
197
+ id: snapshot.id,
198
+ sourceEpoch: snapshot.sourceEpoch,
199
+ worktreeState: snapshot.worktreeState,
200
+ incomplete: snapshot.completeness.skippedOversizedFiles > 0
201
+ || (snapshot.completeness.unreadableFiles ?? 0) > 0
202
+ || snapshot.completeness.removalScanDeferred,
203
+ },
204
+ }
205
+ : {}),
206
+ ...(external.outline ? { semanticCode: external.outline } : {}),
207
+ providerQuality: external.quality,
208
+ ...(external.caution
209
+ ? { runtimeCautions: [{ kind: 'external-codegraph-fallback' as const, message: external.caution }] }
210
+ : {}),
211
+ });
212
+ emitResult({ project, pack, providerQuality: external.quality }, buildContextPackPrompt(pack), asJson);
110
213
  return;
111
214
  }
112
215
 
@@ -45,6 +45,8 @@ export default defineCommand({
45
45
  currentFacts: context.currentFacts,
46
46
  overview: context.overview,
47
47
  refresh: context.refresh,
48
+ providerQuality: context.providerQuality,
49
+ workset: context.workset,
48
50
  ...(context.task ? { task: context.task } : {}),
49
51
  },
50
52
  formatAutoProjectContextPrompt(context),
@@ -319,9 +319,11 @@ export default defineCommand({
319
319
  const { CodeGraphStore } = await import('../../codegraph/store.js');
320
320
  const { buildProjectContextOverview } = await import('../../codegraph/project-context.js');
321
321
  const { getResolvedConfig } = await import('../../config/resolved-config.js');
322
+ const { inspectExternalCodeGraph } = await import('../../codegraph/external-provider.js');
322
323
  const codeStore = new CodeGraphStore();
323
324
  await codeStore.init(dataDir);
324
- const exclude = getResolvedConfig({ projectRoot: projectRoot || process.cwd() }).codegraph.excludePatterns;
325
+ const codegraphConfig = getResolvedConfig({ projectRoot: projectRoot || process.cwd() }).codegraph;
326
+ const exclude = codegraphConfig.excludePatterns;
325
327
  const overview = buildProjectContextOverview({
326
328
  project: {
327
329
  id: projectId,
@@ -335,6 +337,12 @@ export default defineCommand({
335
337
  const languageText = overview.code.languages.length > 0
336
338
  ? overview.code.languages.map((item: any) => `${item.language} ${item.files}`).join(', ')
337
339
  : 'none indexed yet';
340
+ const providerQuality = await inspectExternalCodeGraph({
341
+ projectRoot: projectRoot || process.cwd(),
342
+ mode: codegraphConfig.externalContext,
343
+ command: codegraphConfig.externalCommand,
344
+ timeoutMs: codegraphConfig.externalTimeoutMs,
345
+ });
338
346
 
339
347
  if (overview.code.files > 0) {
340
348
  lines.push(ok(`Code memory: ${overview.code.files} files, ${overview.code.symbols} symbols, ${overview.code.refs} memory links`));
@@ -344,6 +352,15 @@ export default defineCommand({
344
352
  tips.push('Run `memorix codegraph refresh` once to seed project context.');
345
353
  }
346
354
 
355
+ lines.push(info(
356
+ `Code provider: Lite durable index; external semantic graph ${providerQuality.health.state}`,
357
+ ));
358
+ if (providerQuality.health.state !== 'ready'
359
+ && providerQuality.health.state !== 'not-detected'
360
+ && providerQuality.health.state !== 'disabled') {
361
+ lines.push(warn(`External CodeGraph: ${providerQuality.health.reason ?? providerQuality.health.state}`));
362
+ }
363
+
347
364
  if (overview.freshness.stale > 0 || overview.freshness.suspect > 0) {
348
365
  lines.push(warn(`Freshness: ${overview.freshness.current} current, ${overview.freshness.suspect} suspect, ${overview.freshness.stale} stale`));
349
366
  } else {
@@ -362,6 +379,7 @@ export default defineCommand({
362
379
  refs: overview.code.refs,
363
380
  languages: overview.code.languages,
364
381
  freshness: overview.freshness,
382
+ providerQuality: providerQuality.quality,
365
383
  ...(overview.code.indexedAt ? { indexedAt: overview.code.indexedAt } : {}),
366
384
  };
367
385
  } catch (e) {
@@ -373,7 +391,58 @@ export default defineCommand({
373
391
  lines.push(info('Project context unavailable without a detected project.'));
374
392
  }
375
393
 
376
- // ── 6. Conflict Check ────────────────────────────────────────
394
+ // ── 6. Knowledge Lifecycle ──────────────────────────────────
395
+ lines.push('');
396
+ lines.push('┌─ Knowledge Lifecycle ─────────────────────────────');
397
+
398
+ if (projectId && dataDir) {
399
+ try {
400
+ const { collectLifecycleDiagnostics } = await import('../../runtime/lifecycle-status.js');
401
+ const lifecycle = await collectLifecycleDiagnostics({ dataDir, projectId });
402
+ report.lifecycle = lifecycle;
403
+
404
+ const queued = lifecycle.maintenance.summary.pending + lifecycle.maintenance.summary.retrying;
405
+ const running = lifecycle.maintenance.summary.running;
406
+ if (lifecycle.maintenance.summary.failed > 0) {
407
+ lines.push(warn(`Maintenance: ${lifecycle.maintenance.summary.failed} failed job(s)`));
408
+ for (const job of lifecycle.maintenance.failedJobs) {
409
+ lines.push(info(`Failed: ${job.kind} after ${job.attempts} attempt(s)`));
410
+ }
411
+ issues.push('Knowledge maintenance has failed work. Run `memorix doctor --json` to inspect the affected job kind.');
412
+ } else if (queued > 0 || running > 0) {
413
+ lines.push(info(`Maintenance: ${queued} queued, ${running} running`));
414
+ } else {
415
+ lines.push(ok('Maintenance: idle'));
416
+ }
417
+
418
+ lines.push(info(
419
+ `Claims: ${lifecycle.claims.active} active, ${lifecycle.claims.needsReview} need review, ${lifecycle.claims.unknown} unknown`,
420
+ ));
421
+ if (lifecycle.claims.conflicts > 0) {
422
+ lines.push(warn(`Claim conflicts: ${lifecycle.claims.conflicts}`));
423
+ issues.push('Source-backed claims conflict and need review before they guide work.');
424
+ }
425
+
426
+ if (lifecycle.workspaces.length === 0) {
427
+ lines.push(info('Knowledge workspace: not initialized'));
428
+ } else {
429
+ for (const workspace of lifecycle.workspaces) {
430
+ lines.push(info(
431
+ `${workspace.mode} workspace: ${workspace.pages} pages, ${workspace.pendingProposals} pending proposal(s), ${workspace.status}`,
432
+ ));
433
+ }
434
+ }
435
+ lines.push(info(`Workflows: ${lifecycle.workflows.active}/${lifecycle.workflows.total} active, ${lifecycle.workflows.failedRuns} failed run(s)`));
436
+ } catch (e) {
437
+ const message = e instanceof Error ? e.message : String(e);
438
+ lines.push(warn(`Knowledge lifecycle unavailable: ${message}`));
439
+ report.lifecycle = { error: message };
440
+ }
441
+ } else {
442
+ lines.push(info('Knowledge lifecycle unavailable without a detected project.'));
443
+ }
444
+
445
+ // ── 7. Conflict Check ────────────────────────────────────────
377
446
  lines.push('');
378
447
  lines.push('┌─ Conflict Check ──────────────────────────────────');
379
448
 
@@ -403,7 +472,7 @@ export default defineCommand({
403
472
  }
404
473
  report.conflicts = { found: conflictsFound };
405
474
 
406
- // ── 7. LLM Status ────────────────────────────────────────────
475
+ // ── 8. LLM Status ────────────────────────────────────────────
407
476
  lines.push('');
408
477
  lines.push('┌─ LLM Enhanced Mode ───────────────────────────────');
409
478
 
@@ -427,7 +496,7 @@ export default defineCommand({
427
496
  report.llm = { enabled: false };
428
497
  }
429
498
 
430
- // ── 8. Auto-Update Status ──────────────────────────────────
499
+ // ── 9. Auto-Update Status ──────────────────────────────────
431
500
  lines.push('');
432
501
  lines.push('┌─ Auto-Update ─────────────────────────────────────');
433
502