memorix 1.2.1 → 1.2.3

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 (90) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +14 -2
  3. package/README.zh-CN.md +14 -2
  4. package/dist/cli/index.js +15424 -13780
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/index.js +1337 -536
  7. package/dist/index.js.map +1 -1
  8. package/dist/maintenance-runner.d.ts +1 -1
  9. package/dist/maintenance-runner.js +8458 -8087
  10. package/dist/maintenance-runner.js.map +1 -1
  11. package/dist/memcode-runtime/CHANGELOG.md +23 -0
  12. package/dist/sdk.d.ts +7 -2
  13. package/dist/sdk.js +1365 -542
  14. package/dist/sdk.js.map +1 -1
  15. package/dist/types.d.ts +49 -1
  16. package/dist/types.js.map +1 -1
  17. package/docs/1.2.2-MEMORY-CONTROL-PLANE.md +434 -0
  18. package/docs/AGENT_OPERATOR_PLAYBOOK.md +4 -0
  19. package/docs/API_REFERENCE.md +24 -4
  20. package/docs/README.md +1 -1
  21. package/docs/dev-log/progress.txt +101 -11
  22. package/package.json +1 -1
  23. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  24. package/src/cli/command-guide.ts +192 -0
  25. package/src/cli/commands/audit.ts +9 -4
  26. package/src/cli/commands/cleanup.ts +5 -1
  27. package/src/cli/commands/codegraph.ts +15 -5
  28. package/src/cli/commands/context.ts +3 -2
  29. package/src/cli/commands/doctor.ts +4 -2
  30. package/src/cli/commands/explain.ts +9 -3
  31. package/src/cli/commands/handoff.ts +21 -7
  32. package/src/cli/commands/identity.ts +116 -0
  33. package/src/cli/commands/ingest-image.ts +5 -3
  34. package/src/cli/commands/lock.ts +11 -10
  35. package/src/cli/commands/memory.ts +58 -21
  36. package/src/cli/commands/message.ts +19 -14
  37. package/src/cli/commands/operator-shared.ts +98 -3
  38. package/src/cli/commands/poll.ts +16 -6
  39. package/src/cli/commands/reasoning.ts +17 -3
  40. package/src/cli/commands/retention.ts +9 -4
  41. package/src/cli/commands/serve-http.ts +8 -2
  42. package/src/cli/commands/session.ts +44 -10
  43. package/src/cli/commands/skills.ts +10 -5
  44. package/src/cli/commands/status.ts +4 -3
  45. package/src/cli/commands/task.ts +26 -17
  46. package/src/cli/commands/team.ts +14 -10
  47. package/src/cli/commands/transfer.ts +63 -10
  48. package/src/cli/identity.ts +89 -0
  49. package/src/cli/index.ts +96 -19
  50. package/src/cli/invocation.ts +115 -0
  51. package/src/cli/tui/chat-service.ts +41 -18
  52. package/src/cli/tui/data.ts +23 -44
  53. package/src/cli/tui/operator-context.ts +60 -0
  54. package/src/cli/tui/session-service.ts +3 -2
  55. package/src/cli/tui/views/MemoryView.tsx +10 -8
  56. package/src/codegraph/auto-context.ts +31 -2
  57. package/src/codegraph/context-pack.ts +1 -0
  58. package/src/codegraph/project-context.ts +2 -0
  59. package/src/compact/engine.ts +26 -10
  60. package/src/compact/index-format.ts +25 -2
  61. package/src/dashboard/server.ts +46 -9
  62. package/src/hooks/admission.ts +117 -0
  63. package/src/hooks/handler.ts +98 -91
  64. package/src/knowledge/context-assembly.ts +97 -0
  65. package/src/knowledge/workset.ts +179 -10
  66. package/src/memory/admission.ts +57 -0
  67. package/src/memory/consolidation.ts +13 -2
  68. package/src/memory/disclosure-policy.ts +6 -1
  69. package/src/memory/export-import.ts +11 -3
  70. package/src/memory/graph-context.ts +8 -2
  71. package/src/memory/observations.ts +162 -4
  72. package/src/memory/quality-audit.ts +2 -0
  73. package/src/memory/retention.ts +22 -2
  74. package/src/memory/session.ts +29 -11
  75. package/src/memory/visibility.ts +80 -0
  76. package/src/orchestrate/memorix-bridge.ts +38 -0
  77. package/src/runtime/control-plane-maintenance.ts +1 -0
  78. package/src/runtime/isolated-maintenance.ts +1 -0
  79. package/src/runtime/lifecycle.ts +18 -0
  80. package/src/runtime/maintenance-jobs.ts +1 -0
  81. package/src/runtime/maintenance-runner.ts +2 -0
  82. package/src/runtime/project-maintenance.ts +89 -0
  83. package/src/sdk.ts +35 -5
  84. package/src/server.ts +267 -83
  85. package/src/store/orama-store.ts +61 -6
  86. package/src/store/sqlite-db.ts +23 -1
  87. package/src/store/sqlite-store.ts +12 -2
  88. package/src/team/handoff.ts +7 -0
  89. package/src/types.ts +51 -0
  90. package/src/wiki/generator.ts +2 -0
@@ -35,6 +35,7 @@ Use the **CLI** when:
35
35
  The current CLI namespaces are:
36
36
 
37
37
  - `memorix session`
38
+ - `memorix identity`
38
39
  - `memorix memory`
39
40
  - `memorix codegraph`
40
41
  - `memorix knowledge`
@@ -53,13 +54,16 @@ The current CLI namespaces are:
53
54
  - `memorix receipt`
54
55
  - `memorix sync`
55
56
  - `memorix ingest`
57
+ - `memorix workbench`
56
58
 
57
59
  Typical examples:
58
60
 
59
61
  ```bash
60
- memorix session start --agent codex-main --agentType codex
62
+ memorix --cwd /path/to/repo context --task "continue auth bug"
63
+ memorix identity join --agent-type codex --name codex-main
64
+ memorix session start --agent codex-main --agent-type codex --join-team --use
61
65
  memorix memory search --query "release blocker"
62
- memorix context --task "continue auth bug"
66
+ memorix memory store --text "private triage note" --visibility personal
63
67
  memorix codegraph refresh
64
68
  memorix codegraph status --json
65
69
  memorix knowledge status
@@ -70,7 +74,7 @@ memorix task claim --taskId <id> --agentId <agent-id>
70
74
  memorix message inbox --agentId <agent-id>
71
75
  memorix lock status --file src/cli/index.ts
72
76
  memorix audit project
73
- memorix transfer export --format markdown
77
+ memorix transfer export --format markdown --out ./memorix-export.md
74
78
  memorix skills show --name auth-pattern
75
79
  memorix sync workspace --action scan
76
80
  memorix ingest image --path ./diagram.png
@@ -78,7 +82,7 @@ memorix poll --agentId <agent-id>
78
82
  memorix receipt --json --probe "release blocker"
79
83
  ```
80
84
 
81
- The CLI is for direct terminal use, not a 1:1 mirror of MCP tool names. The only MCP-only area is the optional graph-compatibility tools (`create_entities`, `read_graph`, and related tools) for workflows that expect the official memory-server style graph API.
85
+ The CLI is for direct terminal use, not a 1:1 mirror of MCP tool names. It does not require an MCP connection. `--cwd` selects a Git project from any shell; an unbound terminal has project-visible access only, including transfer exports. `memorix identity join|use|clear` makes personal/team access and coordination explicit, while `--as <agent-id>` is the one-command equivalent for scripts. The only MCP-only area is the optional graph-compatibility tools (`create_entities`, `read_graph`, and related tools) for workflows that expect the official memory-server style graph API.
82
86
 
83
87
  ### Memory Autopilot, Code State, and Context Packs
84
88
 
@@ -208,6 +212,13 @@ Important inputs:
208
212
  - optional `source`
209
213
  - optional `relatedCommits`
210
214
  - optional `relatedEntities`
215
+ - optional `visibility`: `project` (default), `personal`, or `team`
216
+
217
+ Visibility controls who can retrieve a record through agent-facing memory
218
+ tools. Normal memories default to `project`. `personal` and `team` writes
219
+ require a joined coordination identity; a personal record is readable only by
220
+ its creator and explicitly named recipients. Supplying a `topicKey` never
221
+ lets an agent overwrite a record outside its write scope.
211
222
 
212
223
  Example:
213
224
 
@@ -457,6 +468,10 @@ Important inputs:
457
468
 
458
469
  Export or import project memory.
459
470
 
471
+ Exports contain only observations visible to the calling agent. An unbound
472
+ agent receives project-visible observations only; personal and team records
473
+ require its explicit active identity.
474
+
460
475
  Important inputs:
461
476
 
462
477
  - `action`
@@ -666,6 +681,11 @@ Important inputs:
666
681
 
667
682
  Use it when work should survive agent/session boundaries without relying on an IDE chat window staying alive.
668
683
 
684
+ A targeted handoff is private to its sender and recipient. A handoff without
685
+ `toAgentId` is visible only to active members of that project's team. Reading a
686
+ targeted handoff does not give its recipient permission to rewrite or resolve
687
+ it on behalf of the sender.
688
+
669
689
  ---
670
690
 
671
691
  ## 10. Ingestion Tools
package/docs/README.md CHANGED
@@ -87,7 +87,7 @@ The public docs are organized by user intent:
87
87
  | 1.2 task-shaped evidence selection | [1.2 Workset Retrieval](1.2.0-WORKSET-RETRIEVAL.md) |
88
88
  | 1.2 non-blocking refresh and maintenance contract | [1.2 Dynamic Lifecycle](1.2.0-DYNAMIC-LIFECYCLE.md) |
89
89
  | 1.2 honest Lite and optional semantic CodeGraph provider contract | [1.2 Provider Quality](1.2.0-PROVIDER-QUALITY.md) |
90
- | Active 1.2 multi-dimensional memory work | [1.2.0 Development Charter](1.2.0-DEVELOPMENT-CHARTER.md) |
90
+ | Active context-control work | [1.2.2 Memory Control Plane](1.2.2-MEMORY-CONTROL-PLANE.md) |
91
91
  | Historical cloud sync and multi-agent research | [CLOUD_SYNC_AND_MULTI_AGENT_RESEARCH.md](CLOUD_SYNC_AND_MULTI_AGENT_RESEARCH.md) |
92
92
  | Known issues and old roadmap notes | [KNOWN_ISSUES_AND_ROADMAP.md](KNOWN_ISSUES_AND_ROADMAP.md) |
93
93
 
@@ -4,15 +4,25 @@
4
4
  > older notes when they conflict.
5
5
 
6
6
  ## Current State
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.
7
+ - Phase: 1.2.3 session-context visibility hotfix
8
+ - Branch: `codex/1.2.3-session-visibility`
9
+ - Last updated: 2026-07-25
10
+ - Released baseline: `memorix@1.2.2`, tag `v1.2.2`, `origin/main` at
11
+ `2a7ebc7`.
12
+ - Goal: close the agent-facing session-context visibility boundary before
13
+ further control-plane work.
14
+
15
+ ## 1.2.3 Session Context Visibility Hotfix
16
+ - A real installed-package CLI smoke found that a second coordination identity
17
+ could receive the first identity's personal observation in automatic session
18
+ context. The root cause was a reader-less core session-context call.
19
+ - `getSessionContext()` now accepts an `ObservationReader`; CLI, MCP, and TUI
20
+ session entry points pass their resolved caller identity. Alias-backed
21
+ project-visible records remain readable, while personal/team records fail
22
+ closed.
23
+ - Graph-neighbor routing is omitted whenever a reader is present because graph
24
+ relations are not yet visibility-scoped. Core, CLI, MCP, and alias regression
25
+ tests cover the boundary.
16
26
 
17
27
  ## 1.1.13 Closeout
18
28
  - Codex setup now stamps plugin versions and doctor distinguishes bundle,
@@ -102,7 +112,7 @@
102
112
  - The compiled CLI was smoke-tested in an isolated Git project through init,
103
113
  compile, apply, and lint with a source-backed claim.
104
114
 
105
- ## 1.2 Delivery Complete, Release Checks In Progress
115
+ ## 1.2 Delivery Complete, Released As 1.2.1
106
116
  - Phase 4 added canonical Markdown workflows, safe adapter preview/apply, import,
107
117
  selection, and verification receipts. Agent instruction files are render
108
118
  targets, not the workflow source of truth.
@@ -123,4 +133,84 @@
123
133
  - Release audit also incorporated #130 before publication: the optional SQLite
124
134
  runtime now uses the Node-26-compatible `better-sqlite3` 12.x line, with a
125
135
  dedicated Node 26 CI smoke that opens an in-memory database.
126
- - Remaining remote gates: GitHub CI, npm publish, tag, and GitHub release.
136
+ - The release was completed as `memorix@1.2.1`. Its next development line is
137
+ [1.2.2 Memory Control Plane](../1.2.2-MEMORY-CONTROL-PLANE.md), which
138
+ consolidates these capabilities instead of adding another disconnected
139
+ memory feature.
140
+
141
+ ## 1.2.2 Control Plane
142
+ - `TaskWorkset` already has bounded rendering and source-aware claims, but
143
+ SessionStart handoff and legacy context surfaces need one shared admission,
144
+ budget, and receipt contract.
145
+ - First implementation slice complete: the shared `ContextReceipt` records
146
+ delivery target, selected source ids/kinds, trust/freshness, exact budget
147
+ omissions, queued refreshes, and Workset selection time without entering the
148
+ agent prompt. Project Context, Context Pack, and full SessionStart injection
149
+ now carry the same delivery-target semantics; `memorix explain` exposes the
150
+ receipt in text and JSON.
151
+ - Budget selection now keeps a knowledge page dependent on a Claim out of the
152
+ prompt when its qualifying Claim could not fit. The receipt records both as
153
+ withheld instead of presenting an orphaned page path as usable knowledge.
154
+ - Phase 3 admission slice complete: automatic observations now persist an
155
+ `ephemeral`, `candidate`, or `qualified` state and a reason. Hooks and the
156
+ internal orchestrator capture concrete evidence as candidates, keep routine
157
+ success/telemetry ephemeral, and drop low-signal activity without writing it.
158
+ Automatic capture stays quiet in the host agent.
159
+ - A deduplicated `observation-qualify` maintenance job runs after CodeGraph
160
+ refresh. It requires a scan no older than the capture and at least one
161
+ current code reference before upgrading a candidate. Qualification does not
162
+ create a Claim; explicit saves and Git remain the Claim boundary.
163
+ - Auto Project Context, automatic session L1 delivery, Wiki/Knowledge Graph
164
+ compilation, and graph-context packets exclude candidates and ephemeral
165
+ traces. Ordinary search prefers qualified material, while explicit lookup
166
+ can still inspect pending evidence.
167
+ - Pending automatic evidence is also excluded from automatic consolidation so
168
+ a later qualification can still inspect its original source grain. Retention
169
+ explanations no longer describe an unqualified `core` candidate as immune.
170
+ - Actor and visibility enforcement is now one policy shared by MCP retrieval,
171
+ auto context, CLI/TUI, dashboards, knowledge/graph projections, and scoped
172
+ maintenance. Legacy observations remain project-visible; new records may be
173
+ `project`, `team`, or `personal` with an explicit creator and recipients.
174
+ Missing identity never grants private or team visibility.
175
+ - Automatic hooks and orchestrator traces begin personal. A verified hook
176
+ candidate may become project evidence only when qualification proves a
177
+ current code reference. Targeted handoffs are readable by sender and
178
+ recipient but writable only by sender; broadcasts require an active project
179
+ team member.
180
+ - Automatic orchestration lesson lookup is explicitly project-scoped, so its
181
+ prompt injection cannot read personal or team-scoped records.
182
+ - Topic-key writes now check mutation scope before storage, and the
183
+ project-attribution guard receives only memories visible to its current
184
+ reader. This closes both guessed-key overwrite and cross-project existence
185
+ hints without hiding historical project knowledge after upgrade.
186
+ - The embedded SDK remains project-visible when unbound. CLI and the local TUI
187
+ now share the same explicit actor reader: an unbound terminal sees project
188
+ memory only, while `memorix identity join|use` (or one-shot `--as`) grants
189
+ only that active project member's personal/team visibility and coordination
190
+ ergonomics. `identity clear` returns to project scope; private evidence
191
+ cannot be promoted into shared skills or generated project skills.
192
+ - CLI control-plane ergonomics now include `--cwd`, kebab-case flag aliases,
193
+ action-oriented namespace help, explicit `memorix workbench`, and
194
+ file/stdin transfer import/export. Root memory aliases use the same
195
+ canonical command paths as `memorix memory`; CLI and MCP exports are filtered
196
+ by the same active reader so an unbound backup cannot contain private/team
197
+ observations.
198
+ - Direct CLI and foreground Code Memory refreshes now enqueue qualification as
199
+ well as claim requalification, and they register the local project target
200
+ needed by the isolated control-plane worker. The host hook path persists its
201
+ candidate before scheduling a refresh, avoiding a fast-worker race where a
202
+ scan could predate the capture.
203
+ - Compiled-artifact smoke: an isolated Codex `PostToolUse` hook returned only
204
+ `continue: true`, stored a `candidate`, and the isolated background control
205
+ plane upgraded it to `qualified` after a real Code Memory scan with one
206
+ current reference. Embeddings were deliberately disabled for this
207
+ deterministic local smoke. The full test suite, TypeScript check, and
208
+ production build also passed after the admission policy was reconciled with
209
+ OpenCode's concise technical response events.
210
+ - #135 remains a contributor-owned session-handoff candidate for the bounded
211
+ `HandoffPacket` phase. It is not copied or silently replaced.
212
+ - #133/#134 remain open pending an official provider-capability layer and a
213
+ safe agent-facing media path. The existing OpenRouter text embedding path is
214
+ the supported baseline.
215
+ - See [1.2.2 Memory Control Plane](../1.2.2-MEMORY-CONTROL-PLANE.md) for
216
+ phases, acceptance gates, non-goals, and release criteria.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
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,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -0,0 +1,192 @@
1
+ export interface CliCommandGuide {
2
+ summary: string;
3
+ usage: string[];
4
+ notes?: string[];
5
+ }
6
+
7
+ const GUIDES: Record<string, CliCommandGuide> = {
8
+ memory: {
9
+ summary: 'Store, search, inspect, resolve, consolidate, and promote project memory.',
10
+ usage: [
11
+ 'memorix memory search --query "timeout regression" [--limit 10]',
12
+ 'memorix memory store --text "..." [--title "..."] [--visibility project|personal|team]',
13
+ 'memorix memory detail --id 42',
14
+ 'memorix memory recent [--limit 10]',
15
+ 'memorix memory resolve --ids 42,43 [--status resolved|archived]',
16
+ 'memorix memory consolidate --action preview|execute',
17
+ 'memorix memory promote --ids 42,43 [--trigger "..."] [--instruction "..."]',
18
+ ],
19
+ notes: ['Personal and team visibility require `memorix identity join` or `memorix identity use` first.'],
20
+ },
21
+ identity: {
22
+ summary: 'Select the active local actor for private memory and coordination commands.',
23
+ usage: [
24
+ 'memorix identity status',
25
+ 'memorix identity join --agent-type codex [--name codex-main --instance-id local]',
26
+ 'memorix identity use --agent-id <id>',
27
+ 'memorix identity clear',
28
+ ],
29
+ notes: ['Without an identity, CLI reads and writes only project-visible memory.'],
30
+ },
31
+ session: {
32
+ summary: 'Start, end, and inspect coding sessions. Coordination remains opt-in.',
33
+ usage: [
34
+ 'memorix session start --agent codex',
35
+ 'memorix session start --agent codex --agent-type codex --join-team --use',
36
+ 'memorix session end --session-id <id> [--summary "..."]',
37
+ 'memorix session context [--limit 3]',
38
+ ],
39
+ },
40
+ context: {
41
+ summary: 'Build the bounded task Workset used to resume or begin real work.',
42
+ usage: ['memorix context --task "continue the release fix" [--refresh auto|always|never]'],
43
+ },
44
+ explain: {
45
+ summary: 'Show why a task context contains its current facts and memory evidence.',
46
+ usage: ['memorix explain [--refresh auto|always|never]'],
47
+ },
48
+ codegraph: {
49
+ summary: 'Refresh local code-state snapshots and assemble task-specific code context.',
50
+ usage: [
51
+ 'memorix codegraph status',
52
+ 'memorix codegraph refresh',
53
+ 'memorix codegraph context-pack --task "trace the auth flow" [--limit 20]',
54
+ ],
55
+ },
56
+ knowledge: {
57
+ summary: 'Manage the reviewed, source-backed Knowledge Workspace and project workflows.',
58
+ usage: [
59
+ 'memorix knowledge init [--mode local|versioned]',
60
+ 'memorix knowledge status',
61
+ 'memorix knowledge compile',
62
+ 'memorix knowledge lint',
63
+ 'memorix knowledge workflow list',
64
+ ],
65
+ },
66
+ reasoning: {
67
+ summary: 'Capture and retrieve engineering decision rationale.',
68
+ usage: [
69
+ 'memorix reasoning store --entity auth --decision "Use SQLite" --rationale "..."',
70
+ 'memorix reasoning search --query "why sqlite" [--scope project|global]',
71
+ ],
72
+ },
73
+ retention: {
74
+ summary: 'Inspect retention state and archive records that are eligible under the current scope.',
75
+ usage: [
76
+ 'memorix retention status',
77
+ 'memorix retention stale',
78
+ 'memorix retention archive',
79
+ ],
80
+ },
81
+ transfer: {
82
+ summary: 'Create or restore explicit project memory snapshots for backup and automation.',
83
+ usage: [
84
+ 'memorix transfer export --format json --out ./.memorix-export.json',
85
+ 'memorix transfer import --file ./.memorix-export.json',
86
+ 'memorix transfer import --stdin',
87
+ ],
88
+ },
89
+ team: {
90
+ summary: 'Manage explicit multi-agent coordination state for the current project.',
91
+ usage: [
92
+ 'memorix team join --agent-type codex [--name codex-main]',
93
+ 'memorix team status [--all]',
94
+ 'memorix team leave [--agent-id <id>]',
95
+ ],
96
+ },
97
+ task: {
98
+ summary: 'Create and progress coordination tasks. An active CLI identity fills agentId automatically.',
99
+ usage: [
100
+ 'memorix task create --description "Review release evidence"',
101
+ 'memorix task claim --task-id <id>',
102
+ 'memorix task complete --task-id <id> --result "Verified"',
103
+ 'memorix task list [--available]',
104
+ ],
105
+ },
106
+ message: {
107
+ summary: 'Send and read coordination messages. An active CLI identity fills the sender automatically.',
108
+ usage: [
109
+ 'memorix message send --to <agent-id> --type info --content "..."',
110
+ 'memorix message broadcast --type announcement --content "..."',
111
+ 'memorix message inbox [--mark-read]',
112
+ ],
113
+ },
114
+ lock: {
115
+ summary: 'Use advisory file locks to reduce overlapping edits between agents.',
116
+ usage: [
117
+ 'memorix lock lock --file src/server.ts',
118
+ 'memorix lock unlock --file src/server.ts',
119
+ 'memorix lock status [--file src/server.ts]',
120
+ ],
121
+ },
122
+ handoff: {
123
+ summary: 'Create durable, targeted or team-visible handoff artifacts.',
124
+ usage: ['memorix handoff send --summary "..." --context "..." [--to-agent-id <id>]'],
125
+ },
126
+ poll: {
127
+ summary: 'Return a compact coordination snapshot for the active CLI identity.',
128
+ usage: ['memorix poll [--mark-inbox-read]'],
129
+ },
130
+ audit: {
131
+ summary: 'Inspect quality, attribution, and recorded audit evidence.',
132
+ usage: ['memorix audit memory', 'memorix audit project [--threshold 2]', 'memorix audit list'],
133
+ },
134
+ skills: {
135
+ summary: 'Inspect and generate project skills from project-visible memory evidence.',
136
+ usage: ['memorix skills list', 'memorix skills generate [--write --target codex]', 'memorix skills show --name <skill>'],
137
+ },
138
+ sync: {
139
+ summary: 'Synchronize agent rules and workspace artifacts through explicit routes.',
140
+ usage: ['memorix sync rules --action status', 'memorix sync workspace --action scan'],
141
+ },
142
+ ingest: {
143
+ summary: 'Ingest Git and image evidence into project memory.',
144
+ usage: ['memorix ingest commit [--ref HEAD]', 'memorix ingest log [--count 10]', 'memorix ingest image --path ./diagram.png'],
145
+ },
146
+ workbench: {
147
+ summary: 'Open the interactive terminal memory control plane.',
148
+ usage: ['memorix workbench'],
149
+ },
150
+ };
151
+
152
+ export function commandGuideNames(): string[] {
153
+ return Object.keys(GUIDES).sort();
154
+ }
155
+
156
+ export function renderCliGuide(command?: string): string {
157
+ const normalized = command?.trim().toLowerCase();
158
+ if (normalized && GUIDES[normalized]) {
159
+ const guide = GUIDES[normalized];
160
+ return [
161
+ `Memorix ${normalized}`,
162
+ '',
163
+ guide.summary,
164
+ '',
165
+ 'Usage:',
166
+ ...guide.usage.map((line) => ` ${line}`),
167
+ ...(guide.notes?.length ? ['', ...guide.notes.map((line) => `Note: ${line}`)] : []),
168
+ '',
169
+ 'Project/actor options: --cwd <git-project> --as <active-agent-id>. Operator commands accept --json.',
170
+ ].join('\n');
171
+ }
172
+
173
+ return [
174
+ 'Memorix CLI',
175
+ '',
176
+ 'Use `memorix <command> --help` for an action-oriented guide.',
177
+ '',
178
+ `Command groups: ${commandGuideNames().join(', ')}`,
179
+ '',
180
+ 'Global options: --cwd <git-project> --as <active-agent-id>',
181
+ 'Compatibility: camelCase flags remain supported; kebab-case flags are accepted too.',
182
+ ].join('\n');
183
+ }
184
+
185
+ /** Render manual action help before Citty consumes `--help` as flag metadata. */
186
+ export function printCliGuideForHelp(argv: string[] = process.argv.slice(2)): boolean {
187
+ const [command, ...rest] = argv;
188
+ if (!command || !GUIDES[command.toLowerCase()]) return false;
189
+ if (!rest.includes('--help') && !rest.includes('-h')) return false;
190
+ console.log(renderCliGuide(command));
191
+ return true;
192
+ }
@@ -3,6 +3,7 @@ import { getAllAuditEntries, getProjectId } from '../../audit/index.js';
3
3
  import { auditProjectObservations } from '../../memory/attribution-guard.js';
4
4
  import { getAllObservations } from '../../memory/observations.js';
5
5
  import { auditMemoryQuality } from '../../memory/quality-audit.js';
6
+ import { filterReadableObservations } from '../../memory/visibility.js';
6
7
  import { emitError, emitResult, getCliProjectContext } from './operator-shared.js';
7
8
 
8
9
  export default defineCommand({
@@ -22,8 +23,8 @@ export default defineCommand({
22
23
  try {
23
24
  switch (action) {
24
25
  case 'memory': {
25
- const { project } = await getCliProjectContext();
26
- const report = auditMemoryQuality(getAllObservations(), {
26
+ const { project, reader } = await getCliProjectContext();
27
+ const report = auditMemoryQuality(filterReadableObservations(getAllObservations(), reader), {
27
28
  projectId: project.id,
28
29
  });
29
30
  emitResult(
@@ -68,9 +69,13 @@ export default defineCommand({
68
69
  }
69
70
 
70
71
  case 'project': {
71
- const { project } = await getCliProjectContext();
72
+ const { project, reader } = await getCliProjectContext();
72
73
  const threshold = Number.parseInt(String(args.threshold ?? '2'), 10) || 2;
73
- const entries = await auditProjectObservations(project.id, getAllObservations(), threshold);
74
+ const entries = await auditProjectObservations(
75
+ project.id,
76
+ filterReadableObservations(getAllObservations(), reader),
77
+ threshold,
78
+ );
74
79
  emitResult(
75
80
  { project, entries, threshold },
76
81
  entries.length === 0
@@ -19,6 +19,7 @@ import { detectProject } from '../../project/detector.js';
19
19
  import { getProjectDataDir } from '../../store/persistence.js';
20
20
  import type { ObservationStore } from '../../store/obs-store.js';
21
21
  import { getObservationStore, initObservationStore } from '../../store/obs-store.js';
22
+ import { filterReadableObservations } from '../../memory/visibility.js';
22
23
 
23
24
  /** Patterns that indicate auto-generated, low-value observations */
24
25
  const LOW_QUALITY_PATTERNS = [
@@ -148,7 +149,10 @@ export default defineCommand({
148
149
  const dataDir = await getProjectDataDir(projectId);
149
150
  await initObservationStore(dataDir);
150
151
  const store = getObservationStore();
151
- const projectObs = await store.loadByProject(projectId, { status: 'active' }) as Array<{
152
+ const projectObs = filterReadableObservations(
153
+ await store.loadByProject(projectId, { status: 'active' }),
154
+ { projectId },
155
+ ) as Array<{
152
156
  id?: number;
153
157
  type?: string;
154
158
  title?: string;
@@ -9,6 +9,7 @@ import { getExternalCodeGraphContext, inspectExternalCodeGraph } from '../../cod
9
9
  import type { CodeGraphProviderQuality } from '../../codegraph/types.js';
10
10
  import { getResolvedConfig } from '../../config/resolved-config.js';
11
11
  import { getAllObservations } from '../../memory/observations.js';
12
+ import { filterReadableObservations } from '../../memory/visibility.js';
12
13
  import { emitError, emitResult, getCliProjectContext, parsePositiveInt } from './operator-shared.js';
13
14
 
14
15
  function formatSnapshotStatus(status: ReturnType<CodeGraphStore['status']>): string[] {
@@ -92,7 +93,7 @@ export default defineCommand({
92
93
  const asJson = !!args.json;
93
94
 
94
95
  try {
95
- const { project, dataDir } = await getCliProjectContext();
96
+ const { project, dataDir, reader } = await getCliProjectContext();
96
97
  const store = new CodeGraphStore();
97
98
  await store.init(dataDir);
98
99
  const explicitAction = Boolean(positional[0] || (args.action as string | undefined));
@@ -125,13 +126,21 @@ export default defineCommand({
125
126
  const activeObservations = getAllObservations()
126
127
  .filter(obs => obs.projectId === project.id && (obs.status ?? 'active') === 'active');
127
128
  const backfill = await backfillMissingObservationCodeRefs(store, activeObservations);
128
- const { enqueueClaimRequalification } = await import('../../runtime/lifecycle.js');
129
+ const {
130
+ enqueueClaimRequalification,
131
+ enqueueObservationQualification,
132
+ } = await import('../../runtime/lifecycle.js');
129
133
  enqueueClaimRequalification({
130
134
  dataDir,
131
135
  projectId: project.id,
132
136
  source: 'manual-codegraph-refresh',
133
137
  snapshotId: refresh.snapshot.id,
134
138
  });
139
+ enqueueObservationQualification({
140
+ dataDir,
141
+ projectId: project.id,
142
+ source: 'manual-codegraph-refresh',
143
+ });
135
144
  const status = store.status(project.id);
136
145
  const providerQuality = await inspectExternalCodeGraph({
137
146
  projectRoot: project.rootPath,
@@ -160,9 +169,10 @@ export default defineCommand({
160
169
  return;
161
170
  }
162
171
  const limit = parsePositiveInt(args.limit as string | undefined, 20);
163
- const observations = getAllObservations()
164
- .filter(obs => obs.projectId === project.id && (obs.status ?? 'active') === 'active')
165
- .reverse();
172
+ const observations = filterReadableObservations(
173
+ getAllObservations().filter(obs => obs.projectId === project.id && (obs.status ?? 'active') === 'active'),
174
+ reader,
175
+ ).reverse();
166
176
  const basePack = assembleContextPackForTask({
167
177
  store,
168
178
  projectId: project.id,
@@ -6,6 +6,7 @@ import {
6
6
  type AutoContextRefreshMode,
7
7
  } from '../../codegraph/auto-context.js';
8
8
  import { getAllObservations } from '../../memory/observations.js';
9
+ import { filterReadableObservations } from '../../memory/visibility.js';
9
10
  import { emitError, emitResult, getCliProjectContext } from './operator-shared.js';
10
11
 
11
12
  function coerceRefreshMode(input?: string): AutoContextRefreshMode {
@@ -28,11 +29,11 @@ export default defineCommand({
28
29
  const asJson = !!args.json;
29
30
 
30
31
  try {
31
- const { project, dataDir } = await getCliProjectContext();
32
+ const { project, dataDir, reader } = await getCliProjectContext();
32
33
  const context = await buildAutoProjectContext({
33
34
  project,
34
35
  dataDir,
35
- observations: getAllObservations(),
36
+ observations: filterReadableObservations(getAllObservations(), reader),
36
37
  task: args.task as string | undefined,
37
38
  refresh: coerceRefreshMode(args.refresh as string | undefined),
38
39
  });
@@ -257,8 +257,10 @@ export default defineCommand({
257
257
  await initObservationStore(dataDir);
258
258
  const store = getObservationStore();
259
259
  backendName = store.getBackendName();
260
- const obs = await store.loadAll();
261
- projectObservations = obs.filter((o: any) => o.projectId === projectId);
260
+ const { filterReadableObservations } = await import('../../memory/visibility.js');
261
+ projectObservations = projectId
262
+ ? filterReadableObservations(await store.loadAll(), { projectId })
263
+ : [];
262
264
  obsCount = projectObservations.length;
263
265
  activeCount = projectObservations.filter((o: any) => (o.status ?? 'active') === 'active').length;
264
266
  ranCount = projectObservations.filter((o: any) => /^Ran:\s/i.test(o.title ?? '')).length;
@@ -1,7 +1,9 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import { buildAutoProjectContext, type AutoContextRefreshMode } from '../../codegraph/auto-context.js';
3
3
  import { formatProjectContextExplain } from '../../codegraph/project-context.js';
4
+ import { formatContextReceipt } from '../../knowledge/context-assembly.js';
4
5
  import { getAllObservations } from '../../memory/observations.js';
6
+ import { filterReadableObservations } from '../../memory/visibility.js';
5
7
  import { emitError, emitResult, getCliProjectContext } from './operator-shared.js';
6
8
 
7
9
  function coerceRefreshMode(input?: string): AutoContextRefreshMode {
@@ -23,15 +25,19 @@ export default defineCommand({
23
25
  const asJson = !!args.json;
24
26
 
25
27
  try {
26
- const { project, dataDir } = await getCliProjectContext();
28
+ const { project, dataDir, reader } = await getCliProjectContext();
27
29
  const context = await buildAutoProjectContext({
28
30
  project,
29
31
  dataDir,
30
- observations: getAllObservations(),
32
+ observations: filterReadableObservations(getAllObservations(), reader),
31
33
  refresh: coerceRefreshMode(args.refresh as string | undefined),
32
34
  });
33
35
 
34
- emitResult({ project, explain: context.explain, refresh: context.refresh }, formatProjectContextExplain(context.explain), asJson);
36
+ emitResult(
37
+ { project, explain: context.explain, receipt: context.workset.receipt, refresh: context.refresh },
38
+ formatProjectContextExplain(context.explain) + '\n\n' + formatContextReceipt(context.workset.receipt),
39
+ asJson,
40
+ );
35
41
  } catch (error) {
36
42
  emitError(error instanceof Error ? error.message : String(error), asJson);
37
43
  }