pmem-ai 0.7.1 → 0.7.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 +21 -0
- package/README.md +40 -2
- package/dist/commands/integration.js +1 -1
- package/dist/commands/mcp.d.ts +9 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +64 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/milestone.d.ts +5 -0
- package/dist/commands/milestone.d.ts.map +1 -0
- package/dist/commands/milestone.js +197 -0
- package/dist/commands/milestone.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +87 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +19 -8
- package/dist/commands/verify.js.map +1 -1
- package/dist/core/consistency.d.ts.map +1 -1
- package/dist/core/consistency.js +6 -0
- package/dist/core/consistency.js.map +1 -1
- package/dist/core/query/ask.d.ts +20 -0
- package/dist/core/query/ask.d.ts.map +1 -0
- package/dist/core/query/ask.js +256 -0
- package/dist/core/query/ask.js.map +1 -0
- package/dist/core/query/recall.d.ts +21 -0
- package/dist/core/query/recall.d.ts.map +1 -0
- package/dist/core/query/recall.js +148 -0
- package/dist/core/query/recall.js.map +1 -0
- package/dist/core/query/related.d.ts +29 -0
- package/dist/core/query/related.d.ts.map +1 -0
- package/dist/core/query/related.js +106 -0
- package/dist/core/query/related.js.map +1 -0
- package/dist/core/query/status.d.ts +24 -0
- package/dist/core/query/status.d.ts.map +1 -0
- package/dist/core/query/status.js +236 -0
- package/dist/core/query/status.js.map +1 -0
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/security.d.ts +21 -0
- package/dist/mcp/security.d.ts.map +1 -0
- package/dist/mcp/security.js +150 -0
- package/dist/mcp/security.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +177 -0
- package/dist/mcp/server.js.map +1 -0
- package/docs/dogfooding.md +98 -0
- package/docs/pmem-rt.md +137 -0
- package/package.json +3 -2
- package/skills/pmem/SKILL.md +43 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pmem are documented here.
|
|
4
4
|
|
|
5
|
+
## v0.7.2 — pmem-rt v1 MCP Adapter + Dogfooding Usability Fixes
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **pmem-rt v1 MCP Server**: New `pmem mcp` command starts a read-only stdio MCP server (`src/mcp/server.ts`) with 4 tools: `pmem_recall`, `pmem_ask`, `pmem_related`, `pmem_status`. All card content carries `content_trust: "untrusted_project_data"`. Uses `@modelcontextprotocol/sdk` (pure ESM, loaded via dynamic import).
|
|
10
|
+
- **Query layer** (`src/core/query/`): Extracted pure query functions (`recallQuery`, `askQuery`, `relatedQuery`, `statusQuery`) shared by CLI and MCP server. No console.log, no process.exit(), no Commander.js dependency.
|
|
11
|
+
- **MCP security** (`src/mcp/security.ts`): `validatePathScope` (realpath + path.sep comparison to prevent symlink escape and prefix confusion), `enforceBudget` (token budget truncation), `addContentTrust` (marks all card objects).
|
|
12
|
+
- **`pmem milestone <version>`**: Records release milestones as memory cards with auto git-tag detection and manifest type registration.
|
|
13
|
+
- **`pmem update --confirm --refresh-verified <ids>`**: Bumps `last_verified` on specified cards during confirm, before rebuild.
|
|
14
|
+
- **`pmem mark-dirty --card <id...>`**: Explicit per-card dirty marking, bypassing git diff.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **Exclude `.pmem/**` from stale_memory check**: Prevent false-positive warnings from `pmem update --confirm` rewriting manifest.yml / next.md / state.md / index.md.
|
|
19
|
+
- **Separate `--fix` and `--fix-stale` semantics**: `--fix` handles structural index issues only; `--fix-stale` additionally refreshes stale_memory `last_verified` timestamps.
|
|
20
|
+
- **`docs/dogfooding.md`**: Documents self-referential stale patterns, cleanup cadence, and new command workflows.
|
|
21
|
+
|
|
22
|
+
### Version
|
|
23
|
+
|
|
24
|
+
Bumped from 0.7.1 → 0.7.2.
|
|
25
|
+
|
|
5
26
|
## 0.7.0 - Universal Agent Memory (presets, custom card types, and domain neutrality)
|
|
6
27
|
|
|
7
28
|
### Added
|
package/README.md
CHANGED
|
@@ -346,14 +346,18 @@ pmem related <id> [--depth N] [--type <edge-type>] [--format compact|json] [--so
|
|
|
346
346
|
pmem trace <id>
|
|
347
347
|
|
|
348
348
|
pmem status [--since <timestamp>] [--format compact|json]
|
|
349
|
-
pmem mark-dirty [-r <reason>] [--auto]
|
|
349
|
+
pmem mark-dirty [-r <reason>] [--auto] [--card <id...>]
|
|
350
350
|
pmem update [--auto] [--suggest] [--apply-suggestion <id>] [--confirm] [--force]
|
|
351
351
|
[-s <summary>] [-n <next>] [--format compact|json] [--include-history]
|
|
352
352
|
[--accept-edges <ids>] [--reject-edges <ids>]
|
|
353
|
+
[--refresh-verified <ids>]
|
|
354
|
+
pmem sync -s "<summary>" [-n "<next>"]
|
|
355
|
+
|
|
356
|
+
pmem milestone <version> [-m <message>] [--tag <name>]
|
|
353
357
|
|
|
354
358
|
pmem distill [--suggest] [--confirm] [--apply-suggestion <id>] [--suggest-splits]
|
|
355
359
|
pmem rebuild [--changed] [--full] [--card <id>]
|
|
356
|
-
pmem verify [--fix] [--fix-locks] [--relaxed]
|
|
360
|
+
pmem verify [--fix] [--fix-stale] [--fix-locks] [--relaxed]
|
|
357
361
|
pmem doctor [--format compact|json]
|
|
358
362
|
pmem new <type> <title>
|
|
359
363
|
pmem rename --find <pattern> --replace <replacement> [--write]
|
|
@@ -362,6 +366,7 @@ pmem session start [-a <agent-name>]
|
|
|
362
366
|
pmem session end [-s <summary>]
|
|
363
367
|
pmem integration list|install <framework>|verify
|
|
364
368
|
pmem install [--skills] [--claude] [--codex] [--gemini] [--all]
|
|
369
|
+
pmem mcp
|
|
365
370
|
```
|
|
366
371
|
|
|
367
372
|
## Exit Codes
|
|
@@ -379,6 +384,39 @@ Agents should parse structured JSON output (`--format json`) to decide next step
|
|
|
379
384
|
|
|
380
385
|
> **Breaking change from v0.6.1:** `pmem update --suggest` and `pmem distill --suggest` previously exited with code `1` when suggestions existed. Scripts that checked `$? -eq 1` must now parse JSON output instead.
|
|
381
386
|
|
|
387
|
+
## pmem-rt — MCP Runtime for AI Agents (v0.7.2)
|
|
388
|
+
|
|
389
|
+
pmem-rt is a read-only stdio MCP adapter that lets AI coding agents use pmem as a low-latency memory backend directly in their tool loop.
|
|
390
|
+
|
|
391
|
+
### Quick Start
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
# In your project
|
|
395
|
+
npm install pmem-ai
|
|
396
|
+
npx pmem init --guided
|
|
397
|
+
npx pmem rebuild
|
|
398
|
+
|
|
399
|
+
# Configure your agent (e.g. Claude Code settings.json):
|
|
400
|
+
# {
|
|
401
|
+
# "mcpServers": {
|
|
402
|
+
# "pmem": { "command": "npx", "args": ["pmem", "mcp"], "cwd": "/absolute/path/to/your-project" }
|
|
403
|
+
# }
|
|
404
|
+
# }
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### MCP Tools
|
|
408
|
+
|
|
409
|
+
| Tool | Description |
|
|
410
|
+
|------|-------------|
|
|
411
|
+
| `pmem_recall` | Restore project context: name, stage, focus, next, active cards, recent updates |
|
|
412
|
+
| `pmem_ask` | 6-step search: ID → alias → tag → graph expansion → FTS5 → LIKE |
|
|
413
|
+
| `pmem_related` | Graph neighbors of a card, grouped by edge type with direction/confidence |
|
|
414
|
+
| `pmem_status` | Changed files → affected memory cards |
|
|
415
|
+
|
|
416
|
+
All tools are read-only. Writes continue through the CLI (`pmem update --confirm`, `pmem sync`). Every card carries `content_trust: "untrusted_project_data"`.
|
|
417
|
+
|
|
418
|
+
[Full integration guide →](docs/pmem-rt.md)
|
|
419
|
+
|
|
382
420
|
## Project Layout
|
|
383
421
|
|
|
384
422
|
```txt
|
|
@@ -375,7 +375,7 @@ function installIntegration(pmemPath, manifest, framework) {
|
|
|
375
375
|
console.log(`✓ Integration "${framework}" installed.`);
|
|
376
376
|
console.log(` Template: .pmem/integrations/${framework}/`);
|
|
377
377
|
}
|
|
378
|
-
const CURRENT_TEMPLATE_VERSION = '0.7.
|
|
378
|
+
const CURRENT_TEMPLATE_VERSION = '0.7.2';
|
|
379
379
|
function verifyIntegrations(pmemPath, manifest) {
|
|
380
380
|
if (!manifest)
|
|
381
381
|
return;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Start a read-only stdio MCP server for agent tool integration.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: This command MUST NOT output any console.log — stdout is the
|
|
5
|
+
* MCP protocol transport channel. Any non-JSON output will cause protocol
|
|
6
|
+
* errors. Use stderr for diagnostics if absolutely necessary.
|
|
7
|
+
*/
|
|
8
|
+
export declare function mcpCommand(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBhD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.mcpCommand = mcpCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const fs_1 = require("../core/fs");
|
|
39
|
+
const security_1 = require("../mcp/security");
|
|
40
|
+
const server_1 = require("../mcp/server");
|
|
41
|
+
/**
|
|
42
|
+
* Start a read-only stdio MCP server for agent tool integration.
|
|
43
|
+
*
|
|
44
|
+
* IMPORTANT: This command MUST NOT output any console.log — stdout is the
|
|
45
|
+
* MCP protocol transport channel. Any non-JSON output will cause protocol
|
|
46
|
+
* errors. Use stderr for diagnostics if absolutely necessary.
|
|
47
|
+
*/
|
|
48
|
+
async function mcpCommand() {
|
|
49
|
+
const cwd = process.cwd();
|
|
50
|
+
const pmemPath = path.join(cwd, '.pmem');
|
|
51
|
+
if (!(0, fs_1.fileExists)(pmemPath)) {
|
|
52
|
+
process.stderr.write('Error: No .pmem directory found. Run `pmem init` first.\n');
|
|
53
|
+
process.exit(2);
|
|
54
|
+
}
|
|
55
|
+
const dbPath = path.join(pmemPath, 'pmem.db');
|
|
56
|
+
if (!(0, fs_1.fileExists)(dbPath)) {
|
|
57
|
+
process.stderr.write('Error: No .pmem/pmem.db found. Run `pmem rebuild` first.\n');
|
|
58
|
+
process.exit(2);
|
|
59
|
+
}
|
|
60
|
+
// Security: validate path scope before starting
|
|
61
|
+
(0, security_1.validatePathScope)(pmemPath);
|
|
62
|
+
await (0, server_1.startMcpServer)(pmemPath);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,gCAmBC;AA/BD,2CAA6B;AAC7B,mCAAwC;AACxC,8CAAoD;AACpD,0CAA+C;AAE/C;;;;;;GAMG;AACI,KAAK,UAAU,UAAU;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEzC,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAA,eAAU,EAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAA,4BAAiB,EAAC,QAAQ,CAAC,CAAC;IAE5B,MAAM,IAAA,uBAAc,EAAC,QAAQ,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestone.d.ts","sourceRoot":"","sources":["../../src/commands/milestone.ts"],"names":[],"mappings":"AAQA,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,IAAI,CAyIxG"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.milestoneCommand = milestoneCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const fs_1 = require("../core/fs");
|
|
40
|
+
const manifest_1 = require("../core/manifest");
|
|
41
|
+
const db_1 = require("../core/db");
|
|
42
|
+
const PMEM_DIR = '.pmem';
|
|
43
|
+
function milestoneCommand(version, options = {}) {
|
|
44
|
+
const cwd = process.cwd();
|
|
45
|
+
const pmemPath = path.join(cwd, PMEM_DIR);
|
|
46
|
+
if (!(0, fs_1.fileExists)(pmemPath)) {
|
|
47
|
+
console.log('No .pmem directory found. Run `pmem init` first.');
|
|
48
|
+
process.exit(2);
|
|
49
|
+
}
|
|
50
|
+
const manifest = (0, manifest_1.loadManifest)(pmemPath);
|
|
51
|
+
if (!manifest) {
|
|
52
|
+
console.log('No manifest found. Run `pmem init` first.');
|
|
53
|
+
process.exit(2);
|
|
54
|
+
}
|
|
55
|
+
const config = (0, manifest_1.resolveConfig)(manifest);
|
|
56
|
+
// Determine the directory for milestone/trace cards
|
|
57
|
+
const traceDirName = config.type_dirs['trace'] || config.type_dirs['milestone'] || 'traces';
|
|
58
|
+
const traceDir = path.join(pmemPath, traceDirName);
|
|
59
|
+
(0, fs_1.ensureDir)(traceDir);
|
|
60
|
+
const versionClean = version.replace(/^v/, '');
|
|
61
|
+
const milestoneId = `milestone.v${versionClean}`;
|
|
62
|
+
const message = options.message || `Released version ${version}`;
|
|
63
|
+
const tag = options.tag || `v${versionClean}`;
|
|
64
|
+
// Check if git tag exists
|
|
65
|
+
let gitInfo = '';
|
|
66
|
+
try {
|
|
67
|
+
const gitDir = (0, child_process_1.execSync)('git rev-parse --git-dir', { cwd, stdio: 'ignore', encoding: 'utf8' }).trim();
|
|
68
|
+
if (gitDir) {
|
|
69
|
+
try {
|
|
70
|
+
const tagSha = (0, child_process_1.execSync)(`git rev-parse refs/tags/${tag}`, { cwd, stdio: 'pipe', encoding: 'utf8' }).trim();
|
|
71
|
+
gitInfo = `\n## Git Tag\n- Tag: \`${tag}\`\n- Commit: \`${tagSha.slice(0, 8)}\``;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
try {
|
|
75
|
+
const headSha = (0, child_process_1.execSync)('git rev-parse HEAD', { cwd, encoding: 'utf8' }).trim();
|
|
76
|
+
gitInfo = `\n## Git\n- HEAD: \`${headSha.slice(0, 8)}\`\n- Tag \`${tag}\` not yet created (use \`git tag ${tag}\` to create it)`;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// no git info available
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// not a git repo
|
|
86
|
+
}
|
|
87
|
+
const milestoneFile = path.join(traceDir, `milestone.${milestoneId}.md`);
|
|
88
|
+
if ((0, fs_1.fileExists)(milestoneFile)) {
|
|
89
|
+
console.log(`Milestone card already exists: ${path.relative(cwd, milestoneFile)}`);
|
|
90
|
+
console.log(` Edit it directly or use a different version.`);
|
|
91
|
+
process.exit(2);
|
|
92
|
+
}
|
|
93
|
+
(0, fs_1.atomicWrite)(milestoneFile, `---
|
|
94
|
+
id: ${milestoneId}
|
|
95
|
+
type: milestone
|
|
96
|
+
status: shipped
|
|
97
|
+
created: ${new Date().toISOString().split('T')[0]}
|
|
98
|
+
tags: [release, ${tag}]
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
# Milestone: ${version}
|
|
102
|
+
|
|
103
|
+
## What
|
|
104
|
+
${message}
|
|
105
|
+
|
|
106
|
+
## When
|
|
107
|
+
Released ${new Date().toISOString().split('T')[0]}.
|
|
108
|
+
${gitInfo}
|
|
109
|
+
## Next
|
|
110
|
+
Continue development toward the next milestone.
|
|
111
|
+
`);
|
|
112
|
+
console.log(`Milestone recorded: ${path.relative(cwd, milestoneFile)}`);
|
|
113
|
+
console.log(` Version: ${version}`);
|
|
114
|
+
console.log(` ID: ${milestoneId}`);
|
|
115
|
+
// Register 'milestone' in manifest if not already present (review item #3)
|
|
116
|
+
registerMilestoneType(manifest, config, pmemPath);
|
|
117
|
+
// Index the card and link to related feature cards
|
|
118
|
+
let didRebuild = false;
|
|
119
|
+
const dbPath = path.join(pmemPath, 'pmem.db');
|
|
120
|
+
if ((0, fs_1.fileExists)(dbPath)) {
|
|
121
|
+
try {
|
|
122
|
+
const db = (0, db_1.openDatabase)(pmemPath);
|
|
123
|
+
(0, db_1.createSchema)(db);
|
|
124
|
+
// Rebuild to index the new card
|
|
125
|
+
const { rebuildCommand } = require('./rebuild');
|
|
126
|
+
rebuildCommand({ card: milestoneId });
|
|
127
|
+
didRebuild = true;
|
|
128
|
+
// Link to feature cards whose ID contains the version (tightened: match
|
|
129
|
+
// `feature.v<version>` prefix or `v<version_underscored>` segment).
|
|
130
|
+
const versionUnderscored = versionClean.replace(/\./g, '_');
|
|
131
|
+
const featureCards = db.prepare(`SELECT id FROM cards
|
|
132
|
+
WHERE type = 'feature'
|
|
133
|
+
AND (id LIKE ? OR id LIKE ?)
|
|
134
|
+
AND is_deleted = 0`).all(`feature.v${versionClean}%`, `%v${versionUnderscored}%`);
|
|
135
|
+
const now = new Date().toISOString();
|
|
136
|
+
for (const fc of featureCards) {
|
|
137
|
+
(0, db_1.insertEdge)(db, {
|
|
138
|
+
from_id: milestoneId,
|
|
139
|
+
to_id: fc.id,
|
|
140
|
+
type: 'implements',
|
|
141
|
+
source: 'inferred',
|
|
142
|
+
confidence: 0.9,
|
|
143
|
+
created_at: now,
|
|
144
|
+
updated_at: now,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (featureCards.length > 0) {
|
|
148
|
+
console.log(` Linked to ${featureCards.length} feature card(s): ${featureCards.map(f => f.id).join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
(0, db_1.closeDatabase)();
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// DB operations are best-effort
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Only suggest a manual rebuild when the DB path didn't already do one (review item #4)
|
|
157
|
+
if (!didRebuild) {
|
|
158
|
+
console.log(`\nRun \`pmem rebuild\` to index the new milestone card.`);
|
|
159
|
+
}
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Ensure 'milestone' is registered in the manifest's card type whitelist
|
|
164
|
+
* so that verify / rebuild don't produce card_id_violation warnings.
|
|
165
|
+
*/
|
|
166
|
+
function registerMilestoneType(manifest, config, pmemPath) {
|
|
167
|
+
let changed = false;
|
|
168
|
+
// v0.7.0+ projects: add to schema.card_types
|
|
169
|
+
if (manifest.schema && Array.isArray(manifest.schema.card_types)) {
|
|
170
|
+
if (!manifest.schema.card_types.includes('milestone')) {
|
|
171
|
+
manifest.schema.card_types.push('milestone');
|
|
172
|
+
changed = true;
|
|
173
|
+
}
|
|
174
|
+
// Also add type_dirs entry if missing
|
|
175
|
+
if (!manifest.schema.type_dirs) {
|
|
176
|
+
manifest.schema.type_dirs = {};
|
|
177
|
+
}
|
|
178
|
+
if (!manifest.schema.type_dirs['milestone']) {
|
|
179
|
+
manifest.schema.type_dirs['milestone'] = 'traces';
|
|
180
|
+
changed = true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// v0.6.x projects: add milestone to id_pattern alternation
|
|
184
|
+
if (manifest.card_policy?.id_pattern) {
|
|
185
|
+
const pattern = manifest.card_policy.id_pattern;
|
|
186
|
+
if (!pattern.includes('milestone')) {
|
|
187
|
+
// Insert milestone before the closing parenthesis of the type alternation
|
|
188
|
+
manifest.card_policy.id_pattern = pattern.replace(/(\([^)]+)\)/, '$1|milestone)');
|
|
189
|
+
changed = true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (changed) {
|
|
193
|
+
(0, manifest_1.saveManifest)(pmemPath, manifest);
|
|
194
|
+
console.log(' Registered "milestone" type in manifest.');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=milestone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestone.js","sourceRoot":"","sources":["../../src/commands/milestone.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,8 +10,10 @@ export declare function updateCommand(options: {
|
|
|
10
10
|
includeHistory?: boolean;
|
|
11
11
|
acceptEdges?: string;
|
|
12
12
|
rejectEdges?: string;
|
|
13
|
+
refreshVerified?: string;
|
|
13
14
|
}): void;
|
|
14
15
|
export declare function markDirtyCommand(reason: string, options?: {
|
|
15
16
|
auto?: boolean;
|
|
17
|
+
cardIds?: string[];
|
|
16
18
|
}): void;
|
|
17
19
|
//# sourceMappingURL=update.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAaA,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAaA,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CA+CP;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAAG,IAAI,CA0I3G"}
|
package/dist/commands/update.js
CHANGED
|
@@ -78,7 +78,7 @@ function updateCommand(options) {
|
|
|
78
78
|
}
|
|
79
79
|
// --confirm or --force: write changes
|
|
80
80
|
if (options.confirm || options.force) {
|
|
81
|
-
confirmUpdate(pmemPath, options.summary, options.next);
|
|
81
|
+
confirmUpdate(pmemPath, options.summary, options.next, options.refreshVerified);
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
// no flag: show current dirty state
|
|
@@ -91,6 +91,44 @@ function markDirtyCommand(reason, options = {}) {
|
|
|
91
91
|
console.log('No .pmem directory found. Run `pmem init` first.');
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
|
+
// --card <id>: explicitly mark specific cards as dirty
|
|
95
|
+
if (options.cardIds && options.cardIds.length > 0) {
|
|
96
|
+
const dbPath = path.join(pmemPath, 'pmem.db');
|
|
97
|
+
if (!(0, fs_1.fileExists)(dbPath)) {
|
|
98
|
+
console.log('No SQLite database found. Run `pmem rebuild` first.');
|
|
99
|
+
process.exit(2);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const db = (0, db_1.openDatabase)(pmemPath);
|
|
103
|
+
const activeSession = (0, db_1.getActiveSession)(db);
|
|
104
|
+
for (const cardId of options.cardIds) {
|
|
105
|
+
const card = db.prepare('SELECT id FROM cards WHERE id = ? AND is_deleted = 0').get(cardId);
|
|
106
|
+
if (card) {
|
|
107
|
+
(0, db_1.insertDirtyFlag)(db, 'card', cardId, reason, activeSession?.id);
|
|
108
|
+
console.log(`Marked card dirty: ${cardId}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(`Card not found or deleted: ${cardId}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Also mark project-level dirty
|
|
115
|
+
const manifest = (0, manifest_1.loadManifest)(pmemPath);
|
|
116
|
+
if (manifest) {
|
|
117
|
+
const timestamp = new Date().toISOString();
|
|
118
|
+
manifest.memory_status.dirty = true;
|
|
119
|
+
manifest.memory_status.dirty_reason = reason;
|
|
120
|
+
manifest.memory_status.dirty_since = timestamp;
|
|
121
|
+
(0, manifest_1.saveManifest)(pmemPath, manifest);
|
|
122
|
+
(0, db_1.insertDirtyFlag)(db, 'project', '.pmem', reason, activeSession?.id);
|
|
123
|
+
}
|
|
124
|
+
(0, db_1.closeDatabase)();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
console.error('Could not mark cards as dirty:', err);
|
|
129
|
+
process.exit(2);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
94
132
|
// --auto: detect changed files via git and mark related cards as dirty
|
|
95
133
|
if (options.auto) {
|
|
96
134
|
const dbPath = path.join(pmemPath, 'pmem.db');
|
|
@@ -251,7 +289,7 @@ function autoUpdate(pmemPath, manifest) {
|
|
|
251
289
|
}
|
|
252
290
|
}
|
|
253
291
|
}
|
|
254
|
-
function confirmUpdate(pmemPath, summary, next) {
|
|
292
|
+
function confirmUpdate(pmemPath, summary, next, refreshVerified) {
|
|
255
293
|
const lockPath = path.join(pmemPath, '.lock');
|
|
256
294
|
if (!(0, fs_1.acquireLock)(lockPath)) {
|
|
257
295
|
console.log('Failed to acquire pmem lock after 3s.');
|
|
@@ -335,7 +373,53 @@ ${next || 'Continue as planned.'}
|
|
|
335
373
|
manifest.memory_status.dirty_since = null;
|
|
336
374
|
(0, manifest_1.saveManifest)(pmemPath, manifest);
|
|
337
375
|
}
|
|
338
|
-
//
|
|
376
|
+
// --refresh-verified: bump last_verified on specified cards.
|
|
377
|
+
// MUST run BEFORE rebuildCommand() so the updated frontmatter
|
|
378
|
+
// is picked up by the rebuild and SQLite hashes stay in sync.
|
|
379
|
+
if (refreshVerified) {
|
|
380
|
+
const cardIds = refreshVerified.split(',').map(s => s.trim()).filter(Boolean);
|
|
381
|
+
const refreshDbPath = path.join(pmemPath, 'pmem.db');
|
|
382
|
+
if ((0, fs_1.fileExists)(refreshDbPath) && cardIds.length > 0) {
|
|
383
|
+
try {
|
|
384
|
+
const refreshDb = (0, db_1.openDatabase)(pmemPath); // open once
|
|
385
|
+
const refreshed = [];
|
|
386
|
+
for (const cardId of cardIds) {
|
|
387
|
+
const card = refreshDb.prepare('SELECT file_path FROM cards WHERE id = ?').get(cardId);
|
|
388
|
+
if (card) {
|
|
389
|
+
const cardFilePath = path.join(process.cwd(), card.file_path);
|
|
390
|
+
if ((0, fs_1.fileExists)(cardFilePath)) {
|
|
391
|
+
const content = (0, fs_1.readFile)(cardFilePath);
|
|
392
|
+
if (content) {
|
|
393
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
394
|
+
if (match) {
|
|
395
|
+
const frontmatterText = match[1];
|
|
396
|
+
const nowStr = new Date().toISOString();
|
|
397
|
+
let newFmText = frontmatterText;
|
|
398
|
+
const regex = /^last_verified:.*$/m;
|
|
399
|
+
if (regex.test(frontmatterText)) {
|
|
400
|
+
newFmText = frontmatterText.replace(regex, `last_verified: "${nowStr}"`);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
newFmText = frontmatterText.trimEnd() + `\nlast_verified: "${nowStr}"`;
|
|
404
|
+
}
|
|
405
|
+
const newContent = content.replace(/^---\n([\s\S]*?)\n---/, `---\n${newFmText}\n---`);
|
|
406
|
+
(0, fs_1.writeFile)(cardFilePath, newContent);
|
|
407
|
+
refreshed.push(cardId);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (refreshed.length > 0) {
|
|
414
|
+
console.log(`Refreshed last_verified for: ${refreshed.join(', ')}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
// skip cards that can't be refreshed
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// Rebuild indexes — picks up frontmatter changes from --refresh-verified above
|
|
339
423
|
console.log('Rebuilding indexes...');
|
|
340
424
|
(0, rebuild_1.rebuildCommand)();
|
|
341
425
|
console.log('\n✓ Memory updated.');
|