@rolexjs/local-platform 0.12.0-dev-20260302084345 → 0.12.0-dev-20260302114956

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
@@ -1,15 +1,13 @@
1
- import { Platform } from '@rolexjs/core';
2
- import { State } from '@rolexjs/system';
1
+ import { Platform, RoleXRepository, PrototypeRegistry, ContextData } from '@rolexjs/core';
2
+ import { State, Runtime } from '@rolexjs/system';
3
+ import { CommonXDatabase } from '@deepracticex/drizzle';
3
4
 
4
5
  /**
5
6
  * localPlatform — create a Platform backed by SQLite + local filesystem.
6
7
  *
7
8
  * Storage:
8
- * {dataDir}/rolex.db — SQLite database (single source of truth for runtime graph)
9
- * {dataDir}/prototype.json — prototype registry
10
- * {dataDir}/context/<id>.json — role context persistence
9
+ * {dataDir}/rolex.db — SQLite database (all state: nodes, links, prototypes, contexts)
11
10
  *
12
- * Runtime: SQLite-backed via Drizzle ORM (no in-memory Map, no load/save cycle).
13
11
  * When dataDir is null, runs with in-memory SQLite (useful for tests).
14
12
  */
15
13
 
@@ -78,4 +76,21 @@ declare function stateToFiles(state: State): {
78
76
  */
79
77
  declare function filesToState(manifest: Manifest, fileContents: Record<string, string>): State;
80
78
 
81
- export { type FileEntry, type LocalPlatformConfig, type Manifest, type ManifestNode, filesToState, localPlatform, stateToFiles };
79
+ /**
80
+ * SqliteRepository — RoleXRepository backed by SQLite via Drizzle.
81
+ *
82
+ * Single database, four tables: nodes, links, prototypes, contexts.
83
+ * All state in one place — swap the db connection to go from local to cloud.
84
+ */
85
+
86
+ type DB = CommonXDatabase;
87
+ declare class SqliteRepository implements RoleXRepository {
88
+ private db;
89
+ readonly runtime: Runtime;
90
+ readonly prototype: PrototypeRegistry;
91
+ constructor(db: DB);
92
+ saveContext(roleId: string, data: ContextData): void;
93
+ loadContext(roleId: string): ContextData | null;
94
+ }
95
+
96
+ export { type FileEntry, type LocalPlatformConfig, type Manifest, type ManifestNode, SqliteRepository, filesToState, localPlatform, stateToFiles };
package/dist/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  // src/LocalPlatform.ts
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
+ import { mkdirSync } from "fs";
3
3
  import { homedir } from "os";
4
4
  import { join } from "path";
5
5
  import { drizzle } from "@deepracticex/drizzle";
6
6
  import { openDatabase } from "@deepracticex/sqlite";
7
7
  import { NodeProvider } from "@resourcexjs/node-provider";
8
+
9
+ // src/SqliteRepository.ts
8
10
  import { sql } from "drizzle-orm";
9
- import { createResourceX, setProvider } from "resourcexjs";
10
11
 
11
12
  // src/sqliteRuntime.ts
12
13
  import { and, eq, isNull } from "drizzle-orm";
@@ -197,30 +198,88 @@ function createSqliteRuntime(db) {
197
198
  };
198
199
  }
199
200
 
200
- // src/LocalPlatform.ts
201
- var CREATE_NODES = sql`CREATE TABLE IF NOT EXISTS nodes (
202
- ref TEXT PRIMARY KEY,
203
- id TEXT,
204
- alias TEXT,
205
- name TEXT NOT NULL,
206
- description TEXT DEFAULT '',
207
- parent_ref TEXT REFERENCES nodes(ref),
208
- information TEXT,
209
- tag TEXT
210
- )`;
211
- var CREATE_LINKS = sql`CREATE TABLE IF NOT EXISTS links (
212
- from_ref TEXT NOT NULL REFERENCES nodes(ref),
213
- to_ref TEXT NOT NULL REFERENCES nodes(ref),
214
- relation TEXT NOT NULL,
215
- PRIMARY KEY (from_ref, to_ref, relation)
216
- )`;
217
- var CREATE_INDEXES = [
201
+ // src/SqliteRepository.ts
202
+ var DDL = [
203
+ sql`CREATE TABLE IF NOT EXISTS nodes (
204
+ ref TEXT PRIMARY KEY,
205
+ id TEXT,
206
+ alias TEXT,
207
+ name TEXT NOT NULL,
208
+ description TEXT DEFAULT '',
209
+ parent_ref TEXT REFERENCES nodes(ref),
210
+ information TEXT,
211
+ tag TEXT
212
+ )`,
213
+ sql`CREATE TABLE IF NOT EXISTS links (
214
+ from_ref TEXT NOT NULL REFERENCES nodes(ref),
215
+ to_ref TEXT NOT NULL REFERENCES nodes(ref),
216
+ relation TEXT NOT NULL,
217
+ PRIMARY KEY (from_ref, to_ref, relation)
218
+ )`,
219
+ sql`CREATE TABLE IF NOT EXISTS prototypes (
220
+ id TEXT PRIMARY KEY,
221
+ source TEXT NOT NULL
222
+ )`,
223
+ sql`CREATE TABLE IF NOT EXISTS contexts (
224
+ role_id TEXT PRIMARY KEY,
225
+ focused_goal_id TEXT,
226
+ focused_plan_id TEXT
227
+ )`,
228
+ // Indexes
218
229
  sql`CREATE INDEX IF NOT EXISTS idx_nodes_id ON nodes(id)`,
219
230
  sql`CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)`,
220
231
  sql`CREATE INDEX IF NOT EXISTS idx_nodes_parent_ref ON nodes(parent_ref)`,
221
232
  sql`CREATE INDEX IF NOT EXISTS idx_links_from ON links(from_ref)`,
222
233
  sql`CREATE INDEX IF NOT EXISTS idx_links_to ON links(to_ref)`
223
234
  ];
235
+ var SqliteRepository = class {
236
+ constructor(db) {
237
+ this.db = db;
238
+ for (const stmt of DDL) {
239
+ db.run(stmt);
240
+ }
241
+ this.runtime = createSqliteRuntime(db);
242
+ this.prototype = createPrototypeRegistry(db);
243
+ }
244
+ runtime;
245
+ prototype;
246
+ saveContext(roleId, data) {
247
+ this.db.run(
248
+ sql`INSERT OR REPLACE INTO contexts (role_id, focused_goal_id, focused_plan_id)
249
+ VALUES (${roleId}, ${data.focusedGoalId}, ${data.focusedPlanId})`
250
+ );
251
+ }
252
+ loadContext(roleId) {
253
+ const row = this.db.all(
254
+ sql`SELECT role_id, focused_goal_id, focused_plan_id FROM contexts WHERE role_id = ${roleId}`
255
+ );
256
+ if (row.length === 0) return null;
257
+ return {
258
+ focusedGoalId: row[0].focused_goal_id,
259
+ focusedPlanId: row[0].focused_plan_id
260
+ };
261
+ }
262
+ };
263
+ function createPrototypeRegistry(db) {
264
+ return {
265
+ settle(id, source) {
266
+ db.run(sql`INSERT OR REPLACE INTO prototypes (id, source) VALUES (${id}, ${source})`);
267
+ },
268
+ evict(id) {
269
+ db.run(sql`DELETE FROM prototypes WHERE id = ${id}`);
270
+ },
271
+ list() {
272
+ const rows = db.all(sql`SELECT id, source FROM prototypes`);
273
+ const result = {};
274
+ for (const row of rows) {
275
+ result[row.id] = row.source;
276
+ }
277
+ return result;
278
+ }
279
+ };
280
+ }
281
+
282
+ // src/LocalPlatform.ts
224
283
  function deepracticeHome() {
225
284
  return process.env.DEEPRACTICE_HOME ?? join(homedir(), ".deepractice");
226
285
  }
@@ -235,70 +294,17 @@ function localPlatform(config = {}) {
235
294
  }
236
295
  const rawDb = openDatabase(dbPath);
237
296
  const db = drizzle(rawDb);
238
- db.run(CREATE_NODES);
239
- db.run(CREATE_LINKS);
240
- for (const idx of CREATE_INDEXES) {
241
- db.run(idx);
242
- }
243
- const runtime = createSqliteRuntime(db);
244
- let resourcex;
245
- if (config.resourceDir !== null) {
246
- setProvider(new NodeProvider());
247
- resourcex = createResourceX({
248
- path: config.resourceDir ?? join(deepracticeHome(), "resourcex")
249
- });
250
- }
251
- const registryPath = dataDir ? join(dataDir, "prototype.json") : void 0;
252
- const readRegistry = () => {
253
- if (registryPath && existsSync(registryPath)) {
254
- return JSON.parse(readFileSync(registryPath, "utf-8"));
255
- }
256
- return {};
257
- };
258
- const writeRegistry = (registry) => {
259
- if (!registryPath) return;
260
- mkdirSync(dataDir, { recursive: true });
261
- writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf-8");
262
- };
263
- const prototype = {
264
- settle(id, source) {
265
- const registry = readRegistry();
266
- registry[id] = source;
267
- writeRegistry(registry);
268
- },
269
- evict(id) {
270
- const registry = readRegistry();
271
- delete registry[id];
272
- writeRegistry(registry);
273
- },
274
- list() {
275
- return readRegistry();
276
- }
277
- };
297
+ const repository = new SqliteRepository(db);
298
+ const resourcexProvider = config.resourceDir !== null ? new NodeProvider() : void 0;
278
299
  const initializer = {
279
300
  async bootstrap() {
280
301
  }
281
302
  };
282
- const saveContext = (roleId, data) => {
283
- if (!dataDir) return;
284
- const contextDir = join(dataDir, "context");
285
- mkdirSync(contextDir, { recursive: true });
286
- writeFileSync(join(contextDir, `${roleId}.json`), JSON.stringify(data, null, 2), "utf-8");
287
- };
288
- const loadContext = (roleId) => {
289
- if (!dataDir) return null;
290
- const contextPath = join(dataDir, "context", `${roleId}.json`);
291
- if (!existsSync(contextPath)) return null;
292
- return JSON.parse(readFileSync(contextPath, "utf-8"));
293
- };
294
303
  return {
295
- runtime,
296
- prototype,
297
- resourcex,
304
+ repository,
305
+ resourcexProvider,
298
306
  initializer,
299
- bootstrap: config.bootstrap,
300
- saveContext,
301
- loadContext
307
+ bootstrap: config.bootstrap
302
308
  };
303
309
  }
304
310
 
@@ -432,6 +438,7 @@ function filesToState(manifest, fileContents) {
432
438
  };
433
439
  }
434
440
  export {
441
+ SqliteRepository,
435
442
  filesToState,
436
443
  localPlatform,
437
444
  stateToFiles
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LocalPlatform.ts","../src/sqliteRuntime.ts","../src/schema.ts","../src/manifest.ts"],"sourcesContent":["/**\n * localPlatform — create a Platform backed by SQLite + local filesystem.\n *\n * Storage:\n * {dataDir}/rolex.db — SQLite database (single source of truth for runtime graph)\n * {dataDir}/prototype.json — prototype registry\n * {dataDir}/context/<id>.json — role context persistence\n *\n * Runtime: SQLite-backed via Drizzle ORM (no in-memory Map, no load/save cycle).\n * When dataDir is null, runs with in-memory SQLite (useful for tests).\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { drizzle } from \"@deepracticex/drizzle\";\nimport { openDatabase } from \"@deepracticex/sqlite\";\nimport { NodeProvider } from \"@resourcexjs/node-provider\";\nimport type { ContextData, Platform } from \"@rolexjs/core\";\nimport type { Initializer } from \"@rolexjs/system\";\nimport { sql } from \"drizzle-orm\";\nimport { createResourceX, setProvider } from \"resourcexjs\";\nimport { createSqliteRuntime } from \"./sqliteRuntime.js\";\n\n// ===== Config =====\n\nexport interface LocalPlatformConfig {\n /** Directory for persistent storage. Defaults to ~/.deepractice/rolex. Set to null for in-memory only. */\n dataDir?: string | null;\n /** Directory for ResourceX storage. Defaults to ~/.deepractice/resourcex. Set to null to disable. */\n resourceDir?: string | null;\n /** Prototype sources to settle on genesis. */\n bootstrap?: string[];\n}\n\n// ===== DDL =====\n\nconst CREATE_NODES = sql`CREATE TABLE IF NOT EXISTS nodes (\n ref TEXT PRIMARY KEY,\n id TEXT,\n alias TEXT,\n name TEXT NOT NULL,\n description TEXT DEFAULT '',\n parent_ref TEXT REFERENCES nodes(ref),\n information TEXT,\n tag TEXT\n)`;\n\nconst CREATE_LINKS = sql`CREATE TABLE IF NOT EXISTS links (\n from_ref TEXT NOT NULL REFERENCES nodes(ref),\n to_ref TEXT NOT NULL REFERENCES nodes(ref),\n relation TEXT NOT NULL,\n PRIMARY KEY (from_ref, to_ref, relation)\n)`;\n\nconst CREATE_INDEXES = [\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_id ON nodes(id)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_parent_ref ON nodes(parent_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_from ON links(from_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_to ON links(to_ref)`,\n];\n\n// ===== Factory =====\n\n/** Resolve the DEEPRACTICE_HOME base directory. Env > default (~/.deepractice). */\nfunction deepracticeHome(): string {\n return process.env.DEEPRACTICE_HOME ?? join(homedir(), \".deepractice\");\n}\n\n/** Create a local Platform. Persistent by default ($DEEPRACTICE_HOME/rolex), in-memory if dataDir is null. */\nexport function localPlatform(config: LocalPlatformConfig = {}): Platform {\n const dataDir =\n config.dataDir === null ? undefined : (config.dataDir ?? join(deepracticeHome(), \"rolex\"));\n\n // ===== SQLite database =====\n\n let dbPath: string;\n if (dataDir) {\n mkdirSync(dataDir, { recursive: true });\n dbPath = join(dataDir, \"rolex.db\");\n } else {\n dbPath = \":memory:\";\n }\n\n const rawDb = openDatabase(dbPath);\n const db = drizzle(rawDb);\n\n // Ensure tables exist\n db.run(CREATE_NODES);\n db.run(CREATE_LINKS);\n for (const idx of CREATE_INDEXES) {\n db.run(idx);\n }\n\n // ===== Runtime =====\n\n const runtime = createSqliteRuntime(db);\n\n // ===== ResourceX =====\n\n let resourcex: ReturnType<typeof createResourceX> | undefined;\n if (config.resourceDir !== null) {\n setProvider(new NodeProvider());\n resourcex = createResourceX({\n path: config.resourceDir ?? join(deepracticeHome(), \"resourcex\"),\n });\n }\n\n // ===== Prototype registry =====\n\n const registryPath = dataDir ? join(dataDir, \"prototype.json\") : undefined;\n\n const readRegistry = (): Record<string, string> => {\n if (registryPath && existsSync(registryPath)) {\n return JSON.parse(readFileSync(registryPath, \"utf-8\"));\n }\n return {};\n };\n\n const writeRegistry = (registry: Record<string, string>): void => {\n if (!registryPath) return;\n mkdirSync(dataDir!, { recursive: true });\n writeFileSync(registryPath, JSON.stringify(registry, null, 2), \"utf-8\");\n };\n\n const prototype = {\n settle(id: string, source: string) {\n const registry = readRegistry();\n registry[id] = source;\n writeRegistry(registry);\n },\n\n evict(id: string) {\n const registry = readRegistry();\n delete registry[id];\n writeRegistry(registry);\n },\n\n list(): Record<string, string> {\n return readRegistry();\n },\n };\n\n // ===== Initializer =====\n\n const initializer: Initializer = {\n async bootstrap() {},\n };\n\n // ===== Context persistence =====\n\n const saveContext = (roleId: string, data: ContextData): void => {\n if (!dataDir) return;\n const contextDir = join(dataDir, \"context\");\n mkdirSync(contextDir, { recursive: true });\n writeFileSync(join(contextDir, `${roleId}.json`), JSON.stringify(data, null, 2), \"utf-8\");\n };\n\n const loadContext = (roleId: string): ContextData | null => {\n if (!dataDir) return null;\n const contextPath = join(dataDir, \"context\", `${roleId}.json`);\n if (!existsSync(contextPath)) return null;\n return JSON.parse(readFileSync(contextPath, \"utf-8\"));\n };\n\n return {\n runtime,\n prototype,\n resourcex,\n initializer,\n bootstrap: config.bootstrap,\n saveContext,\n loadContext,\n };\n}\n","/**\n * SQLite-backed Runtime — single source of truth.\n *\n * Every operation reads/writes directly to SQLite.\n * No in-memory Map, no load/save cycle, no stale refs.\n */\n\nimport type { CommonXDatabase } from \"@deepracticex/drizzle\";\nimport type { Runtime, State, Structure } from \"@rolexjs/system\";\nimport { and, eq, isNull } from \"drizzle-orm\";\nimport { links, nodes } from \"./schema.js\";\n\ntype DB = CommonXDatabase;\n\n// ===== Helpers =====\n\nfunction nextRef(db: DB): string {\n const max = db\n .select({ ref: nodes.ref })\n .from(nodes)\n .all()\n .reduce((max, r) => {\n const n = parseInt(r.ref.slice(1), 10);\n return Number.isNaN(n) ? max : Math.max(max, n);\n }, 0);\n return `n${max + 1}`;\n}\n\nfunction toStructure(row: typeof nodes.$inferSelect): Structure {\n return {\n ref: row.ref,\n ...(row.id ? { id: row.id } : {}),\n ...(row.alias ? { alias: JSON.parse(row.alias) } : {}),\n name: row.name,\n description: row.description ?? \"\",\n parent: null, // Runtime doesn't use parent as Structure; tree is via parentRef\n ...(row.information ? { information: row.information } : {}),\n ...(row.tag ? { tag: row.tag } : {}),\n };\n}\n\n// ===== Projection =====\n\nfunction projectNode(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n\n const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();\n\n const nodeLinks = db.select().from(links).where(eq(links.fromRef, ref)).all();\n\n return {\n ...toStructure(row),\n children: children.map((c) => projectNode(db, c.ref)),\n ...(nodeLinks.length > 0\n ? {\n links: nodeLinks.map((l) => ({\n relation: l.relation,\n target: projectLinked(db, l.toRef),\n })),\n }\n : {}),\n };\n}\n\n/** Project a node with full subtree but without following links (prevents cycles). */\nfunction projectLinked(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();\n return {\n ...toStructure(row),\n children: children.map((c) => projectLinked(db, c.ref)),\n };\n}\n\n// ===== Subtree removal =====\n\nfunction removeSubtree(db: DB, ref: string): void {\n // Remove children first (depth-first)\n const children = db.select({ ref: nodes.ref }).from(nodes).where(eq(nodes.parentRef, ref)).all();\n for (const child of children) {\n removeSubtree(db, child.ref);\n }\n\n // Remove links from/to this node\n db.delete(links).where(eq(links.fromRef, ref)).run();\n db.delete(links).where(eq(links.toRef, ref)).run();\n\n // Remove the node itself\n db.delete(nodes).where(eq(nodes.ref, ref)).run();\n}\n\n// ===== Runtime factory =====\n\nexport function createSqliteRuntime(db: DB): Runtime {\n return {\n create(parent, type, information, id, alias) {\n // Idempotent: same id under same parent → return existing.\n if (id) {\n const existing = db\n .select()\n .from(nodes)\n .where(and(eq(nodes.id, id), eq(nodes.parentRef, parent?.ref ?? null)))\n .get();\n if (existing) return toStructure(existing);\n }\n const ref = nextRef(db);\n db.insert(nodes)\n .values({\n ref,\n id: id ?? null,\n alias: alias && alias.length > 0 ? JSON.stringify(alias) : null,\n name: type.name,\n description: type.description,\n parentRef: parent?.ref ?? null,\n information: information ?? null,\n tag: null,\n })\n .run();\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, ref)).get()!);\n },\n\n remove(node) {\n if (!node.ref) return;\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) return;\n\n // Detach from parent's children (implicit via parentRef)\n removeSubtree(db, node.ref);\n },\n\n transform(source, target, information) {\n if (!source.ref) throw new Error(\"Source node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, source.ref)).get();\n if (!row) throw new Error(`Source node not found: ${source.ref}`);\n\n const targetParent = target.parent;\n if (!targetParent) {\n throw new Error(`Cannot transform to root structure: ${target.name}`);\n }\n\n const parentRow = db.select().from(nodes).where(eq(nodes.name, targetParent.name)).get();\n if (!parentRow) {\n throw new Error(`No node found for structure: ${targetParent.name}`);\n }\n\n // Reparent + update type in place — subtree preserved\n db.update(nodes)\n .set({\n parentRef: parentRow.ref,\n name: target.name,\n description: target.description,\n ...(information !== undefined ? { information } : {}),\n })\n .where(eq(nodes.ref, source.ref))\n .run();\n\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, source.ref)).get()!);\n },\n\n link(from, to, relationName, reverseName) {\n if (!from.ref) throw new Error(\"Source node has no ref\");\n if (!to.ref) throw new Error(\"Target node has no ref\");\n\n // Forward: from → to\n const existsForward = db\n .select()\n .from(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .get();\n if (!existsForward) {\n db.insert(links).values({ fromRef: from.ref, toRef: to.ref, relation: relationName }).run();\n }\n\n // Reverse: to → from\n const existsReverse = db\n .select()\n .from(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .get();\n if (!existsReverse) {\n db.insert(links).values({ fromRef: to.ref, toRef: from.ref, relation: reverseName }).run();\n }\n },\n\n unlink(from, to, relationName, reverseName) {\n if (!from.ref || !to.ref) return;\n\n db.delete(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .run();\n\n db.delete(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .run();\n },\n\n tag(node, tagValue) {\n if (!node.ref) throw new Error(\"Node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) throw new Error(`Node not found: ${node.ref}`);\n db.update(nodes).set({ tag: tagValue }).where(eq(nodes.ref, node.ref)).run();\n },\n\n project(node) {\n if (!node.ref) throw new Error(`Node has no ref`);\n return projectNode(db, node.ref);\n },\n\n roots() {\n const rows = db.select().from(nodes).where(isNull(nodes.parentRef)).all();\n return rows.map(toStructure);\n },\n };\n}\n","/**\n * Drizzle schema — SQLite tables for the RoleX runtime graph.\n *\n * Two tables:\n * nodes — tree backbone (Structure instances)\n * links — cross-branch relations (bidirectional)\n */\n\nimport { index, primaryKey, sqliteTable, text } from \"drizzle-orm/sqlite-core\";\n\n/**\n * nodes — every node in the society graph.\n *\n * Maps 1:1 to the Structure interface:\n * ref → graph-internal reference (primary key)\n * id → user-facing kebab-case identifier\n * alias → JSON array of alternative names\n * name → structure type (\"individual\", \"goal\", \"task\", etc.)\n * description → what this structure is\n * parent_ref → tree parent (self-referencing foreign key)\n * information → Gherkin Feature source text\n * tag → generic label (\"done\", \"abandoned\")\n */\nexport const nodes = sqliteTable(\n \"nodes\",\n {\n ref: text(\"ref\").primaryKey(),\n id: text(\"id\"),\n alias: text(\"alias\"), // JSON array: '[\"Sean\",\"姜山\"]'\n name: text(\"name\").notNull(),\n description: text(\"description\").default(\"\"),\n parentRef: text(\"parent_ref\").references((): any => nodes.ref),\n information: text(\"information\"),\n tag: text(\"tag\"),\n },\n (table) => [\n index(\"idx_nodes_id\").on(table.id),\n index(\"idx_nodes_name\").on(table.name),\n index(\"idx_nodes_parent_ref\").on(table.parentRef),\n ]\n);\n\n/**\n * links — cross-branch relations between nodes.\n *\n * Bidirectional: if A→B is \"membership\", B→A is \"belong\".\n * Both directions stored as separate rows.\n */\nexport const links = sqliteTable(\n \"links\",\n {\n fromRef: text(\"from_ref\")\n .notNull()\n .references(() => nodes.ref),\n toRef: text(\"to_ref\")\n .notNull()\n .references(() => nodes.ref),\n relation: text(\"relation\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.fromRef, table.toRef, table.relation] }),\n index(\"idx_links_from\").on(table.fromRef),\n index(\"idx_links_to\").on(table.toRef),\n ]\n);\n","/**\n * Manifest — file-based storage format for RoleX entities.\n *\n * Storage layout:\n * role/<id>/\n * individual.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * organization/<id>/\n * organization.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * Rules:\n * - Directories: only role/ and organization/ at top level\n * - Files: all [id].[type].feature, flat within the entity directory\n * - Manifest: tree structure in JSON, content in .feature files\n * - Nodes without explicit id default to their type name\n */\n\nimport type { State } from \"@rolexjs/system\";\n\n// ===== Manifest types =====\n\n/** A node in the manifest tree. */\nexport interface ManifestNode {\n readonly type: string;\n readonly ref?: string;\n readonly tag?: string;\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n/** Root manifest for an entity (individual or organization). */\nexport interface Manifest {\n readonly id: string;\n readonly type: string;\n readonly ref?: string;\n readonly alias?: readonly string[];\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n// ===== State → files =====\n\nexport interface FileEntry {\n readonly path: string;\n readonly content: string;\n}\n\n/**\n * Convert a State tree to a manifest + feature files.\n * Returns the manifest and a list of file entries (path → content).\n */\nexport function stateToFiles(state: State): { manifest: Manifest; files: FileEntry[] } {\n const files: FileEntry[] = [];\n\n const collectFiles = (node: State, nodeId: string) => {\n if (node.information) {\n files.push({\n path: `${nodeId}.${node.name}.feature`,\n content: node.information,\n });\n }\n if (node.children) {\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n collectFiles(child, childId);\n }\n }\n };\n\n const rootId = state.id ?? state.name;\n collectFiles(state, rootId);\n\n const buildManifestNode = (node: State): ManifestNode => {\n const entry: ManifestNode = {\n type: node.name,\n ...(node.ref ? { ref: node.ref } : {}),\n ...(node.tag ? { tag: node.tag } : {}),\n ...(node.links && node.links.length > 0 ? { links: buildManifestLinks(node.links) } : {}),\n };\n if (node.children && node.children.length > 0) {\n const children: Record<string, ManifestNode> = {};\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n children[childId] = buildManifestNode(child);\n }\n return { ...entry, children };\n }\n return entry;\n };\n\n const manifestNode = buildManifestNode(state);\n\n const manifest: Manifest = {\n id: rootId,\n type: state.name,\n ...(state.ref ? { ref: state.ref } : {}),\n ...(state.alias ? { alias: state.alias } : {}),\n ...(manifestNode.children ? { children: manifestNode.children } : {}),\n ...(state.links && state.links.length > 0\n ? {\n links: buildManifestLinks(state.links),\n }\n : {}),\n };\n\n return { manifest, files };\n}\n\nfunction buildManifestLinks(\n links: readonly { readonly relation: string; readonly target: State }[]\n): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const link of links) {\n const targetId = link.target.id ?? link.target.name;\n if (!result[link.relation]) {\n result[link.relation] = [];\n }\n result[link.relation].push(targetId);\n }\n return result;\n}\n\n// ===== Files → State =====\n\n/**\n * Convert a manifest + feature file contents to a State tree.\n * fileContents maps filename (e.g. \"role-creation.principle.feature\") to Gherkin text.\n */\nexport function filesToState(manifest: Manifest, fileContents: Record<string, string>): State {\n const buildState = (id: string, node: ManifestNode): State => {\n const filename = `${id}.${node.type}.feature`;\n const information = fileContents[filename];\n\n const children: State[] = [];\n if (node.children) {\n for (const [childId, childNode] of Object.entries(node.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const nodeLinks: { relation: string; target: State }[] = [];\n if (node.links) {\n for (const [relation, targetIds] of Object.entries(node.links)) {\n for (const targetId of targetIds) {\n nodeLinks.push({\n relation,\n target: { id: targetId, name: \"\", description: \"\", parent: null },\n });\n }\n }\n }\n\n return {\n ...(node.ref ? { ref: node.ref } : {}),\n id,\n name: node.type,\n description: \"\",\n parent: null,\n ...(node.tag ? { tag: node.tag } : {}),\n ...(information ? { information } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(nodeLinks.length > 0 ? { links: nodeLinks } : {}),\n };\n };\n\n const rootFilename = `${manifest.id}.${manifest.type}.feature`;\n const rootInformation = fileContents[rootFilename];\n\n const children: State[] = [];\n if (manifest.children) {\n for (const [childId, childNode] of Object.entries(manifest.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const links: { relation: string; target: State }[] = [];\n if (manifest.links) {\n for (const [relation, targetIds] of Object.entries(manifest.links)) {\n for (const targetId of targetIds) {\n links.push({\n relation,\n target: {\n id: targetId,\n name: \"\",\n description: \"\",\n parent: null,\n },\n });\n }\n }\n }\n\n return {\n ...(manifest.ref ? { ref: manifest.ref } : {}),\n id: manifest.id,\n ...(manifest.alias ? { alias: manifest.alias } : {}),\n name: manifest.type,\n description: \"\",\n parent: null,\n ...(rootInformation ? { information: rootInformation } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(links.length > 0 ? { links } : {}),\n };\n}\n"],"mappings":";AAYA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAG7B,SAAS,WAAW;AACpB,SAAS,iBAAiB,mBAAmB;;;ACZ7C,SAAS,KAAK,IAAI,cAAc;;;ACDhC,SAAS,OAAO,YAAY,aAAa,YAAY;AAe9C,IAAM,QAAQ;AAAA,EACnB;AAAA,EACA;AAAA,IACE,KAAK,KAAK,KAAK,EAAE,WAAW;AAAA,IAC5B,IAAI,KAAK,IAAI;AAAA,IACb,OAAO,KAAK,OAAO;AAAA;AAAA,IACnB,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,aAAa,KAAK,aAAa,EAAE,QAAQ,EAAE;AAAA,IAC3C,WAAW,KAAK,YAAY,EAAE,WAAW,MAAW,MAAM,GAAG;AAAA,IAC7D,aAAa,KAAK,aAAa;AAAA,IAC/B,KAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EACA,CAAC,UAAU;AAAA,IACT,MAAM,cAAc,EAAE,GAAG,MAAM,EAAE;AAAA,IACjC,MAAM,gBAAgB,EAAE,GAAG,MAAM,IAAI;AAAA,IACrC,MAAM,sBAAsB,EAAE,GAAG,MAAM,SAAS;AAAA,EAClD;AACF;AAQO,IAAM,QAAQ;AAAA,EACnB;AAAA,EACA;AAAA,IACE,SAAS,KAAK,UAAU,EACrB,QAAQ,EACR,WAAW,MAAM,MAAM,GAAG;AAAA,IAC7B,OAAO,KAAK,QAAQ,EACjB,QAAQ,EACR,WAAW,MAAM,MAAM,GAAG;AAAA,IAC7B,UAAU,KAAK,UAAU,EAAE,QAAQ;AAAA,EACrC;AAAA,EACA,CAAC,UAAU;AAAA,IACT,WAAW,EAAE,SAAS,CAAC,MAAM,SAAS,MAAM,OAAO,MAAM,QAAQ,EAAE,CAAC;AAAA,IACpE,MAAM,gBAAgB,EAAE,GAAG,MAAM,OAAO;AAAA,IACxC,MAAM,cAAc,EAAE,GAAG,MAAM,KAAK;AAAA,EACtC;AACF;;;ADhDA,SAAS,QAAQ,IAAgB;AAC/B,QAAM,MAAM,GACT,OAAO,EAAE,KAAK,MAAM,IAAI,CAAC,EACzB,KAAK,KAAK,EACV,IAAI,EACJ,OAAO,CAACA,MAAK,MAAM;AAClB,UAAM,IAAI,SAAS,EAAE,IAAI,MAAM,CAAC,GAAG,EAAE;AACrC,WAAO,OAAO,MAAM,CAAC,IAAIA,OAAM,KAAK,IAAIA,MAAK,CAAC;AAAA,EAChD,GAAG,CAAC;AACN,SAAO,IAAI,MAAM,CAAC;AACpB;AAEA,SAAS,YAAY,KAA2C;AAC9D,SAAO;AAAA,IACL,KAAK,IAAI;AAAA,IACT,GAAI,IAAI,KAAK,EAAE,IAAI,IAAI,GAAG,IAAI,CAAC;AAAA,IAC/B,GAAI,IAAI,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,KAAK,EAAE,IAAI,CAAC;AAAA,IACpD,MAAM,IAAI;AAAA,IACV,aAAa,IAAI,eAAe;AAAA,IAChC,QAAQ;AAAA;AAAA,IACR,GAAI,IAAI,cAAc,EAAE,aAAa,IAAI,YAAY,IAAI,CAAC;AAAA,IAC1D,GAAI,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC;AAAA,EACpC;AACF;AAIA,SAAS,YAAY,IAAQ,KAAoB;AAC/C,QAAM,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI;AAClE,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB,GAAG,EAAE;AAElD,QAAM,WAAW,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,WAAW,GAAG,CAAC,EAAE,IAAI;AAE7E,QAAM,YAAY,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI;AAE5E,SAAO;AAAA,IACL,GAAG,YAAY,GAAG;AAAA,IAClB,UAAU,SAAS,IAAI,CAAC,MAAM,YAAY,IAAI,EAAE,GAAG,CAAC;AAAA,IACpD,GAAI,UAAU,SAAS,IACnB;AAAA,MACE,OAAO,UAAU,IAAI,CAAC,OAAO;AAAA,QAC3B,UAAU,EAAE;AAAA,QACZ,QAAQ,cAAc,IAAI,EAAE,KAAK;AAAA,MACnC,EAAE;AAAA,IACJ,IACA,CAAC;AAAA,EACP;AACF;AAGA,SAAS,cAAc,IAAQ,KAAoB;AACjD,QAAM,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI;AAClE,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB,GAAG,EAAE;AAClD,QAAM,WAAW,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,WAAW,GAAG,CAAC,EAAE,IAAI;AAC7E,SAAO;AAAA,IACL,GAAG,YAAY,GAAG;AAAA,IAClB,UAAU,SAAS,IAAI,CAAC,MAAM,cAAc,IAAI,EAAE,GAAG,CAAC;AAAA,EACxD;AACF;AAIA,SAAS,cAAc,IAAQ,KAAmB;AAEhD,QAAM,WAAW,GAAG,OAAO,EAAE,KAAK,MAAM,IAAI,CAAC,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,WAAW,GAAG,CAAC,EAAE,IAAI;AAC/F,aAAW,SAAS,UAAU;AAC5B,kBAAc,IAAI,MAAM,GAAG;AAAA,EAC7B;AAGA,KAAG,OAAO,KAAK,EAAE,MAAM,GAAG,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI;AACnD,KAAG,OAAO,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI;AAGjD,KAAG,OAAO,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI;AACjD;AAIO,SAAS,oBAAoB,IAAiB;AACnD,SAAO;AAAA,IACL,OAAO,QAAQ,MAAM,aAAa,IAAI,OAAO;AAE3C,UAAI,IAAI;AACN,cAAM,WAAW,GACd,OAAO,EACP,KAAK,KAAK,EACV,MAAM,IAAI,GAAG,MAAM,IAAI,EAAE,GAAG,GAAG,MAAM,WAAW,QAAQ,OAAO,IAAI,CAAC,CAAC,EACrE,IAAI;AACP,YAAI,SAAU,QAAO,YAAY,QAAQ;AAAA,MAC3C;AACA,YAAM,MAAM,QAAQ,EAAE;AACtB,SAAG,OAAO,KAAK,EACZ,OAAO;AAAA,QACN;AAAA,QACA,IAAI,MAAM;AAAA,QACV,OAAO,SAAS,MAAM,SAAS,IAAI,KAAK,UAAU,KAAK,IAAI;AAAA,QAC3D,MAAM,KAAK;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,WAAW,QAAQ,OAAO;AAAA,QAC1B,aAAa,eAAe;AAAA,QAC5B,KAAK;AAAA,MACP,CAAC,EACA,IAAI;AACP,aAAO,YAAY,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI,CAAE;AAAA,IAC7E;AAAA,IAEA,OAAO,MAAM;AACX,UAAI,CAAC,KAAK,IAAK;AACf,YAAM,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI;AACvE,UAAI,CAAC,IAAK;AAGV,oBAAc,IAAI,KAAK,GAAG;AAAA,IAC5B;AAAA,IAEA,UAAU,QAAQ,QAAQ,aAAa;AACrC,UAAI,CAAC,OAAO,IAAK,OAAM,IAAI,MAAM,wBAAwB;AACzD,YAAM,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,OAAO,GAAG,CAAC,EAAE,IAAI;AACzE,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,0BAA0B,OAAO,GAAG,EAAE;AAEhE,YAAM,eAAe,OAAO;AAC5B,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,MAAM,uCAAuC,OAAO,IAAI,EAAE;AAAA,MACtE;AAEA,YAAM,YAAY,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,MAAM,aAAa,IAAI,CAAC,EAAE,IAAI;AACvF,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,gCAAgC,aAAa,IAAI,EAAE;AAAA,MACrE;AAGA,SAAG,OAAO,KAAK,EACZ,IAAI;AAAA,QACH,WAAW,UAAU;AAAA,QACrB,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,MACrD,CAAC,EACA,MAAM,GAAG,MAAM,KAAK,OAAO,GAAG,CAAC,EAC/B,IAAI;AAEP,aAAO,YAAY,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,OAAO,GAAG,CAAC,EAAE,IAAI,CAAE;AAAA,IACpF;AAAA,IAEA,KAAK,MAAM,IAAI,cAAc,aAAa;AACxC,UAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,wBAAwB;AACvD,UAAI,CAAC,GAAG,IAAK,OAAM,IAAI,MAAM,wBAAwB;AAGrD,YAAM,gBAAgB,GACnB,OAAO,EACP,KAAK,KAAK,EACV;AAAA,QACC;AAAA,UACE,GAAG,MAAM,SAAS,KAAK,GAAG;AAAA,UAC1B,GAAG,MAAM,OAAO,GAAG,GAAG;AAAA,UACtB,GAAG,MAAM,UAAU,YAAY;AAAA,QACjC;AAAA,MACF,EACC,IAAI;AACP,UAAI,CAAC,eAAe;AAClB,WAAG,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,KAAK,KAAK,OAAO,GAAG,KAAK,UAAU,aAAa,CAAC,EAAE,IAAI;AAAA,MAC5F;AAGA,YAAM,gBAAgB,GACnB,OAAO,EACP,KAAK,KAAK,EACV;AAAA,QACC,IAAI,GAAG,MAAM,SAAS,GAAG,GAAG,GAAG,GAAG,MAAM,OAAO,KAAK,GAAG,GAAG,GAAG,MAAM,UAAU,WAAW,CAAC;AAAA,MAC3F,EACC,IAAI;AACP,UAAI,CAAC,eAAe;AAClB,WAAG,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,GAAG,KAAK,OAAO,KAAK,KAAK,UAAU,YAAY,CAAC,EAAE,IAAI;AAAA,MAC3F;AAAA,IACF;AAAA,IAEA,OAAO,MAAM,IAAI,cAAc,aAAa;AAC1C,UAAI,CAAC,KAAK,OAAO,CAAC,GAAG,IAAK;AAE1B,SAAG,OAAO,KAAK,EACZ;AAAA,QACC;AAAA,UACE,GAAG,MAAM,SAAS,KAAK,GAAG;AAAA,UAC1B,GAAG,MAAM,OAAO,GAAG,GAAG;AAAA,UACtB,GAAG,MAAM,UAAU,YAAY;AAAA,QACjC;AAAA,MACF,EACC,IAAI;AAEP,SAAG,OAAO,KAAK,EACZ;AAAA,QACC,IAAI,GAAG,MAAM,SAAS,GAAG,GAAG,GAAG,GAAG,MAAM,OAAO,KAAK,GAAG,GAAG,GAAG,MAAM,UAAU,WAAW,CAAC;AAAA,MAC3F,EACC,IAAI;AAAA,IACT;AAAA,IAEA,IAAI,MAAM,UAAU;AAClB,UAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,iBAAiB;AAChD,YAAM,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI;AACvE,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB,KAAK,GAAG,EAAE;AACvD,SAAG,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI;AAAA,IAC7E;AAAA,IAEA,QAAQ,MAAM;AACZ,UAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,iBAAiB;AAChD,aAAO,YAAY,IAAI,KAAK,GAAG;AAAA,IACjC;AAAA,IAEA,QAAQ;AACN,YAAM,OAAO,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,OAAO,MAAM,SAAS,CAAC,EAAE,IAAI;AACxE,aAAO,KAAK,IAAI,WAAW;AAAA,IAC7B;AAAA,EACF;AACF;;;ADlMA,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWrB,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAOrB,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,kBAA0B;AACjC,SAAO,QAAQ,IAAI,oBAAoB,KAAK,QAAQ,GAAG,cAAc;AACvE;AAGO,SAAS,cAAc,SAA8B,CAAC,GAAa;AACxE,QAAM,UACJ,OAAO,YAAY,OAAO,SAAa,OAAO,WAAW,KAAK,gBAAgB,GAAG,OAAO;AAI1F,MAAI;AACJ,MAAI,SAAS;AACX,cAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,aAAS,KAAK,SAAS,UAAU;AAAA,EACnC,OAAO;AACL,aAAS;AAAA,EACX;AAEA,QAAM,QAAQ,aAAa,MAAM;AACjC,QAAM,KAAK,QAAQ,KAAK;AAGxB,KAAG,IAAI,YAAY;AACnB,KAAG,IAAI,YAAY;AACnB,aAAW,OAAO,gBAAgB;AAChC,OAAG,IAAI,GAAG;AAAA,EACZ;AAIA,QAAM,UAAU,oBAAoB,EAAE;AAItC,MAAI;AACJ,MAAI,OAAO,gBAAgB,MAAM;AAC/B,gBAAY,IAAI,aAAa,CAAC;AAC9B,gBAAY,gBAAgB;AAAA,MAC1B,MAAM,OAAO,eAAe,KAAK,gBAAgB,GAAG,WAAW;AAAA,IACjE,CAAC;AAAA,EACH;AAIA,QAAM,eAAe,UAAU,KAAK,SAAS,gBAAgB,IAAI;AAEjE,QAAM,eAAe,MAA8B;AACjD,QAAI,gBAAgB,WAAW,YAAY,GAAG;AAC5C,aAAO,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAAA,IACvD;AACA,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,gBAAgB,CAAC,aAA2C;AAChE,QAAI,CAAC,aAAc;AACnB,cAAU,SAAU,EAAE,WAAW,KAAK,CAAC;AACvC,kBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AAAA,EACxE;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO,IAAY,QAAgB;AACjC,YAAM,WAAW,aAAa;AAC9B,eAAS,EAAE,IAAI;AACf,oBAAc,QAAQ;AAAA,IACxB;AAAA,IAEA,MAAM,IAAY;AAChB,YAAM,WAAW,aAAa;AAC9B,aAAO,SAAS,EAAE;AAClB,oBAAc,QAAQ;AAAA,IACxB;AAAA,IAEA,OAA+B;AAC7B,aAAO,aAAa;AAAA,IACtB;AAAA,EACF;AAIA,QAAM,cAA2B;AAAA,IAC/B,MAAM,YAAY;AAAA,IAAC;AAAA,EACrB;AAIA,QAAM,cAAc,CAAC,QAAgB,SAA4B;AAC/D,QAAI,CAAC,QAAS;AACd,UAAM,aAAa,KAAK,SAAS,SAAS;AAC1C,cAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,kBAAc,KAAK,YAAY,GAAG,MAAM,OAAO,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAAA,EAC1F;AAEA,QAAM,cAAc,CAAC,WAAuC;AAC1D,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,cAAc,KAAK,SAAS,WAAW,GAAG,MAAM,OAAO;AAC7D,QAAI,CAAC,WAAW,WAAW,EAAG,QAAO;AACrC,WAAO,KAAK,MAAM,aAAa,aAAa,OAAO,CAAC;AAAA,EACtD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,OAAO;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AACF;;;AG1HO,SAAS,aAAa,OAA0D;AACrF,QAAM,QAAqB,CAAC;AAE5B,QAAM,eAAe,CAAC,MAAa,WAAmB;AACpD,QAAI,KAAK,aAAa;AACpB,YAAM,KAAK;AAAA,QACT,MAAM,GAAG,MAAM,IAAI,KAAK,IAAI;AAAA,QAC5B,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AACA,QAAI,KAAK,UAAU;AACjB,iBAAW,SAAS,KAAK,UAAU;AACjC,cAAM,UAAU,MAAM,MAAM,MAAM;AAClC,qBAAa,OAAO,OAAO;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,MAAM,MAAM;AACjC,eAAa,OAAO,MAAM;AAE1B,QAAM,oBAAoB,CAAC,SAA8B;AACvD,UAAM,QAAsB;AAAA,MAC1B,MAAM,KAAK;AAAA,MACX,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,MACpC,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,MACpC,GAAI,KAAK,SAAS,KAAK,MAAM,SAAS,IAAI,EAAE,OAAO,mBAAmB,KAAK,KAAK,EAAE,IAAI,CAAC;AAAA,IACzF;AACA,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,YAAM,WAAyC,CAAC;AAChD,iBAAW,SAAS,KAAK,UAAU;AACjC,cAAM,UAAU,MAAM,MAAM,MAAM;AAClC,iBAAS,OAAO,IAAI,kBAAkB,KAAK;AAAA,MAC7C;AACA,aAAO,EAAE,GAAG,OAAO,SAAS;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,kBAAkB,KAAK;AAE5C,QAAM,WAAqB;AAAA,IACzB,IAAI;AAAA,IACJ,MAAM,MAAM;AAAA,IACZ,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,IAAI,IAAI,CAAC;AAAA,IACtC,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,IAC5C,GAAI,aAAa,WAAW,EAAE,UAAU,aAAa,SAAS,IAAI,CAAC;AAAA,IACnE,GAAI,MAAM,SAAS,MAAM,MAAM,SAAS,IACpC;AAAA,MACE,OAAO,mBAAmB,MAAM,KAAK;AAAA,IACvC,IACA,CAAC;AAAA,EACP;AAEA,SAAO,EAAE,UAAU,MAAM;AAC3B;AAEA,SAAS,mBACPC,QAC0B;AAC1B,QAAM,SAAmC,CAAC;AAC1C,aAAW,QAAQA,QAAO;AACxB,UAAM,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO;AAC/C,QAAI,CAAC,OAAO,KAAK,QAAQ,GAAG;AAC1B,aAAO,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC3B;AACA,WAAO,KAAK,QAAQ,EAAE,KAAK,QAAQ;AAAA,EACrC;AACA,SAAO;AACT;AAQO,SAAS,aAAa,UAAoB,cAA6C;AAC5F,QAAM,aAAa,CAAC,IAAY,SAA8B;AAC5D,UAAM,WAAW,GAAG,EAAE,IAAI,KAAK,IAAI;AACnC,UAAM,cAAc,aAAa,QAAQ;AAEzC,UAAMC,YAAoB,CAAC;AAC3B,QAAI,KAAK,UAAU;AACjB,iBAAW,CAAC,SAAS,SAAS,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AAChE,QAAAA,UAAS,KAAK,WAAW,SAAS,SAAS,CAAC;AAAA,MAC9C;AAAA,IACF;AAEA,UAAM,YAAmD,CAAC;AAC1D,QAAI,KAAK,OAAO;AACd,iBAAW,CAAC,UAAU,SAAS,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAC9D,mBAAW,YAAY,WAAW;AAChC,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,QAAQ,EAAE,IAAI,UAAU,MAAM,IAAI,aAAa,IAAI,QAAQ,KAAK;AAAA,UAClE,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,MACpC;AAAA,MACA,MAAM,KAAK;AAAA,MACX,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,MACpC,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,MACrC,GAAIA,UAAS,SAAS,IAAI,EAAE,UAAAA,UAAS,IAAI,CAAC;AAAA,MAC1C,GAAI,UAAU,SAAS,IAAI,EAAE,OAAO,UAAU,IAAI,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,eAAe,GAAG,SAAS,EAAE,IAAI,SAAS,IAAI;AACpD,QAAM,kBAAkB,aAAa,YAAY;AAEjD,QAAM,WAAoB,CAAC;AAC3B,MAAI,SAAS,UAAU;AACrB,eAAW,CAAC,SAAS,SAAS,KAAK,OAAO,QAAQ,SAAS,QAAQ,GAAG;AACpE,eAAS,KAAK,WAAW,SAAS,SAAS,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,QAAMD,SAA+C,CAAC;AACtD,MAAI,SAAS,OAAO;AAClB,eAAW,CAAC,UAAU,SAAS,KAAK,OAAO,QAAQ,SAAS,KAAK,GAAG;AAClE,iBAAW,YAAY,WAAW;AAChC,QAAAA,OAAM,KAAK;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,YACb,QAAQ;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAI,SAAS,MAAM,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC;AAAA,IAC5C,IAAI,SAAS;AAAA,IACb,GAAI,SAAS,QAAQ,EAAE,OAAO,SAAS,MAAM,IAAI,CAAC;AAAA,IAClD,MAAM,SAAS;AAAA,IACf,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,GAAI,kBAAkB,EAAE,aAAa,gBAAgB,IAAI,CAAC;AAAA,IAC1D,GAAI,SAAS,SAAS,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,IAC1C,GAAIA,OAAM,SAAS,IAAI,EAAE,OAAAA,OAAM,IAAI,CAAC;AAAA,EACtC;AACF;","names":["max","links","children"]}
1
+ {"version":3,"sources":["../src/LocalPlatform.ts","../src/SqliteRepository.ts","../src/sqliteRuntime.ts","../src/schema.ts","../src/manifest.ts"],"sourcesContent":["/**\n * localPlatform — create a Platform backed by SQLite + local filesystem.\n *\n * Storage:\n * {dataDir}/rolex.db — SQLite database (all state: nodes, links, prototypes, contexts)\n *\n * When dataDir is null, runs with in-memory SQLite (useful for tests).\n */\n\nimport { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { drizzle } from \"@deepracticex/drizzle\";\nimport { openDatabase } from \"@deepracticex/sqlite\";\nimport { NodeProvider } from \"@resourcexjs/node-provider\";\nimport type { Platform } from \"@rolexjs/core\";\nimport type { Initializer } from \"@rolexjs/system\";\nimport { SqliteRepository } from \"./SqliteRepository.js\";\n\n// ===== Config =====\n\nexport interface LocalPlatformConfig {\n /** Directory for persistent storage. Defaults to ~/.deepractice/rolex. Set to null for in-memory only. */\n dataDir?: string | null;\n /** Directory for ResourceX storage. Defaults to ~/.deepractice/resourcex. Set to null to disable. */\n resourceDir?: string | null;\n /** Prototype sources to settle on genesis. */\n bootstrap?: string[];\n}\n\n// ===== Factory =====\n\n/** Resolve the DEEPRACTICE_HOME base directory. Env > default (~/.deepractice). */\nfunction deepracticeHome(): string {\n return process.env.DEEPRACTICE_HOME ?? join(homedir(), \".deepractice\");\n}\n\n/** Create a local Platform. Persistent by default ($DEEPRACTICE_HOME/rolex), in-memory if dataDir is null. */\nexport function localPlatform(config: LocalPlatformConfig = {}): Platform {\n const dataDir =\n config.dataDir === null ? undefined : (config.dataDir ?? join(deepracticeHome(), \"rolex\"));\n\n // ===== SQLite database =====\n\n let dbPath: string;\n if (dataDir) {\n mkdirSync(dataDir, { recursive: true });\n dbPath = join(dataDir, \"rolex.db\");\n } else {\n dbPath = \":memory:\";\n }\n\n const rawDb = openDatabase(dbPath);\n const db = drizzle(rawDb);\n\n // ===== Repository (all state in one place) =====\n\n const repository = new SqliteRepository(db);\n\n // ===== ResourceX Provider =====\n\n const resourcexProvider = config.resourceDir !== null ? new NodeProvider() : undefined;\n\n // ===== Initializer =====\n\n const initializer: Initializer = {\n async bootstrap() {},\n };\n\n return {\n repository,\n resourcexProvider,\n initializer,\n bootstrap: config.bootstrap,\n };\n}\n","/**\n * SqliteRepository — RoleXRepository backed by SQLite via Drizzle.\n *\n * Single database, four tables: nodes, links, prototypes, contexts.\n * All state in one place — swap the db connection to go from local to cloud.\n */\n\nimport type { CommonXDatabase } from \"@deepracticex/drizzle\";\nimport type { ContextData, PrototypeRegistry, RoleXRepository } from \"@rolexjs/core\";\nimport type { Runtime } from \"@rolexjs/system\";\nimport { sql } from \"drizzle-orm\";\nimport { createSqliteRuntime } from \"./sqliteRuntime.js\";\n\ntype DB = CommonXDatabase;\n\n// ===== DDL =====\n\nconst DDL = [\n sql`CREATE TABLE IF NOT EXISTS nodes (\n ref TEXT PRIMARY KEY,\n id TEXT,\n alias TEXT,\n name TEXT NOT NULL,\n description TEXT DEFAULT '',\n parent_ref TEXT REFERENCES nodes(ref),\n information TEXT,\n tag TEXT\n )`,\n sql`CREATE TABLE IF NOT EXISTS links (\n from_ref TEXT NOT NULL REFERENCES nodes(ref),\n to_ref TEXT NOT NULL REFERENCES nodes(ref),\n relation TEXT NOT NULL,\n PRIMARY KEY (from_ref, to_ref, relation)\n )`,\n sql`CREATE TABLE IF NOT EXISTS prototypes (\n id TEXT PRIMARY KEY,\n source TEXT NOT NULL\n )`,\n sql`CREATE TABLE IF NOT EXISTS contexts (\n role_id TEXT PRIMARY KEY,\n focused_goal_id TEXT,\n focused_plan_id TEXT\n )`,\n // Indexes\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_id ON nodes(id)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_parent_ref ON nodes(parent_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_from ON links(from_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_to ON links(to_ref)`,\n];\n\n// ===== Repository =====\n\nexport class SqliteRepository implements RoleXRepository {\n readonly runtime: Runtime;\n readonly prototype: PrototypeRegistry;\n\n constructor(private db: DB) {\n // Ensure all tables exist\n for (const stmt of DDL) {\n db.run(stmt);\n }\n\n this.runtime = createSqliteRuntime(db);\n this.prototype = createPrototypeRegistry(db);\n }\n\n saveContext(roleId: string, data: ContextData): void {\n this.db.run(\n sql`INSERT OR REPLACE INTO contexts (role_id, focused_goal_id, focused_plan_id)\n VALUES (${roleId}, ${data.focusedGoalId}, ${data.focusedPlanId})`\n );\n }\n\n loadContext(roleId: string): ContextData | null {\n const row = this.db.all<{\n role_id: string;\n focused_goal_id: string | null;\n focused_plan_id: string | null;\n }>(\n sql`SELECT role_id, focused_goal_id, focused_plan_id FROM contexts WHERE role_id = ${roleId}`\n );\n if (row.length === 0) return null;\n return {\n focusedGoalId: row[0].focused_goal_id,\n focusedPlanId: row[0].focused_plan_id,\n };\n }\n}\n\n// ===== Prototype Registry (SQLite-backed) =====\n\nfunction createPrototypeRegistry(db: DB): PrototypeRegistry {\n return {\n settle(id: string, source: string) {\n db.run(sql`INSERT OR REPLACE INTO prototypes (id, source) VALUES (${id}, ${source})`);\n },\n\n evict(id: string) {\n db.run(sql`DELETE FROM prototypes WHERE id = ${id}`);\n },\n\n list(): Record<string, string> {\n const rows = db.all<{ id: string; source: string }>(sql`SELECT id, source FROM prototypes`);\n const result: Record<string, string> = {};\n for (const row of rows) {\n result[row.id] = row.source;\n }\n return result;\n },\n };\n}\n","/**\n * SQLite-backed Runtime — single source of truth.\n *\n * Every operation reads/writes directly to SQLite.\n * No in-memory Map, no load/save cycle, no stale refs.\n */\n\nimport type { CommonXDatabase } from \"@deepracticex/drizzle\";\nimport type { Runtime, State, Structure } from \"@rolexjs/system\";\nimport { and, eq, isNull } from \"drizzle-orm\";\nimport { links, nodes } from \"./schema.js\";\n\ntype DB = CommonXDatabase;\n\n// ===== Helpers =====\n\nfunction nextRef(db: DB): string {\n const max = db\n .select({ ref: nodes.ref })\n .from(nodes)\n .all()\n .reduce((max, r) => {\n const n = parseInt(r.ref.slice(1), 10);\n return Number.isNaN(n) ? max : Math.max(max, n);\n }, 0);\n return `n${max + 1}`;\n}\n\nfunction toStructure(row: typeof nodes.$inferSelect): Structure {\n return {\n ref: row.ref,\n ...(row.id ? { id: row.id } : {}),\n ...(row.alias ? { alias: JSON.parse(row.alias) } : {}),\n name: row.name,\n description: row.description ?? \"\",\n parent: null, // Runtime doesn't use parent as Structure; tree is via parentRef\n ...(row.information ? { information: row.information } : {}),\n ...(row.tag ? { tag: row.tag } : {}),\n };\n}\n\n// ===== Projection =====\n\nfunction projectNode(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n\n const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();\n\n const nodeLinks = db.select().from(links).where(eq(links.fromRef, ref)).all();\n\n return {\n ...toStructure(row),\n children: children.map((c) => projectNode(db, c.ref)),\n ...(nodeLinks.length > 0\n ? {\n links: nodeLinks.map((l) => ({\n relation: l.relation,\n target: projectLinked(db, l.toRef),\n })),\n }\n : {}),\n };\n}\n\n/** Project a node with full subtree but without following links (prevents cycles). */\nfunction projectLinked(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();\n return {\n ...toStructure(row),\n children: children.map((c) => projectLinked(db, c.ref)),\n };\n}\n\n// ===== Subtree removal =====\n\nfunction removeSubtree(db: DB, ref: string): void {\n // Remove children first (depth-first)\n const children = db.select({ ref: nodes.ref }).from(nodes).where(eq(nodes.parentRef, ref)).all();\n for (const child of children) {\n removeSubtree(db, child.ref);\n }\n\n // Remove links from/to this node\n db.delete(links).where(eq(links.fromRef, ref)).run();\n db.delete(links).where(eq(links.toRef, ref)).run();\n\n // Remove the node itself\n db.delete(nodes).where(eq(nodes.ref, ref)).run();\n}\n\n// ===== Runtime factory =====\n\nexport function createSqliteRuntime(db: DB): Runtime {\n return {\n create(parent, type, information, id, alias) {\n // Idempotent: same id under same parent → return existing.\n if (id) {\n const existing = db\n .select()\n .from(nodes)\n .where(and(eq(nodes.id, id), eq(nodes.parentRef, parent?.ref ?? null)))\n .get();\n if (existing) return toStructure(existing);\n }\n const ref = nextRef(db);\n db.insert(nodes)\n .values({\n ref,\n id: id ?? null,\n alias: alias && alias.length > 0 ? JSON.stringify(alias) : null,\n name: type.name,\n description: type.description,\n parentRef: parent?.ref ?? null,\n information: information ?? null,\n tag: null,\n })\n .run();\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, ref)).get()!);\n },\n\n remove(node) {\n if (!node.ref) return;\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) return;\n\n // Detach from parent's children (implicit via parentRef)\n removeSubtree(db, node.ref);\n },\n\n transform(source, target, information) {\n if (!source.ref) throw new Error(\"Source node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, source.ref)).get();\n if (!row) throw new Error(`Source node not found: ${source.ref}`);\n\n const targetParent = target.parent;\n if (!targetParent) {\n throw new Error(`Cannot transform to root structure: ${target.name}`);\n }\n\n const parentRow = db.select().from(nodes).where(eq(nodes.name, targetParent.name)).get();\n if (!parentRow) {\n throw new Error(`No node found for structure: ${targetParent.name}`);\n }\n\n // Reparent + update type in place — subtree preserved\n db.update(nodes)\n .set({\n parentRef: parentRow.ref,\n name: target.name,\n description: target.description,\n ...(information !== undefined ? { information } : {}),\n })\n .where(eq(nodes.ref, source.ref))\n .run();\n\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, source.ref)).get()!);\n },\n\n link(from, to, relationName, reverseName) {\n if (!from.ref) throw new Error(\"Source node has no ref\");\n if (!to.ref) throw new Error(\"Target node has no ref\");\n\n // Forward: from → to\n const existsForward = db\n .select()\n .from(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .get();\n if (!existsForward) {\n db.insert(links).values({ fromRef: from.ref, toRef: to.ref, relation: relationName }).run();\n }\n\n // Reverse: to → from\n const existsReverse = db\n .select()\n .from(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .get();\n if (!existsReverse) {\n db.insert(links).values({ fromRef: to.ref, toRef: from.ref, relation: reverseName }).run();\n }\n },\n\n unlink(from, to, relationName, reverseName) {\n if (!from.ref || !to.ref) return;\n\n db.delete(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .run();\n\n db.delete(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .run();\n },\n\n tag(node, tagValue) {\n if (!node.ref) throw new Error(\"Node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) throw new Error(`Node not found: ${node.ref}`);\n db.update(nodes).set({ tag: tagValue }).where(eq(nodes.ref, node.ref)).run();\n },\n\n project(node) {\n if (!node.ref) throw new Error(`Node has no ref`);\n return projectNode(db, node.ref);\n },\n\n roots() {\n const rows = db.select().from(nodes).where(isNull(nodes.parentRef)).all();\n return rows.map(toStructure);\n },\n };\n}\n","/**\n * Drizzle schema — SQLite tables for the RoleX runtime graph.\n *\n * Two tables:\n * nodes — tree backbone (Structure instances)\n * links — cross-branch relations (bidirectional)\n */\n\nimport { index, primaryKey, sqliteTable, text } from \"drizzle-orm/sqlite-core\";\n\n/**\n * nodes — every node in the society graph.\n *\n * Maps 1:1 to the Structure interface:\n * ref → graph-internal reference (primary key)\n * id → user-facing kebab-case identifier\n * alias → JSON array of alternative names\n * name → structure type (\"individual\", \"goal\", \"task\", etc.)\n * description → what this structure is\n * parent_ref → tree parent (self-referencing foreign key)\n * information → Gherkin Feature source text\n * tag → generic label (\"done\", \"abandoned\")\n */\nexport const nodes = sqliteTable(\n \"nodes\",\n {\n ref: text(\"ref\").primaryKey(),\n id: text(\"id\"),\n alias: text(\"alias\"), // JSON array: '[\"Sean\",\"姜山\"]'\n name: text(\"name\").notNull(),\n description: text(\"description\").default(\"\"),\n parentRef: text(\"parent_ref\").references((): any => nodes.ref),\n information: text(\"information\"),\n tag: text(\"tag\"),\n },\n (table) => [\n index(\"idx_nodes_id\").on(table.id),\n index(\"idx_nodes_name\").on(table.name),\n index(\"idx_nodes_parent_ref\").on(table.parentRef),\n ]\n);\n\n/**\n * links — cross-branch relations between nodes.\n *\n * Bidirectional: if A→B is \"membership\", B→A is \"belong\".\n * Both directions stored as separate rows.\n */\nexport const links = sqliteTable(\n \"links\",\n {\n fromRef: text(\"from_ref\")\n .notNull()\n .references(() => nodes.ref),\n toRef: text(\"to_ref\")\n .notNull()\n .references(() => nodes.ref),\n relation: text(\"relation\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.fromRef, table.toRef, table.relation] }),\n index(\"idx_links_from\").on(table.fromRef),\n index(\"idx_links_to\").on(table.toRef),\n ]\n);\n","/**\n * Manifest — file-based storage format for RoleX entities.\n *\n * Storage layout:\n * role/<id>/\n * individual.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * organization/<id>/\n * organization.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * Rules:\n * - Directories: only role/ and organization/ at top level\n * - Files: all [id].[type].feature, flat within the entity directory\n * - Manifest: tree structure in JSON, content in .feature files\n * - Nodes without explicit id default to their type name\n */\n\nimport type { State } from \"@rolexjs/system\";\n\n// ===== Manifest types =====\n\n/** A node in the manifest tree. */\nexport interface ManifestNode {\n readonly type: string;\n readonly ref?: string;\n readonly tag?: string;\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n/** Root manifest for an entity (individual or organization). */\nexport interface Manifest {\n readonly id: string;\n readonly type: string;\n readonly ref?: string;\n readonly alias?: readonly string[];\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n// ===== State → files =====\n\nexport interface FileEntry {\n readonly path: string;\n readonly content: string;\n}\n\n/**\n * Convert a State tree to a manifest + feature files.\n * Returns the manifest and a list of file entries (path → content).\n */\nexport function stateToFiles(state: State): { manifest: Manifest; files: FileEntry[] } {\n const files: FileEntry[] = [];\n\n const collectFiles = (node: State, nodeId: string) => {\n if (node.information) {\n files.push({\n path: `${nodeId}.${node.name}.feature`,\n content: node.information,\n });\n }\n if (node.children) {\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n collectFiles(child, childId);\n }\n }\n };\n\n const rootId = state.id ?? state.name;\n collectFiles(state, rootId);\n\n const buildManifestNode = (node: State): ManifestNode => {\n const entry: ManifestNode = {\n type: node.name,\n ...(node.ref ? { ref: node.ref } : {}),\n ...(node.tag ? { tag: node.tag } : {}),\n ...(node.links && node.links.length > 0 ? { links: buildManifestLinks(node.links) } : {}),\n };\n if (node.children && node.children.length > 0) {\n const children: Record<string, ManifestNode> = {};\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n children[childId] = buildManifestNode(child);\n }\n return { ...entry, children };\n }\n return entry;\n };\n\n const manifestNode = buildManifestNode(state);\n\n const manifest: Manifest = {\n id: rootId,\n type: state.name,\n ...(state.ref ? { ref: state.ref } : {}),\n ...(state.alias ? { alias: state.alias } : {}),\n ...(manifestNode.children ? { children: manifestNode.children } : {}),\n ...(state.links && state.links.length > 0\n ? {\n links: buildManifestLinks(state.links),\n }\n : {}),\n };\n\n return { manifest, files };\n}\n\nfunction buildManifestLinks(\n links: readonly { readonly relation: string; readonly target: State }[]\n): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const link of links) {\n const targetId = link.target.id ?? link.target.name;\n if (!result[link.relation]) {\n result[link.relation] = [];\n }\n result[link.relation].push(targetId);\n }\n return result;\n}\n\n// ===== Files → State =====\n\n/**\n * Convert a manifest + feature file contents to a State tree.\n * fileContents maps filename (e.g. \"role-creation.principle.feature\") to Gherkin text.\n */\nexport function filesToState(manifest: Manifest, fileContents: Record<string, string>): State {\n const buildState = (id: string, node: ManifestNode): State => {\n const filename = `${id}.${node.type}.feature`;\n const information = fileContents[filename];\n\n const children: State[] = [];\n if (node.children) {\n for (const [childId, childNode] of Object.entries(node.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const nodeLinks: { relation: string; target: State }[] = [];\n if (node.links) {\n for (const [relation, targetIds] of Object.entries(node.links)) {\n for (const targetId of targetIds) {\n nodeLinks.push({\n relation,\n target: { id: targetId, name: \"\", description: \"\", parent: null },\n });\n }\n }\n }\n\n return {\n ...(node.ref ? { ref: node.ref } : {}),\n id,\n name: node.type,\n description: \"\",\n parent: null,\n ...(node.tag ? { tag: node.tag } : {}),\n ...(information ? { information } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(nodeLinks.length > 0 ? { links: nodeLinks } : {}),\n };\n };\n\n const rootFilename = `${manifest.id}.${manifest.type}.feature`;\n const rootInformation = fileContents[rootFilename];\n\n const children: State[] = [];\n if (manifest.children) {\n for (const [childId, childNode] of Object.entries(manifest.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const links: { relation: string; target: State }[] = [];\n if (manifest.links) {\n for (const [relation, targetIds] of Object.entries(manifest.links)) {\n for (const targetId of targetIds) {\n links.push({\n relation,\n target: {\n id: targetId,\n name: \"\",\n description: \"\",\n parent: null,\n },\n });\n }\n }\n }\n\n return {\n ...(manifest.ref ? { ref: manifest.ref } : {}),\n id: manifest.id,\n ...(manifest.alias ? { alias: manifest.alias } : {}),\n name: manifest.type,\n description: \"\",\n parent: null,\n ...(rootInformation ? { information: rootInformation } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(links.length > 0 ? { links } : {}),\n };\n}\n"],"mappings":"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","names":["max","links","children"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rolexjs/local-platform",
3
- "version": "0.12.0-dev-20260302084345",
3
+ "version": "0.12.0-dev-20260302114956",
4
4
  "description": "Local filesystem Platform for RoleX — stores roles in .rolex/ directories",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,10 +23,9 @@
23
23
  "@deepracticex/drizzle": "^0.2.0",
24
24
  "@deepracticex/sqlite": "^0.2.0",
25
25
  "@resourcexjs/node-provider": "^2.14.0",
26
- "@rolexjs/core": "0.12.0-dev-20260302084345",
27
- "@rolexjs/system": "0.12.0-dev-20260302084345",
28
- "drizzle-orm": "^0.45.1",
29
- "resourcexjs": "^2.14.0"
26
+ "@rolexjs/core": "0.12.0-dev-20260302114956",
27
+ "@rolexjs/system": "0.12.0-dev-20260302114956",
28
+ "drizzle-orm": "^0.45.1"
30
29
  },
31
30
  "devDependencies": {},
32
31
  "publishConfig": {