memorix 1.2.1 → 1.2.2
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 +16 -0
- package/README.md +14 -2
- package/README.zh-CN.md +14 -2
- package/TEAM.md +86 -86
- package/dist/cli/index.js +15407 -13779
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1321 -529
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +8458 -8087
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +16 -0
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +1349 -535
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +49 -1
- package/dist/types.js.map +1 -1
- package/docs/1.2.2-MEMORY-CONTROL-PLANE.md +434 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +4 -0
- package/docs/API_REFERENCE.md +24 -4
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/README.md +1 -1
- package/docs/dev-log/progress.txt +91 -11
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/audit/index.ts +156 -156
- package/src/cli/command-guide.ts +192 -0
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/audit.ts +9 -4
- package/src/cli/commands/background.ts +659 -659
- package/src/cli/commands/cleanup.ts +5 -1
- package/src/cli/commands/codegraph.ts +15 -5
- package/src/cli/commands/context.ts +3 -2
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/explain.ts +9 -3
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +75 -61
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/identity.ts +116 -0
- package/src/cli/commands/ingest-commit.ts +153 -153
- package/src/cli/commands/ingest-image.ts +71 -69
- package/src/cli/commands/ingest-log.ts +180 -180
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +93 -92
- package/src/cli/commands/memory.ts +58 -21
- package/src/cli/commands/message.ts +123 -118
- package/src/cli/commands/operator-shared.ts +98 -3
- package/src/cli/commands/poll.ts +74 -64
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +135 -121
- package/src/cli/commands/retention.ts +9 -4
- package/src/cli/commands/serve-http.ts +8 -2
- package/src/cli/commands/serve-shared.ts +118 -118
- package/src/cli/commands/session.ts +29 -3
- package/src/cli/commands/skills.ts +124 -119
- package/src/cli/commands/status.ts +4 -3
- package/src/cli/commands/task.ts +193 -184
- package/src/cli/commands/team.ts +14 -10
- package/src/cli/commands/transfer.ts +108 -55
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/identity.ts +89 -0
- package/src/cli/index.ts +96 -19
- package/src/cli/invocation.ts +115 -0
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/chat-service.ts +41 -18
- package/src/cli/tui/data.ts +23 -44
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/operator-context.ts +60 -0
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/tui/views/MemoryView.tsx +10 -8
- package/src/cli/update-checker.ts +211 -211
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/codegraph/auto-context.ts +31 -2
- package/src/codegraph/context-pack.ts +1 -0
- package/src/codegraph/project-context.ts +2 -0
- package/src/compact/engine.ts +26 -10
- package/src/compact/index-format.ts +25 -2
- package/src/compact/token-budget.ts +74 -74
- package/src/dashboard/project-classification.ts +64 -64
- package/src/dashboard/server.ts +46 -9
- package/src/embedding/fastembed-provider.ts +142 -142
- package/src/embedding/transformers-provider.ts +111 -111
- package/src/git/extractor.ts +209 -209
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/admission.ts +117 -0
- package/src/hooks/handler.ts +98 -91
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/knowledge/context-assembly.ts +97 -0
- package/src/knowledge/workset.ts +179 -10
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/memory/admission.ts +57 -0
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/consolidation.ts +13 -2
- package/src/memory/disclosure-policy.ts +140 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/export-import.ts +11 -3
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph-context.ts +8 -2
- package/src/memory/graph.ts +197 -197
- package/src/memory/observations.ts +162 -4
- package/src/memory/quality-audit.ts +2 -0
- package/src/memory/refs.ts +94 -94
- package/src/memory/retention.ts +22 -2
- package/src/memory/secret-filter.ts +79 -79
- package/src/memory/session.ts +5 -2
- package/src/memory/visibility.ts +80 -0
- package/src/multimodal/image-loader.ts +143 -143
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/spawn-helper.ts +286 -286
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +378 -340
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/orchestrate/worktree.ts +232 -232
- package/src/project/aliases.ts +374 -374
- package/src/project/detector.ts +268 -268
- package/src/rules/adapters/claude-code.ts +99 -99
- package/src/rules/adapters/codex.ts +97 -97
- package/src/rules/adapters/copilot.ts +124 -124
- package/src/rules/adapters/cursor.ts +114 -114
- package/src/rules/adapters/kiro.ts +126 -126
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/adapters/windsurf.ts +83 -83
- package/src/rules/syncer.ts +235 -235
- package/src/runtime/control-plane-maintenance.ts +1 -0
- package/src/runtime/isolated-maintenance.ts +1 -0
- package/src/runtime/lifecycle.ts +18 -0
- package/src/runtime/maintenance-jobs.ts +1 -0
- package/src/runtime/maintenance-runner.ts +2 -0
- package/src/runtime/project-maintenance.ts +89 -0
- package/src/sdk.ts +334 -304
- package/src/search/intent-detector.ts +289 -289
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +260 -81
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/orama-store.ts +61 -6
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/store/sqlite-db.ts +23 -1
- package/src/store/sqlite-store.ts +12 -2
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +168 -161
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/types.ts +51 -0
- package/src/wiki/generator.ts +2 -0
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/src/workspace/workflow-sync.ts +131 -131
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
|
|
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,15 @@
|
|
|
4
4
|
> older notes when they conflict.
|
|
5
5
|
|
|
6
6
|
## Current State
|
|
7
|
-
- Phase: 1.2
|
|
8
|
-
- Branch: `codex/1.2.
|
|
9
|
-
- Last updated: 2026-07-
|
|
10
|
-
- Released baseline: `memorix@1.1
|
|
11
|
-
`
|
|
12
|
-
- Goal:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
- Phase: 1.2.2 memory-control-plane admission and visibility implementation
|
|
8
|
+
- Branch: `codex/1.2.2-memory-control-plane`
|
|
9
|
+
- Last updated: 2026-07-25
|
|
10
|
+
- Released baseline: `memorix@1.2.1`, tag `v1.2.1`, `origin/main` at
|
|
11
|
+
`1b5bf7f`.
|
|
12
|
+
- Goal: make the 1.2 multi-dimensional evidence layer behave as one bounded,
|
|
13
|
+
explainable control plane. A task Workset, hook handoff, lifecycle refresh,
|
|
14
|
+
and provider capability result must share evidence qualification, delivery
|
|
15
|
+
budgets, and privacy-safe receipts.
|
|
16
16
|
|
|
17
17
|
## 1.1.13 Closeout
|
|
18
18
|
- Codex setup now stamps plugin versions and doctor distinguishes bundle,
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
- The compiled CLI was smoke-tested in an isolated Git project through init,
|
|
103
103
|
compile, apply, and lint with a source-backed claim.
|
|
104
104
|
|
|
105
|
-
## 1.2 Delivery Complete,
|
|
105
|
+
## 1.2 Delivery Complete, Released As 1.2.1
|
|
106
106
|
- Phase 4 added canonical Markdown workflows, safe adapter preview/apply, import,
|
|
107
107
|
selection, and verification receipts. Agent instruction files are render
|
|
108
108
|
targets, not the workflow source of truth.
|
|
@@ -123,4 +123,84 @@
|
|
|
123
123
|
- Release audit also incorporated #130 before publication: the optional SQLite
|
|
124
124
|
runtime now uses the Node-26-compatible `better-sqlite3` 12.x line, with a
|
|
125
125
|
dedicated Node 26 CI smoke that opens an in-memory database.
|
|
126
|
-
-
|
|
126
|
+
- The release was completed as `memorix@1.2.1`. Its next development line is
|
|
127
|
+
[1.2.2 Memory Control Plane](../1.2.2-MEMORY-CONTROL-PLANE.md), which
|
|
128
|
+
consolidates these capabilities instead of adding another disconnected
|
|
129
|
+
memory feature.
|
|
130
|
+
|
|
131
|
+
## 1.2.2 Control Plane
|
|
132
|
+
- `TaskWorkset` already has bounded rendering and source-aware claims, but
|
|
133
|
+
SessionStart handoff and legacy context surfaces need one shared admission,
|
|
134
|
+
budget, and receipt contract.
|
|
135
|
+
- First implementation slice complete: the shared `ContextReceipt` records
|
|
136
|
+
delivery target, selected source ids/kinds, trust/freshness, exact budget
|
|
137
|
+
omissions, queued refreshes, and Workset selection time without entering the
|
|
138
|
+
agent prompt. Project Context, Context Pack, and full SessionStart injection
|
|
139
|
+
now carry the same delivery-target semantics; `memorix explain` exposes the
|
|
140
|
+
receipt in text and JSON.
|
|
141
|
+
- Budget selection now keeps a knowledge page dependent on a Claim out of the
|
|
142
|
+
prompt when its qualifying Claim could not fit. The receipt records both as
|
|
143
|
+
withheld instead of presenting an orphaned page path as usable knowledge.
|
|
144
|
+
- Phase 3 admission slice complete: automatic observations now persist an
|
|
145
|
+
`ephemeral`, `candidate`, or `qualified` state and a reason. Hooks and the
|
|
146
|
+
internal orchestrator capture concrete evidence as candidates, keep routine
|
|
147
|
+
success/telemetry ephemeral, and drop low-signal activity without writing it.
|
|
148
|
+
Automatic capture stays quiet in the host agent.
|
|
149
|
+
- A deduplicated `observation-qualify` maintenance job runs after CodeGraph
|
|
150
|
+
refresh. It requires a scan no older than the capture and at least one
|
|
151
|
+
current code reference before upgrading a candidate. Qualification does not
|
|
152
|
+
create a Claim; explicit saves and Git remain the Claim boundary.
|
|
153
|
+
- Auto Project Context, automatic session L1 delivery, Wiki/Knowledge Graph
|
|
154
|
+
compilation, and graph-context packets exclude candidates and ephemeral
|
|
155
|
+
traces. Ordinary search prefers qualified material, while explicit lookup
|
|
156
|
+
can still inspect pending evidence.
|
|
157
|
+
- Pending automatic evidence is also excluded from automatic consolidation so
|
|
158
|
+
a later qualification can still inspect its original source grain. Retention
|
|
159
|
+
explanations no longer describe an unqualified `core` candidate as immune.
|
|
160
|
+
- Actor and visibility enforcement is now one policy shared by MCP retrieval,
|
|
161
|
+
auto context, CLI/TUI, dashboards, knowledge/graph projections, and scoped
|
|
162
|
+
maintenance. Legacy observations remain project-visible; new records may be
|
|
163
|
+
`project`, `team`, or `personal` with an explicit creator and recipients.
|
|
164
|
+
Missing identity never grants private or team visibility.
|
|
165
|
+
- Automatic hooks and orchestrator traces begin personal. A verified hook
|
|
166
|
+
candidate may become project evidence only when qualification proves a
|
|
167
|
+
current code reference. Targeted handoffs are readable by sender and
|
|
168
|
+
recipient but writable only by sender; broadcasts require an active project
|
|
169
|
+
team member.
|
|
170
|
+
- Automatic orchestration lesson lookup is explicitly project-scoped, so its
|
|
171
|
+
prompt injection cannot read personal or team-scoped records.
|
|
172
|
+
- Topic-key writes now check mutation scope before storage, and the
|
|
173
|
+
project-attribution guard receives only memories visible to its current
|
|
174
|
+
reader. This closes both guessed-key overwrite and cross-project existence
|
|
175
|
+
hints without hiding historical project knowledge after upgrade.
|
|
176
|
+
- The embedded SDK remains project-visible when unbound. CLI and the local TUI
|
|
177
|
+
now share the same explicit actor reader: an unbound terminal sees project
|
|
178
|
+
memory only, while `memorix identity join|use` (or one-shot `--as`) grants
|
|
179
|
+
only that active project member's personal/team visibility and coordination
|
|
180
|
+
ergonomics. `identity clear` returns to project scope; private evidence
|
|
181
|
+
cannot be promoted into shared skills or generated project skills.
|
|
182
|
+
- CLI control-plane ergonomics now include `--cwd`, kebab-case flag aliases,
|
|
183
|
+
action-oriented namespace help, explicit `memorix workbench`, and
|
|
184
|
+
file/stdin transfer import/export. Root memory aliases use the same
|
|
185
|
+
canonical command paths as `memorix memory`; CLI and MCP exports are filtered
|
|
186
|
+
by the same active reader so an unbound backup cannot contain private/team
|
|
187
|
+
observations.
|
|
188
|
+
- Direct CLI and foreground Code Memory refreshes now enqueue qualification as
|
|
189
|
+
well as claim requalification, and they register the local project target
|
|
190
|
+
needed by the isolated control-plane worker. The host hook path persists its
|
|
191
|
+
candidate before scheduling a refresh, avoiding a fast-worker race where a
|
|
192
|
+
scan could predate the capture.
|
|
193
|
+
- Compiled-artifact smoke: an isolated Codex `PostToolUse` hook returned only
|
|
194
|
+
`continue: true`, stored a `candidate`, and the isolated background control
|
|
195
|
+
plane upgraded it to `qualified` after a real Code Memory scan with one
|
|
196
|
+
current reference. Embeddings were deliberately disabled for this
|
|
197
|
+
deterministic local smoke. The full test suite, TypeScript check, and
|
|
198
|
+
production build also passed after the admission policy was reconciled with
|
|
199
|
+
OpenCode's concise technical response events.
|
|
200
|
+
- #135 remains a contributor-owned session-handoff candidate for the bounded
|
|
201
|
+
`HandoffPacket` phase. It is not copied or silently replaced.
|
|
202
|
+
- #133/#134 remain open pending an official provider-capability layer and a
|
|
203
|
+
safe agent-facing media path. The existing OpenRouter text embedding path is
|
|
204
|
+
the supported baseline.
|
|
205
|
+
- See [1.2.2 Memory Control Plane](../1.2.2-MEMORY-CONTROL-PLANE.md) for
|
|
206
|
+
phases, acceptance gates, non-goals, and release criteria.
|
package/package.json
CHANGED
package/src/audit/index.ts
CHANGED
|
@@ -1,156 +1,156 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Module - Track Memorix-written files
|
|
3
|
-
*
|
|
4
|
-
* Records all files written by Memorix to distinguish them from
|
|
5
|
-
* project-native files. Provides audit trail for cleanup and rollback.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import * as fs from 'node:fs/promises';
|
|
9
|
-
import * as path from 'node:path';
|
|
10
|
-
import { homedir } from 'node:os';
|
|
11
|
-
|
|
12
|
-
function getAuditFilePath(): string {
|
|
13
|
-
return process.env.MEMORIX_AUDIT_FILE || path.join(homedir(), '.memorix', 'audit.json');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface AuditEntry {
|
|
17
|
-
type: 'hook' | 'rule' | 'other';
|
|
18
|
-
agent?: string;
|
|
19
|
-
path: string;
|
|
20
|
-
createdAt: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ProjectAudit {
|
|
24
|
-
projectRoot: string;
|
|
25
|
-
installedAt: string;
|
|
26
|
-
entries: AuditEntry[];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface AuditData {
|
|
30
|
-
version: string;
|
|
31
|
-
projects: Record<string, ProjectAudit>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Load audit data from disk.
|
|
36
|
-
*/
|
|
37
|
-
export async function loadAudit(): Promise<AuditData> {
|
|
38
|
-
try {
|
|
39
|
-
const content = await fs.readFile(getAuditFilePath(), 'utf-8');
|
|
40
|
-
return JSON.parse(content) as AuditData;
|
|
41
|
-
} catch {
|
|
42
|
-
// No audit file yet
|
|
43
|
-
return {
|
|
44
|
-
version: '1.0.0',
|
|
45
|
-
projects: {},
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Save audit data to disk.
|
|
52
|
-
*/
|
|
53
|
-
export async function saveAudit(data: AuditData): Promise<void> {
|
|
54
|
-
const auditFile = getAuditFilePath();
|
|
55
|
-
const dir = path.dirname(auditFile);
|
|
56
|
-
await fs.mkdir(dir, { recursive: true });
|
|
57
|
-
await fs.writeFile(auditFile, JSON.stringify(data, null, 2), 'utf-8');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get project ID from project root via .git detection.
|
|
62
|
-
*/
|
|
63
|
-
export function getProjectId(projectRoot: string): string {
|
|
64
|
-
try {
|
|
65
|
-
const { detectProject } = require('../project/detector.js');
|
|
66
|
-
const project = detectProject(projectRoot);
|
|
67
|
-
if (project) return project.id;
|
|
68
|
-
} catch { /* fallback below */ }
|
|
69
|
-
const normalized = projectRoot.replace(/\\/g, '/');
|
|
70
|
-
return `untracked/${normalized}`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Record a file written by Memorix.
|
|
75
|
-
*/
|
|
76
|
-
export async function recordFile(
|
|
77
|
-
projectRoot: string,
|
|
78
|
-
type: AuditEntry['type'],
|
|
79
|
-
filePath: string,
|
|
80
|
-
agent?: string,
|
|
81
|
-
): Promise<void> {
|
|
82
|
-
const data = await loadAudit();
|
|
83
|
-
const projectId = getProjectId(projectRoot);
|
|
84
|
-
|
|
85
|
-
if (!data.projects[projectId]) {
|
|
86
|
-
data.projects[projectId] = {
|
|
87
|
-
projectRoot,
|
|
88
|
-
installedAt: new Date().toISOString(),
|
|
89
|
-
entries: [],
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Check if entry already exists
|
|
94
|
-
const existingIndex = data.projects[projectId].entries.findIndex(
|
|
95
|
-
(e) => e.path === filePath
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
if (existingIndex === -1) {
|
|
99
|
-
data.projects[projectId].entries.push({
|
|
100
|
-
type,
|
|
101
|
-
agent,
|
|
102
|
-
path: filePath,
|
|
103
|
-
createdAt: new Date().toISOString(),
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
await saveAudit(data);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get all files written by Memorix for a project.
|
|
112
|
-
*/
|
|
113
|
-
export async function getProjectFiles(projectRoot: string): Promise<AuditEntry[]> {
|
|
114
|
-
const data = await loadAudit();
|
|
115
|
-
const projectId = getProjectId(projectRoot);
|
|
116
|
-
return data.projects[projectId]?.entries || [];
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Remove a file from audit (when uninstalled).
|
|
121
|
-
*/
|
|
122
|
-
export async function removeFile(projectRoot: string, filePath: string): Promise<void> {
|
|
123
|
-
const data = await loadAudit();
|
|
124
|
-
const projectId = getProjectId(projectRoot);
|
|
125
|
-
|
|
126
|
-
if (!data.projects[projectId]) return;
|
|
127
|
-
|
|
128
|
-
data.projects[projectId].entries = data.projects[projectId].entries.filter(
|
|
129
|
-
(e) => e.path !== filePath
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
// If no entries left, remove the project
|
|
133
|
-
if (data.projects[projectId].entries.length === 0) {
|
|
134
|
-
delete data.projects[projectId];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
await saveAudit(data);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get all audit entries across all projects.
|
|
142
|
-
*/
|
|
143
|
-
export async function getAllAuditEntries(): Promise<
|
|
144
|
-
Array<{ projectId: string; entry: AuditEntry }>
|
|
145
|
-
> {
|
|
146
|
-
const data = await loadAudit();
|
|
147
|
-
const entries: Array<{ projectId: string; entry: AuditEntry }> = [];
|
|
148
|
-
|
|
149
|
-
for (const [projectId, project] of Object.entries(data.projects)) {
|
|
150
|
-
for (const entry of project.entries) {
|
|
151
|
-
entries.push({ projectId, entry });
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return entries;
|
|
156
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Audit Module - Track Memorix-written files
|
|
3
|
+
*
|
|
4
|
+
* Records all files written by Memorix to distinguish them from
|
|
5
|
+
* project-native files. Provides audit trail for cleanup and rollback.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'node:fs/promises';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
|
|
12
|
+
function getAuditFilePath(): string {
|
|
13
|
+
return process.env.MEMORIX_AUDIT_FILE || path.join(homedir(), '.memorix', 'audit.json');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AuditEntry {
|
|
17
|
+
type: 'hook' | 'rule' | 'other';
|
|
18
|
+
agent?: string;
|
|
19
|
+
path: string;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ProjectAudit {
|
|
24
|
+
projectRoot: string;
|
|
25
|
+
installedAt: string;
|
|
26
|
+
entries: AuditEntry[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AuditData {
|
|
30
|
+
version: string;
|
|
31
|
+
projects: Record<string, ProjectAudit>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Load audit data from disk.
|
|
36
|
+
*/
|
|
37
|
+
export async function loadAudit(): Promise<AuditData> {
|
|
38
|
+
try {
|
|
39
|
+
const content = await fs.readFile(getAuditFilePath(), 'utf-8');
|
|
40
|
+
return JSON.parse(content) as AuditData;
|
|
41
|
+
} catch {
|
|
42
|
+
// No audit file yet
|
|
43
|
+
return {
|
|
44
|
+
version: '1.0.0',
|
|
45
|
+
projects: {},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Save audit data to disk.
|
|
52
|
+
*/
|
|
53
|
+
export async function saveAudit(data: AuditData): Promise<void> {
|
|
54
|
+
const auditFile = getAuditFilePath();
|
|
55
|
+
const dir = path.dirname(auditFile);
|
|
56
|
+
await fs.mkdir(dir, { recursive: true });
|
|
57
|
+
await fs.writeFile(auditFile, JSON.stringify(data, null, 2), 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get project ID from project root via .git detection.
|
|
62
|
+
*/
|
|
63
|
+
export function getProjectId(projectRoot: string): string {
|
|
64
|
+
try {
|
|
65
|
+
const { detectProject } = require('../project/detector.js');
|
|
66
|
+
const project = detectProject(projectRoot);
|
|
67
|
+
if (project) return project.id;
|
|
68
|
+
} catch { /* fallback below */ }
|
|
69
|
+
const normalized = projectRoot.replace(/\\/g, '/');
|
|
70
|
+
return `untracked/${normalized}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Record a file written by Memorix.
|
|
75
|
+
*/
|
|
76
|
+
export async function recordFile(
|
|
77
|
+
projectRoot: string,
|
|
78
|
+
type: AuditEntry['type'],
|
|
79
|
+
filePath: string,
|
|
80
|
+
agent?: string,
|
|
81
|
+
): Promise<void> {
|
|
82
|
+
const data = await loadAudit();
|
|
83
|
+
const projectId = getProjectId(projectRoot);
|
|
84
|
+
|
|
85
|
+
if (!data.projects[projectId]) {
|
|
86
|
+
data.projects[projectId] = {
|
|
87
|
+
projectRoot,
|
|
88
|
+
installedAt: new Date().toISOString(),
|
|
89
|
+
entries: [],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check if entry already exists
|
|
94
|
+
const existingIndex = data.projects[projectId].entries.findIndex(
|
|
95
|
+
(e) => e.path === filePath
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (existingIndex === -1) {
|
|
99
|
+
data.projects[projectId].entries.push({
|
|
100
|
+
type,
|
|
101
|
+
agent,
|
|
102
|
+
path: filePath,
|
|
103
|
+
createdAt: new Date().toISOString(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await saveAudit(data);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get all files written by Memorix for a project.
|
|
112
|
+
*/
|
|
113
|
+
export async function getProjectFiles(projectRoot: string): Promise<AuditEntry[]> {
|
|
114
|
+
const data = await loadAudit();
|
|
115
|
+
const projectId = getProjectId(projectRoot);
|
|
116
|
+
return data.projects[projectId]?.entries || [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Remove a file from audit (when uninstalled).
|
|
121
|
+
*/
|
|
122
|
+
export async function removeFile(projectRoot: string, filePath: string): Promise<void> {
|
|
123
|
+
const data = await loadAudit();
|
|
124
|
+
const projectId = getProjectId(projectRoot);
|
|
125
|
+
|
|
126
|
+
if (!data.projects[projectId]) return;
|
|
127
|
+
|
|
128
|
+
data.projects[projectId].entries = data.projects[projectId].entries.filter(
|
|
129
|
+
(e) => e.path !== filePath
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// If no entries left, remove the project
|
|
133
|
+
if (data.projects[projectId].entries.length === 0) {
|
|
134
|
+
delete data.projects[projectId];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
await saveAudit(data);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get all audit entries across all projects.
|
|
142
|
+
*/
|
|
143
|
+
export async function getAllAuditEntries(): Promise<
|
|
144
|
+
Array<{ projectId: string; entry: AuditEntry }>
|
|
145
|
+
> {
|
|
146
|
+
const data = await loadAudit();
|
|
147
|
+
const entries: Array<{ projectId: string; entry: AuditEntry }> = [];
|
|
148
|
+
|
|
149
|
+
for (const [projectId, project] of Object.entries(data.projects)) {
|
|
150
|
+
for (const entry of project.entries) {
|
|
151
|
+
entries.push({ projectId, entry });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return entries;
|
|
156
|
+
}
|
|
@@ -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
|
+
}
|