@polderlabs/bizar 4.2.1 → 4.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.
@@ -244,6 +244,60 @@ describe('bizar memory write CLI', () => {
244
244
  assert.strictEqual(r.code, 0, `expected exit 0, got ${r.code}; stderr=${r.stderr}`);
245
245
  assert.ok(existsSync(join(projectRoot, '.obsidian', 'med.md')), 'medium-severity note should be written');
246
246
  });
247
+
248
+ // ─── v4.2.2 — custom frontmatter flags ─────────────────────────────────
249
+ test('--memory-id flag sets a custom memory_id in frontmatter', () => {
250
+ const relPath = 'flags/custom-id.md';
251
+ const r = runBizarMemoryWrite(projectRoot, [
252
+ relPath,
253
+ '--type', 'coding_convention',
254
+ '--memory-id', 'mem_test_custom_id',
255
+ '--body', 'custom id test',
256
+ ]);
257
+ assert.strictEqual(r.code, 0, `expected exit 0, got ${r.code}; stderr=${r.stderr}; stdout=${r.stdout}`);
258
+ const filePath = join(projectRoot, '.obsidian', relPath);
259
+ assert.ok(existsSync(filePath), `note file should exist at ${filePath}`);
260
+ const raw = readFileSync(filePath, 'utf8');
261
+ assert.ok(/memory_id:\s*mem_test_custom_id\b/.test(raw),
262
+ `frontmatter should contain memory_id: mem_test_custom_id; got:\n${raw}`);
263
+ });
264
+
265
+ test('--scope and --source-agent flags pass through to frontmatter', () => {
266
+ const relPath = 'flags/scope-and-agent.md';
267
+ const r = runBizarMemoryWrite(projectRoot, [
268
+ relPath,
269
+ '--type', 'coding_convention',
270
+ '--scope', 'project',
271
+ '--source-agent', 'mimir',
272
+ '--body', 'scope/agent test',
273
+ ]);
274
+ assert.strictEqual(r.code, 0, `expected exit 0, got ${r.code}; stderr=${r.stderr}; stdout=${r.stdout}`);
275
+ const filePath = join(projectRoot, '.obsidian', relPath);
276
+ assert.ok(existsSync(filePath), `note file should exist at ${filePath}`);
277
+ const raw = readFileSync(filePath, 'utf8');
278
+ assert.ok(/scope:\s*project\b/.test(raw),
279
+ `frontmatter should contain scope: project; got:\n${raw}`);
280
+ assert.ok(/source_agent:\s*mimir\b/.test(raw),
281
+ `frontmatter should contain source_agent: mimir; got:\n${raw}`);
282
+ });
283
+
284
+ test('invalid --memory-id format is rejected with kebab/snake-case error', () => {
285
+ const r = runBizarMemoryWrite(projectRoot, [
286
+ 'flags/bad-id.md',
287
+ '--type', 'coding_convention',
288
+ '--memory-id', 'has spaces and !@#',
289
+ '--body', 'should fail',
290
+ ]);
291
+ assert.strictEqual(r.code, 1, `expected exit 1, got ${r.code}; stderr=${r.stderr}`);
292
+ const out = `${r.stdout}\n${r.stderr}`;
293
+ assert.ok(/invalid --memory-id/i.test(out),
294
+ `expected invalid --memory-id error, got: ${out}`);
295
+ assert.ok(/kebab|snake/i.test(out),
296
+ `expected error to mention kebab/snake-case, got: ${out}`);
297
+ // File should NOT exist
298
+ assert.ok(!existsSync(join(projectRoot, '.obsidian', 'flags', 'bad-id.md')),
299
+ 'note file must not be written when --memory-id is invalid');
300
+ });
247
301
  });
248
302
 
249
303
  // ─── bizar memory setup ──────────────────────────────────────────────────────
package/cli/memory.mjs CHANGED
@@ -104,6 +104,10 @@ async function cmdWrite(args) {
104
104
  (default: verified)
105
105
  --tag <tag> Tag to attach (may be passed multiple times)
106
106
  --title <title> Frontmatter title field
107
+ --memory-id <id> Custom memory_id (default: <type>_<timestamp>)
108
+ Must match [a-zA-Z0-9._-]+
109
+ --scope <scope> Frontmatter scope field (e.g. project, team)
110
+ --source-agent <name> Frontmatter source_agent field
107
111
  --body <text> Note body as a string
108
112
  --body-file <path> Path to a file containing the body
109
113
  (exactly one of --body / --body-file is allowed)
@@ -177,6 +181,30 @@ async function cmdWrite(args) {
177
181
  process.exit(1);
178
182
  }
179
183
 
184
+ // --memory-id (kebab/snake-case only)
185
+ const memoryId = optVal('--memory-id');
186
+ if (memoryId !== undefined) {
187
+ if (!/^[a-zA-Z0-9._-]+$/.test(memoryId)) {
188
+ error(`invalid --memory-id: '${memoryId}' (must be kebab/snake-case)`);
189
+ info('expected pattern: mem_<path>, e.g. mem_api_memory_schema_md');
190
+ process.exit(1);
191
+ }
192
+ }
193
+
194
+ // --scope (free-form, but non-empty when provided)
195
+ const scope = optVal('--scope');
196
+ if (scope !== undefined && scope.length === 0) {
197
+ error('--scope must be a non-empty string');
198
+ process.exit(1);
199
+ }
200
+
201
+ // --source-agent (free-form, but non-empty when provided)
202
+ const sourceAgent = optVal('--source-agent');
203
+ if (sourceAgent !== undefined && sourceAgent.length === 0) {
204
+ error('--source-agent must be a non-empty string');
205
+ process.exit(1);
206
+ }
207
+
180
208
  let body = '';
181
209
  if (bodyFile) {
182
210
  try {
@@ -201,6 +229,9 @@ async function cmdWrite(args) {
201
229
  tags,
202
230
  });
203
231
  if (title) frontmatter.title = title;
232
+ if (memoryId) frontmatter.memory_id = memoryId;
233
+ if (scope) frontmatter.scope = scope;
234
+ if (sourceAgent) frontmatter.source_agent = sourceAgent;
204
235
 
205
236
  // ── Write ───────────────────────────────────────────────────────────────
206
237
  let result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar",
3
- "version": "4.2.1",
3
+ "version": "4.2.2",
4
4
  "description": "Norse-pantheon multi-agent system for opencode — 13 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. v4 ships as a single npm package bundling the dashboard server, opencode plugin, and typed SDK.",
5
5
  "type": "module",
6
6
  "bin": {