@plur-ai/core 0.7.5 → 0.7.7

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/dist/index.d.ts CHANGED
@@ -545,10 +545,34 @@ declare const PackManifestSchema: z.ZodObject<{
545
545
  }>;
546
546
  type PackManifest = z.infer<typeof PackManifestSchema>;
547
547
 
548
+ interface RegistryEntry {
549
+ name: string;
550
+ installed_at: string;
551
+ source: string;
552
+ integrity: string;
553
+ version?: string;
554
+ creator?: string;
555
+ }
556
+ interface PreviewResult {
557
+ manifest: PackManifest;
558
+ engram_count: number;
559
+ engrams: Array<{
560
+ id: string;
561
+ type: string;
562
+ statement: string;
563
+ domain?: string;
564
+ tags: string[];
565
+ }>;
566
+ security: PrivacyScanResult;
567
+ warnings: string[];
568
+ }
569
+ declare function previewPack(source: string): PreviewResult;
548
570
  interface InstallResult {
549
571
  installed: number;
550
572
  name: string;
551
573
  conflicts: ConflictItem[];
574
+ security: PrivacyScanResult;
575
+ registry: RegistryEntry;
552
576
  }
553
577
  interface ConflictItem {
554
578
  pack_engram_id: string;
@@ -570,6 +594,9 @@ interface PackInfo {
570
594
  engram_count: number;
571
595
  manifest?: PackManifest;
572
596
  integrity?: string;
597
+ installed_at?: string;
598
+ source?: string;
599
+ integrity_ok?: boolean;
573
600
  }
574
601
  declare function listPacks(packsDir: string): PackInfo[];
575
602
  interface ExportOptions {
@@ -1432,7 +1459,9 @@ declare class Plur {
1432
1459
  timeline(query?: TimelineQuery): Episode[];
1433
1460
  /** Rule-based extraction of engram candidates from content. */
1434
1461
  ingest(content: string, options?: IngestOptions): IngestCandidate[];
1435
- /** Install a pack from a source path. Detects conflicts with existing engrams. */
1462
+ /** Preview a pack before installing shows manifest, engrams, and security scan. */
1463
+ previewPack(source: string): ReturnType<typeof previewPack>;
1464
+ /** Install a pack from a source path. Runs security scan (blocks on secrets), detects conflicts, records in registry. */
1436
1465
  installPack(source: string): ReturnType<typeof installPack>;
1437
1466
  /** Uninstall a pack by name. */
1438
1467
  uninstallPack(name: string): ReturnType<typeof uninstallPack>;
@@ -1466,4 +1495,4 @@ declare class Plur {
1466
1495
  }>;
1467
1496
  }
1468
1497
 
1469
- export { type AlignmentResult, type Association, type CaptureContext, type DomainCoverage, DomainCoverageSchema, type Engram, type EngramCluster, type Episode, type EvidenceEntry, EvidenceEntrySchema, type ExtractOptions, type ExtractionResult, type Falsification, FalsificationSchema, type HierarchyPosition, HierarchyPositionSchema, IndexedStorage, type IngestCandidate, type IngestOptions, type InjectOptions, type InjectionResult, type KnowledgeAnchor, type LearnContext, type LlmFunction, type MemberAlignment, type MetaConfidence, MetaConfidenceSchema, type MetaField, MetaFieldSchema, PLATITUDE_PATTERNS, type PackManifest, Plur, type PlurConfig, type PlurPaths, type RecallOptions, type RelationalAnalysis, type RelationalTriple, SessionBreadcrumbs, type StatusResult, type StoreEntry, type StructuralTemplate, StructuralTemplateSchema, type SyncResult, type SyncStatus, type TimelineQuery, type TypedRole, type ValidationResult, type VersionCheckResult, alignCluster, analyzeStructure, checkForUpdate, classifyPolarity, clearVersionCache, clusterByStructure, computeConfidence, computeMetaConfidence, confidenceBand, detectPlurStorage, detectSecrets, engramSearchText, extractMetaEngrams, formulateMetaEngram, generateGuardrails, getCachedUpdateCheck, isPlatitude, organizeHierarchy, tokenSimilarity, validateMetaEngram };
1498
+ export { type AlignmentResult, type Association, type CaptureContext, type DomainCoverage, DomainCoverageSchema, type Engram, type EngramCluster, type Episode, type EvidenceEntry, EvidenceEntrySchema, type ExtractOptions, type ExtractionResult, type Falsification, FalsificationSchema, type HierarchyPosition, HierarchyPositionSchema, IndexedStorage, type IngestCandidate, type IngestOptions, type InjectOptions, type InjectionResult, type KnowledgeAnchor, type LearnContext, type LlmFunction, type MemberAlignment, type MetaConfidence, MetaConfidenceSchema, type MetaField, MetaFieldSchema, PLATITUDE_PATTERNS, type PackManifest, Plur, type PlurConfig, type PlurPaths, type PreviewResult, type PrivacyIssue, type PrivacyScanResult, type RecallOptions, type RegistryEntry, type RelationalAnalysis, type RelationalTriple, SessionBreadcrumbs, type StatusResult, type StoreEntry, type StructuralTemplate, StructuralTemplateSchema, type SyncResult, type SyncStatus, type TimelineQuery, type TypedRole, type ValidationResult, type VersionCheckResult, alignCluster, analyzeStructure, checkForUpdate, classifyPolarity, clearVersionCache, clusterByStructure, computeConfidence, computeMetaConfidence, confidenceBand, detectPlurStorage, detectSecrets, engramSearchText, extractMetaEngrams, formulateMetaEngram, generateGuardrails, getCachedUpdateCheck, isPlatitude, organizeHierarchy, tokenSimilarity, validateMetaEngram };
package/dist/index.js CHANGED
@@ -1089,6 +1089,57 @@ function detectSecrets(text) {
1089
1089
  }
1090
1090
 
1091
1091
  // src/packs.ts
1092
+ function registryPath(packsDir) {
1093
+ return path.join(packsDir, "registry.yaml");
1094
+ }
1095
+ function loadRegistry(packsDir) {
1096
+ const p = registryPath(packsDir);
1097
+ if (!fs2.existsSync(p)) return [];
1098
+ try {
1099
+ const raw = yaml4.load(fs2.readFileSync(p, "utf8"));
1100
+ return Array.isArray(raw?.packs) ? raw.packs : [];
1101
+ } catch {
1102
+ return [];
1103
+ }
1104
+ }
1105
+ function saveRegistry(packsDir, entries) {
1106
+ const content = yaml4.dump({ packs: entries }, { lineWidth: 120, noRefs: true, quotingType: '"' });
1107
+ fs2.writeFileSync(registryPath(packsDir), content);
1108
+ }
1109
+ function addToRegistry(packsDir, entry) {
1110
+ const entries = loadRegistry(packsDir);
1111
+ const idx = entries.findIndex((e) => e.name === entry.name);
1112
+ if (idx >= 0) entries[idx] = entry;
1113
+ else entries.push(entry);
1114
+ saveRegistry(packsDir, entries);
1115
+ }
1116
+ function removeFromRegistry(packsDir, name) {
1117
+ const entries = loadRegistry(packsDir).filter((e) => e.name !== name);
1118
+ saveRegistry(packsDir, entries);
1119
+ }
1120
+ function previewPack(source) {
1121
+ if (!fs2.existsSync(source)) throw new Error(`Pack source not found: ${source}`);
1122
+ const pack = loadPack(source);
1123
+ const security = scanPrivacy(pack.engrams);
1124
+ const warnings = [];
1125
+ const globalCount = pack.engrams.filter((e) => e.scope === "global").length;
1126
+ if (globalCount > 0) warnings.push(`${globalCount} engram(s) have global scope \u2014 may interact with your own engrams`);
1127
+ const hotEngrams = pack.engrams.filter((e) => e.activation.retrieval_strength > 0.9);
1128
+ if (hotEngrams.length > 0) warnings.push(`${hotEngrams.length} engram(s) have unusually high retrieval strength (>0.9)`);
1129
+ return {
1130
+ manifest: pack.manifest,
1131
+ engram_count: pack.engrams.length,
1132
+ engrams: pack.engrams.map((e) => ({
1133
+ id: e.id,
1134
+ type: e.type,
1135
+ statement: e.statement,
1136
+ domain: e.domain,
1137
+ tags: e.tags ?? []
1138
+ })),
1139
+ security,
1140
+ warnings
1141
+ };
1142
+ }
1092
1143
  function detectConflicts2(newEngrams, existingEngrams) {
1093
1144
  const conflicts = [];
1094
1145
  for (const ne of newEngrams) {
@@ -1131,6 +1182,13 @@ function detectConflicts2(newEngrams, existingEngrams) {
1131
1182
  }
1132
1183
  function installPack(packsDir, source, existingEngrams) {
1133
1184
  if (!fs2.existsSync(source)) throw new Error(`Pack source not found: ${source}`);
1185
+ const preview = previewPack(source);
1186
+ const secretIssues = preview.security.issues.filter((i) => i.type === "secret");
1187
+ if (secretIssues.length > 0) {
1188
+ const details = secretIssues.map((i) => ` ${i.engram_id}: ${i.detail}`).join("\n");
1189
+ throw new Error(`Pack contains secrets \u2014 install blocked:
1190
+ ${details}`);
1191
+ }
1134
1192
  const sourceName = path.basename(source);
1135
1193
  const destDir = path.join(packsDir, sourceName);
1136
1194
  if (!fs2.existsSync(destDir)) fs2.mkdirSync(destDir, { recursive: true });
@@ -1145,7 +1203,17 @@ function installPack(packsDir, source, existingEngrams) {
1145
1203
  const engramsPath = path.join(destDir, "engrams.yaml");
1146
1204
  const newEngrams = fs2.existsSync(engramsPath) ? loadEngrams(engramsPath) : [];
1147
1205
  const conflicts = existingEngrams ? detectConflicts2(newEngrams, existingEngrams) : [];
1148
- return { installed: newEngrams.length, name: sourceName, conflicts };
1206
+ const integrity = `sha256:${computePackHash(destDir)}`;
1207
+ const registryEntry = {
1208
+ name: preview.manifest.name,
1209
+ installed_at: (/* @__PURE__ */ new Date()).toISOString(),
1210
+ source: path.resolve(source),
1211
+ integrity,
1212
+ version: preview.manifest.version,
1213
+ creator: preview.manifest.creator
1214
+ };
1215
+ addToRegistry(packsDir, registryEntry);
1216
+ return { installed: newEngrams.length, name: sourceName, conflicts, security: preview.security, registry: registryEntry };
1149
1217
  }
1150
1218
  function uninstallPack(packsDir, name) {
1151
1219
  let packDir = path.join(packsDir, name);
@@ -1164,31 +1232,48 @@ function uninstallPack(packsDir, name) {
1164
1232
  count = loadEngrams(engramsPath).length;
1165
1233
  } catch {
1166
1234
  }
1235
+ let manifestName;
1236
+ try {
1237
+ manifestName = loadPack(packDir).manifest.name;
1238
+ } catch {
1239
+ }
1240
+ removeFromRegistry(packsDir, name);
1241
+ if (manifestName && manifestName !== name) removeFromRegistry(packsDir, manifestName);
1167
1242
  fs2.rmSync(packDir, { recursive: true, force: true });
1168
1243
  return { name, removed: true, engram_count: count };
1169
1244
  }
1170
1245
  function listPacks(packsDir) {
1171
1246
  if (!fs2.existsSync(packsDir)) return [];
1247
+ const registry = loadRegistry(packsDir);
1248
+ const registryMap = new Map(registry.map((r) => [r.name, r]));
1172
1249
  const result = [];
1173
1250
  for (const entry of fs2.readdirSync(packsDir)) {
1174
1251
  const packDir = path.join(packsDir, entry);
1175
1252
  if (!fs2.statSync(packDir).isDirectory()) continue;
1176
1253
  try {
1177
1254
  const pack = loadPack(packDir);
1255
+ const currentIntegrity = `sha256:${computePackHash(packDir)}`;
1256
+ const reg = registryMap.get(pack.manifest.name);
1178
1257
  result.push({
1179
1258
  name: pack.manifest.name,
1180
1259
  path: packDir,
1181
1260
  engram_count: pack.engrams.length,
1182
1261
  manifest: pack.manifest,
1183
- integrity: computePackHash(packDir)
1262
+ integrity: currentIntegrity,
1263
+ installed_at: reg?.installed_at,
1264
+ source: reg?.source,
1265
+ integrity_ok: reg ? reg.integrity === currentIntegrity : void 0
1184
1266
  });
1185
1267
  } catch {
1186
1268
  const engramsPath = path.join(packDir, "engrams.yaml");
1187
1269
  const engrams = fs2.existsSync(engramsPath) ? loadEngrams(engramsPath) : [];
1270
+ const reg = registryMap.get(entry);
1188
1271
  result.push({
1189
1272
  name: entry,
1190
1273
  path: packDir,
1191
- engram_count: engrams.length
1274
+ engram_count: engrams.length,
1275
+ installed_at: reg?.installed_at,
1276
+ source: reg?.source
1192
1277
  });
1193
1278
  }
1194
1279
  }
@@ -2217,7 +2302,6 @@ var Plur = class {
2217
2302
  _loadAllEngrams() {
2218
2303
  const primary = this._loadCached(this.paths.engrams);
2219
2304
  const stores = this.config.stores ?? [];
2220
- if (stores.length === 0) return primary;
2221
2305
  const all = [...primary];
2222
2306
  for (const store of stores) {
2223
2307
  const storeEngrams = this._loadCached(store.path);
@@ -2238,6 +2322,15 @@ var Plur = class {
2238
2322
  all.push(cloned);
2239
2323
  }
2240
2324
  }
2325
+ const packs = loadAllPacks(this.paths.packs);
2326
+ for (const pack of packs) {
2327
+ for (const e of pack.engrams) {
2328
+ if (e.status !== "active") continue;
2329
+ const cloned = { ...e };
2330
+ cloned._pack = pack.manifest.name;
2331
+ all.push(cloned);
2332
+ }
2333
+ }
2241
2334
  return all;
2242
2335
  }
2243
2336
  /** Load engrams from a path with mtime-based caching */
@@ -2297,7 +2390,7 @@ var Plur = class {
2297
2390
  consolidated: false,
2298
2391
  type: context?.type ?? "behavioral",
2299
2392
  scope,
2300
- visibility: context?.visibility ?? "private",
2393
+ visibility: context?.visibility ?? (context?.domain ? "public" : "private"),
2301
2394
  statement,
2302
2395
  rationale: context?.rationale,
2303
2396
  source: context?.source,
@@ -2745,7 +2838,11 @@ var Plur = class {
2745
2838
  }
2746
2839
  return candidates;
2747
2840
  }
2748
- /** Install a pack from a source path. Detects conflicts with existing engrams. */
2841
+ /** Preview a pack before installing shows manifest, engrams, and security scan. */
2842
+ previewPack(source) {
2843
+ return previewPack(source);
2844
+ }
2845
+ /** Install a pack from a source path. Runs security scan (blocks on secrets), detects conflicts, records in registry. */
2749
2846
  installPack(source) {
2750
2847
  const existing = this._loadAllEngrams();
2751
2848
  return installPack(this.paths.packs, source, existing);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plur-ai/core",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",