iranti 0.2.5 → 0.2.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/README.md CHANGED
@@ -305,6 +305,12 @@ iranti mcp
305
305
 
306
306
  Use it with a project-local `.mcp.json`, and optionally add `iranti claude-hook` for `SessionStart` and `UserPromptSubmit`.
307
307
 
308
+ Fast path:
309
+
310
+ ```bash
311
+ iranti claude-setup
312
+ ```
313
+
308
314
  Guide: [`docs/guides/claude-code.md`](docs/guides/claude-code.md)
309
315
 
310
316
  ### Codex via MCP
@@ -318,6 +324,12 @@ codex -C /path/to/your/project
318
324
 
319
325
  When `iranti codex-setup` is run from a project directory, it automatically captures that project's `.env.iranti` as `IRANTI_PROJECT_ENV` so Codex resolves the correct Iranti instance consistently.
320
326
 
327
+ Alias:
328
+
329
+ ```bash
330
+ iranti integrate codex
331
+ ```
332
+
321
333
  Guide: [`docs/guides/codex.md`](docs/guides/codex.md)
322
334
 
323
335
  ### Resolve Pending Escalations
@@ -153,11 +153,19 @@ function canUseInstalledIranti(repoRoot) {
153
153
  return false;
154
154
  }
155
155
  }
156
+ function ensureCodexInstalled(repoRoot) {
157
+ try {
158
+ run('codex', ['--version'], repoRoot);
159
+ }
160
+ catch {
161
+ throw new Error('Codex CLI is not installed or not on PATH. Install Codex first, confirm `codex --version` works, then rerun `iranti codex-setup`.');
162
+ }
163
+ }
156
164
  function main() {
157
165
  const options = parseArgs(process.argv.slice(2));
158
166
  const repoRoot = findPackageRoot(__dirname);
159
167
  const mcpScript = node_path_1.default.join(repoRoot, 'dist', 'scripts', 'iranti-mcp.js');
160
- run('codex', ['--version'], repoRoot);
168
+ ensureCodexInstalled(repoRoot);
161
169
  const useInstalled = !options.useLocalScript && canUseInstalledIranti(repoRoot);
162
170
  if (!useInstalled && !node_fs_1.default.existsSync(mcpScript)) {
163
171
  throw new Error(`Missing build artifact: ${mcpScript}. Run "npm run build" first, or install iranti globally and rerun without --local-script.`);
@@ -644,39 +644,95 @@ async function ensureInstanceConfigured(root, name, config) {
644
644
  });
645
645
  return { envFile, instanceDir, created };
646
646
  }
647
- async function writeClaudeCodeProjectFiles(projectPath) {
647
+ function makeIrantiMcpServerConfig() {
648
+ return {
649
+ command: 'iranti',
650
+ args: ['mcp'],
651
+ };
652
+ }
653
+ function makeClaudeHookSettings(projectEnvPath) {
654
+ const hookArgs = (event) => {
655
+ const args = ['claude-hook', '--event', event];
656
+ if (projectEnvPath) {
657
+ args.push('--project-env', projectEnvPath);
658
+ }
659
+ return args;
660
+ };
661
+ return {
662
+ hooks: {
663
+ SessionStart: [
664
+ {
665
+ command: 'iranti',
666
+ args: hookArgs('SessionStart'),
667
+ },
668
+ ],
669
+ UserPromptSubmit: [
670
+ {
671
+ command: 'iranti',
672
+ args: hookArgs('UserPromptSubmit'),
673
+ },
674
+ ],
675
+ },
676
+ };
677
+ }
678
+ async function writeClaudeCodeProjectFiles(projectPath, projectEnvPath, force = false) {
648
679
  const mcpFile = path_1.default.join(projectPath, '.mcp.json');
680
+ let mcpStatus = 'unchanged';
681
+ const irantiMcpServer = makeIrantiMcpServerConfig();
649
682
  if (!fs_1.default.existsSync(mcpFile)) {
650
683
  await writeText(mcpFile, `${JSON.stringify({
651
684
  mcpServers: {
652
- iranti: {
653
- command: 'iranti',
654
- args: ['mcp'],
655
- },
685
+ iranti: irantiMcpServer,
656
686
  },
657
687
  }, null, 2)}\n`);
688
+ mcpStatus = 'created';
689
+ }
690
+ else {
691
+ const existing = readJsonFile(mcpFile);
692
+ if (!existing || typeof existing !== 'object' || Array.isArray(existing)) {
693
+ if (!force) {
694
+ throw new Error(`Existing .mcp.json is not valid JSON. Re-run with --force to overwrite it: ${mcpFile}`);
695
+ }
696
+ await writeText(mcpFile, `${JSON.stringify({
697
+ mcpServers: {
698
+ iranti: irantiMcpServer,
699
+ },
700
+ }, null, 2)}\n`);
701
+ mcpStatus = 'updated';
702
+ }
703
+ else {
704
+ const existingServers = existing.mcpServers && typeof existing.mcpServers === 'object' && !Array.isArray(existing.mcpServers)
705
+ ? existing.mcpServers
706
+ : {};
707
+ const hasIranti = Object.prototype.hasOwnProperty.call(existingServers, 'iranti');
708
+ if (!hasIranti || force) {
709
+ await writeText(mcpFile, `${JSON.stringify({
710
+ ...existing,
711
+ mcpServers: {
712
+ ...existingServers,
713
+ iranti: irantiMcpServer,
714
+ },
715
+ }, null, 2)}\n`);
716
+ mcpStatus = 'updated';
717
+ }
718
+ }
658
719
  }
659
720
  const claudeDir = path_1.default.join(projectPath, '.claude');
660
721
  await ensureDir(claudeDir);
661
722
  const settingsFile = path_1.default.join(claudeDir, 'settings.local.json');
723
+ let settingsStatus = 'unchanged';
662
724
  if (!fs_1.default.existsSync(settingsFile)) {
663
- await writeText(settingsFile, `${JSON.stringify({
664
- hooks: {
665
- SessionStart: [
666
- {
667
- command: 'iranti',
668
- args: ['claude-hook', '--event', 'SessionStart'],
669
- },
670
- ],
671
- UserPromptSubmit: [
672
- {
673
- command: 'iranti',
674
- args: ['claude-hook', '--event', 'UserPromptSubmit'],
675
- },
676
- ],
677
- },
678
- }, null, 2)}\n`);
725
+ await writeText(settingsFile, `${JSON.stringify(makeClaudeHookSettings(projectEnvPath), null, 2)}\n`);
726
+ settingsStatus = 'created';
727
+ }
728
+ else if (force) {
729
+ await writeText(settingsFile, `${JSON.stringify(makeClaudeHookSettings(projectEnvPath), null, 2)}\n`);
730
+ settingsStatus = 'updated';
679
731
  }
732
+ return {
733
+ mcp: mcpStatus,
734
+ settings: settingsStatus,
735
+ };
680
736
  }
681
737
  function hasCodexInstalled() {
682
738
  try {
@@ -1133,21 +1189,29 @@ function isPathInside(parentDir, childDir) {
1133
1189
  const child = normalizePathForCompare(childDir);
1134
1190
  return child === parent || child.startsWith(`${parent}/`);
1135
1191
  }
1136
- function resolveSpawnExecutable(executable) {
1137
- if (process.platform !== 'win32')
1138
- return executable;
1139
- if (executable === 'npm')
1140
- return 'npm.cmd';
1141
- if (executable === 'npx')
1142
- return 'npx.cmd';
1143
- return executable;
1192
+ function quoteForCmd(arg) {
1193
+ if (arg.length === 0)
1194
+ return '""';
1195
+ if (!/[ \t"&()<>|^]/.test(arg))
1196
+ return arg;
1197
+ return `"${arg.replace(/"/g, '\\"')}"`;
1144
1198
  }
1145
1199
  function runCommandCapture(executable, args, cwd) {
1146
- const proc = (0, child_process_1.spawnSync)(resolveSpawnExecutable(executable), args, {
1147
- cwd,
1148
- encoding: 'utf8',
1149
- stdio: ['ignore', 'pipe', 'pipe'],
1150
- });
1200
+ const proc = process.platform === 'win32'
1201
+ ? (0, child_process_1.spawnSync)(process.env.ComSpec ?? 'cmd.exe', [
1202
+ '/d',
1203
+ '/c',
1204
+ [executable, ...args].map(quoteForCmd).join(' '),
1205
+ ], {
1206
+ cwd,
1207
+ encoding: 'utf8',
1208
+ stdio: ['ignore', 'pipe', 'pipe'],
1209
+ })
1210
+ : (0, child_process_1.spawnSync)(executable, args, {
1211
+ cwd,
1212
+ encoding: 'utf8',
1213
+ stdio: ['ignore', 'pipe', 'pipe'],
1214
+ });
1151
1215
  return {
1152
1216
  status: proc.status,
1153
1217
  stdout: proc.stdout ?? '',
@@ -1155,10 +1219,19 @@ function runCommandCapture(executable, args, cwd) {
1155
1219
  };
1156
1220
  }
1157
1221
  function runCommandInteractive(step) {
1158
- const proc = (0, child_process_1.spawnSync)(resolveSpawnExecutable(step.executable), step.args, {
1159
- cwd: step.cwd,
1160
- stdio: 'inherit',
1161
- });
1222
+ const proc = process.platform === 'win32'
1223
+ ? (0, child_process_1.spawnSync)(process.env.ComSpec ?? 'cmd.exe', [
1224
+ '/d',
1225
+ '/c',
1226
+ [step.executable, ...step.args].map(quoteForCmd).join(' '),
1227
+ ], {
1228
+ cwd: step.cwd,
1229
+ stdio: 'inherit',
1230
+ })
1231
+ : (0, child_process_1.spawnSync)(step.executable, step.args, {
1232
+ cwd: step.cwd,
1233
+ stdio: 'inherit',
1234
+ });
1162
1235
  return proc.status;
1163
1236
  }
1164
1237
  function detectPythonLauncher() {
@@ -1294,8 +1367,8 @@ function detectUpgradeContext(args) {
1294
1367
  const repoCheckout = fs_1.default.existsSync(path_1.default.join(packageRootPath, '.git'));
1295
1368
  const repoDirty = repoCheckout ? repoIsDirty(packageRootPath) : false;
1296
1369
  const globalNpmRoot = detectGlobalNpmRoot();
1297
- const globalNpmInstall = globalNpmRoot !== null && isPathInside(globalNpmRoot, packageRootPath);
1298
- const globalNpmVersion = globalNpmInstall ? detectGlobalNpmInstalledVersion() : null;
1370
+ const globalNpmVersion = detectGlobalNpmInstalledVersion();
1371
+ const globalNpmInstall = globalNpmVersion !== null;
1299
1372
  const python = detectPythonLauncher();
1300
1373
  const pythonVersion = detectPythonInstalledVersion(python);
1301
1374
  const availableTargets = [];
@@ -1384,16 +1457,16 @@ function describeUpgradeTarget(target) {
1384
1457
  const latest = target.latestVersion ?? 'unknown';
1385
1458
  if (target.target === 'npm-repo') {
1386
1459
  return target.blockedReason
1387
- ? `repo checkout (${current}) ${target.blockedReason}`
1388
- : `repo checkout (${current}) refresh local checkout and rebuild`;
1460
+ ? `repo checkout (${current}) — ${target.blockedReason}`
1461
+ : `repo checkout (${current}) — refresh local checkout and rebuild`;
1389
1462
  }
1390
1463
  if (target.upToDate === true) {
1391
- return `${target.target} (${current}) already at latest ${latest}`;
1464
+ return `${target.target} (${current}) — already at latest ${latest}`;
1392
1465
  }
1393
1466
  if (target.blockedReason) {
1394
- return `${target.target} (${current}) ${target.blockedReason}`;
1467
+ return `${target.target} (${current}) — ${target.blockedReason}`;
1395
1468
  }
1396
- return `${target.target} (${current}) latest ${latest}`;
1469
+ return `${target.target} (${current}) — latest ${latest}`;
1397
1470
  }
1398
1471
  async function chooseInteractiveUpgradeTargets(statuses) {
1399
1472
  const selected = [];
@@ -2063,7 +2136,7 @@ async function doctorCommand(args) {
2063
2136
  : check.status === 'warn'
2064
2137
  ? warnLabel('WARN')
2065
2138
  : failLabel('FAIL');
2066
- console.log(`${marker} ${check.name} ${check.detail}`);
2139
+ console.log(`${marker} ${check.name} — ${check.detail}`);
2067
2140
  }
2068
2141
  if (result.remediations.length > 0) {
2069
2142
  console.log('');
@@ -2736,6 +2809,151 @@ async function resolveCommand(args) {
2736
2809
  const escalationDir = explicitDir ? path_1.default.resolve(explicitDir) : (0, escalationPaths_1.getEscalationPaths)().root;
2737
2810
  await (0, resolutionist_1.resolveInteractive)(escalationDir);
2738
2811
  }
2812
+ function printClaudeSetupHelp() {
2813
+ console.log([
2814
+ 'Scaffold Claude Code MCP and hook files for the current project.',
2815
+ '',
2816
+ 'Usage:',
2817
+ ' iranti claude-setup [path] [--project-env <path>] [--force]',
2818
+ ' iranti claude-setup --scan <dir> [--recursive] [--force]',
2819
+ ' iranti integrate claude [path] [--project-env <path>] [--force]',
2820
+ ' iranti integrate claude --scan <dir> [--recursive] [--force]',
2821
+ '',
2822
+ 'Notes:',
2823
+ ' - Expects a project binding at .env.iranti unless --project-env is supplied.',
2824
+ ' - Writes .mcp.json and .claude/settings.local.json.',
2825
+ ' - Adds the Iranti MCP server to existing .mcp.json files without removing other servers.',
2826
+ ' - Leaves existing Claude hook files untouched unless --force is supplied.',
2827
+ '',
2828
+ 'Scan mode (--scan):',
2829
+ ' - Scans immediate subdirectories of the given dir by default.',
2830
+ ' - Add --recursive to scan nested project trees too.',
2831
+ ' - Only scaffolds projects that already have a .claude subfolder.',
2832
+ ' - No .env.iranti required - skips the per-project binding check.',
2833
+ ' - Scan mode adds or merges .mcp.json and only creates hook settings when missing.',
2834
+ ].join('\n'));
2835
+ }
2836
+ function shouldSkipRecursiveClaudeScanDir(name) {
2837
+ if (name.startsWith('.'))
2838
+ return true;
2839
+ return [
2840
+ 'node_modules',
2841
+ 'dist',
2842
+ 'build',
2843
+ 'out',
2844
+ 'coverage',
2845
+ '.next',
2846
+ '.turbo',
2847
+ '.cache',
2848
+ ].includes(name);
2849
+ }
2850
+ function findClaudeProjects(scanDir, recursive) {
2851
+ if (!recursive) {
2852
+ return fs_1.default.readdirSync(scanDir, { withFileTypes: true })
2853
+ .filter((entry) => entry.isDirectory())
2854
+ .map((entry) => path_1.default.join(scanDir, entry.name))
2855
+ .filter((candidate) => fs_1.default.existsSync(path_1.default.join(candidate, '.claude')));
2856
+ }
2857
+ const found = new Set();
2858
+ const queue = [scanDir];
2859
+ while (queue.length > 0) {
2860
+ const current = queue.shift();
2861
+ let entries = [];
2862
+ try {
2863
+ entries = fs_1.default.readdirSync(current, { withFileTypes: true });
2864
+ }
2865
+ catch {
2866
+ continue;
2867
+ }
2868
+ if (fs_1.default.existsSync(path_1.default.join(current, '.claude'))) {
2869
+ found.add(current);
2870
+ }
2871
+ for (const entry of entries) {
2872
+ if (!entry.isDirectory())
2873
+ continue;
2874
+ if (shouldSkipRecursiveClaudeScanDir(entry.name))
2875
+ continue;
2876
+ queue.push(path_1.default.join(current, entry.name));
2877
+ }
2878
+ }
2879
+ found.delete(scanDir);
2880
+ return Array.from(found).sort((a, b) => a.localeCompare(b));
2881
+ }
2882
+ async function claudeSetupCommand(args) {
2883
+ if (hasFlag(args, 'help')) {
2884
+ printClaudeSetupHelp();
2885
+ return;
2886
+ }
2887
+ const force = hasFlag(args, 'force');
2888
+ if (args.flags.has('scan')) {
2889
+ const recursive = hasFlag(args, 'recursive');
2890
+ const dirArg = getFlag(args, 'scan')
2891
+ ?? args.positionals[0]
2892
+ ?? (args.command === 'claude-setup' ? args.subcommand ?? undefined : undefined);
2893
+ const scanDir = path_1.default.resolve(dirArg ?? process.cwd());
2894
+ if (!fs_1.default.existsSync(scanDir)) {
2895
+ throw new Error(`Scan directory not found: ${scanDir}`);
2896
+ }
2897
+ const candidates = findClaudeProjects(scanDir, recursive);
2898
+ if (candidates.length === 0) {
2899
+ console.log(`${infoLabel()} No ${recursive ? 'nested project directories' : 'subdirectories'} with a .claude folder found in ${scanDir}`);
2900
+ return;
2901
+ }
2902
+ console.log(`${okLabel()} Scanning ${scanDir} - found ${candidates.length} project(s) with .claude${recursive ? ' (recursive)' : ''}`);
2903
+ let createdMcp = 0;
2904
+ let updatedMcp = 0;
2905
+ let createdSettings = 0;
2906
+ let updatedSettings = 0;
2907
+ let unchanged = 0;
2908
+ for (const projectPath of candidates) {
2909
+ const result = await writeClaudeCodeProjectFiles(projectPath, undefined, force);
2910
+ if (result.mcp === 'created')
2911
+ createdMcp += 1;
2912
+ if (result.mcp === 'updated')
2913
+ updatedMcp += 1;
2914
+ if (result.settings === 'created')
2915
+ createdSettings += 1;
2916
+ if (result.settings === 'updated')
2917
+ updatedSettings += 1;
2918
+ if (result.mcp === 'unchanged' && result.settings === 'unchanged')
2919
+ unchanged += 1;
2920
+ console.log(` ${projectPath}`);
2921
+ console.log(` mcp ${result.mcp}`);
2922
+ console.log(` settings ${result.settings}`);
2923
+ }
2924
+ console.log('');
2925
+ console.log('Summary:');
2926
+ console.log(` projects ${candidates.length}`);
2927
+ console.log(` mcp created ${createdMcp}`);
2928
+ console.log(` mcp updated ${updatedMcp}`);
2929
+ console.log(` settings created ${createdSettings}`);
2930
+ console.log(` settings updated ${updatedSettings}`);
2931
+ console.log(` unchanged ${unchanged}`);
2932
+ console.log(`${infoLabel()} Done. Open each project in Claude Code to verify Iranti tools are available.`);
2933
+ return;
2934
+ }
2935
+ const projectArg = args.positionals[0] ?? (args.command === 'claude-setup' ? args.subcommand ?? undefined : undefined);
2936
+ const projectPath = path_1.default.resolve(projectArg ?? process.cwd());
2937
+ const explicitProjectEnv = getFlag(args, 'project-env');
2938
+ const projectEnvPath = explicitProjectEnv
2939
+ ? path_1.default.resolve(explicitProjectEnv)
2940
+ : path_1.default.join(projectPath, '.env.iranti');
2941
+ if (!fs_1.default.existsSync(projectPath)) {
2942
+ throw new Error(`Project path not found: ${projectPath}`);
2943
+ }
2944
+ if (!fs_1.default.existsSync(projectEnvPath)) {
2945
+ throw new Error(`Project binding not found at ${projectEnvPath}. Run \`iranti project init\` or \`iranti configure project\` first.`);
2946
+ }
2947
+ const result = await writeClaudeCodeProjectFiles(projectPath, projectEnvPath, force);
2948
+ console.log(`${okLabel()} Claude Code integration scaffolded`);
2949
+ console.log(` project ${projectPath}`);
2950
+ console.log(` binding ${projectEnvPath}`);
2951
+ console.log(` mcp ${path_1.default.join(projectPath, '.mcp.json')}`);
2952
+ console.log(` settings ${path_1.default.join(projectPath, '.claude', 'settings.local.json')}`);
2953
+ console.log(` mcp status ${result.mcp}`);
2954
+ console.log(` settings status ${result.settings}`);
2955
+ console.log(`${infoLabel()} Next: open Claude Code in this project and verify Iranti tools are available.`);
2956
+ }
2739
2957
  async function chatCommand(args) {
2740
2958
  const provider = normalizeProvider(getFlag(args, 'provider'));
2741
2959
  if (provider && !isSupportedProvider(provider)) {
@@ -2788,8 +3006,13 @@ Project-level:
2788
3006
 
2789
3007
  Integrations:
2790
3008
  iranti mcp [--help]
3009
+ iranti claude-setup [path] [--project-env <path>] [--force]
3010
+ iranti claude-setup --scan <dir> [--force]
2791
3011
  iranti claude-hook --event SessionStart|UserPromptSubmit [--project-env <path>] [--instance-env <path>] [--env-file <path>]
2792
3012
  iranti codex-setup [--name iranti] [--agent codex_code] [--source Codex] [--provider openai] [--project-env <path>] [--local-script]
3013
+ iranti integrate claude [path] [--project-env <path>] [--force]
3014
+ iranti integrate claude --scan <dir> [--force]
3015
+ iranti integrate codex [--name iranti] [--agent codex_code] [--source Codex] [--provider openai] [--project-env <path>] [--local-script]
2793
3016
  `);
2794
3017
  }
2795
3018
  async function main() {
@@ -2895,6 +3118,10 @@ async function main() {
2895
3118
  await handoffToScript('iranti-mcp', process.argv.slice(3));
2896
3119
  return;
2897
3120
  }
3121
+ if (args.command === 'claude-setup') {
3122
+ await claudeSetupCommand(args);
3123
+ return;
3124
+ }
2898
3125
  if (args.command === 'claude-hook') {
2899
3126
  await handoffToScript('claude-code-memory-hook', process.argv.slice(3));
2900
3127
  return;
@@ -2903,6 +3130,17 @@ async function main() {
2903
3130
  await handoffToScript('codex-setup', process.argv.slice(3));
2904
3131
  return;
2905
3132
  }
3133
+ if (args.command === 'integrate') {
3134
+ if (args.subcommand === 'claude') {
3135
+ await claudeSetupCommand(args);
3136
+ return;
3137
+ }
3138
+ if (args.subcommand === 'codex') {
3139
+ await handoffToScript('codex-setup', process.argv.slice(4));
3140
+ return;
3141
+ }
3142
+ throw new Error(`Unknown integrate target '${args.subcommand ?? ''}'. Use 'claude' or 'codex'.`);
3143
+ }
2906
3144
  throw new Error(`Unknown command '${args.command}'. Run: iranti help`);
2907
3145
  }
2908
3146
  main().catch((err) => {
@@ -144,7 +144,7 @@ async function main() {
144
144
  await ensureDefaultAgent(iranti);
145
145
  const server = new mcp_js_1.McpServer({
146
146
  name: 'iranti-mcp',
147
- version: '0.2.5',
147
+ version: '0.2.7',
148
148
  });
149
149
  server.registerTool('iranti_handshake', {
150
150
  description: `Initialize or refresh an agent's working-memory brief for the current task.
@@ -15,7 +15,7 @@ const STAFF_ENTRIES = [
15
15
  entityId: 'librarian',
16
16
  key: 'operating_rules',
17
17
  valueRaw: {
18
- version: '0.2.5',
18
+ version: '0.2.7',
19
19
  rules: [
20
20
  'All writes from external agents go through the Librarian — never directly to the database',
21
21
  'Check for existing entries before every write',
@@ -39,7 +39,7 @@ const STAFF_ENTRIES = [
39
39
  entityId: 'attendant',
40
40
  key: 'operating_rules',
41
41
  valueRaw: {
42
- version: '0.2.5',
42
+ version: '0.2.7',
43
43
  rules: [
44
44
  'Assigned one-per-external-agent — serve the agent, not the user',
45
45
  'On handshake: read AGENTS.md and MCP config, query Librarian for relevant rules and task context',
@@ -61,7 +61,7 @@ const STAFF_ENTRIES = [
61
61
  entityId: 'archivist',
62
62
  key: 'operating_rules',
63
63
  valueRaw: {
64
- version: '0.2.5',
64
+ version: '0.2.7',
65
65
  rules: [
66
66
  'Run on schedule or when conflict flags exceed threshold — not on every write',
67
67
  'Scan for expired, low-confidence, flagged, and duplicate entries',
@@ -82,7 +82,7 @@ const STAFF_ENTRIES = [
82
82
  entityType: 'system',
83
83
  entityId: 'library',
84
84
  key: 'schema_version',
85
- valueRaw: { version: '0.2.5' },
85
+ valueRaw: { version: '0.2.7' },
86
86
  valueSummary: 'Current Library schema version.',
87
87
  confidence: 100,
88
88
  source: 'seed',
@@ -95,7 +95,7 @@ const STAFF_ENTRIES = [
95
95
  key: 'initialization_log',
96
96
  valueRaw: {
97
97
  initializedAt: new Date().toISOString(),
98
- seedVersion: '0.2.5',
98
+ seedVersion: '0.2.7',
99
99
  },
100
100
  valueSummary: 'Record of when and how this Library was initialized.',
101
101
  confidence: 100,
@@ -108,7 +108,7 @@ const STAFF_ENTRIES = [
108
108
  entityId: 'ontology',
109
109
  key: 'core_schema',
110
110
  valueRaw: {
111
- version: '0.2.5',
111
+ version: '0.2.7',
112
112
  states: ['candidate', 'provisional', 'canonical'],
113
113
  coreEntityTypes: [
114
114
  'person',
@@ -156,7 +156,7 @@ const STAFF_ENTRIES = [
156
156
  entityId: 'ontology',
157
157
  key: 'extension_registry',
158
158
  valueRaw: {
159
- version: '0.2.5',
159
+ version: '0.2.7',
160
160
  namespaces: {
161
161
  education: {
162
162
  status: 'provisional',
@@ -187,7 +187,7 @@ const STAFF_ENTRIES = [
187
187
  entityId: 'ontology',
188
188
  key: 'candidate_terms',
189
189
  valueRaw: {
190
- version: '0.2.5',
190
+ version: '0.2.7',
191
191
  terms: [],
192
192
  },
193
193
  valueSummary: 'Staging area for ontology terms detected repeatedly but not yet promoted.',
@@ -201,7 +201,7 @@ const STAFF_ENTRIES = [
201
201
  entityId: 'ontology',
202
202
  key: 'promotion_policy',
203
203
  valueRaw: {
204
- version: '0.2.5',
204
+ version: '0.2.7',
205
205
  candidateToProvisional: {
206
206
  minSeenCount: 3,
207
207
  minDistinctAgents: 2,
@@ -237,7 +237,7 @@ const STAFF_ENTRIES = [
237
237
  entityId: 'ontology',
238
238
  key: 'change_log',
239
239
  valueRaw: {
240
- version: '0.2.5',
240
+ version: '0.2.7',
241
241
  events: [
242
242
  {
243
243
  at: new Date().toISOString(),
@@ -69,7 +69,7 @@ app.use(express_1.default.json({ limit: process.env.IRANTI_MAX_BODY_BYTES ?? '25
69
69
  app.get(ROUTES.health, (_req, res) => {
70
70
  res.json({
71
71
  status: 'ok',
72
- version: '0.2.5',
72
+ version: '0.2.7',
73
73
  provider: process.env.LLM_PROVIDER ?? 'mock',
74
74
  });
75
75
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iranti",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Memory infrastructure for multi-agent AI systems",
5
5
  "main": "dist/src/sdk/index.js",
6
6
  "files": [