iranti 0.3.2 → 0.3.3
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 +873 -873
- package/bin/iranti.js +1 -1
- package/dist/scripts/claude-code-memory-hook.js +1 -0
- package/dist/scripts/codex-setup.js +1 -1
- package/dist/scripts/iranti-cli.js +75 -8
- package/dist/scripts/iranti-mcp.js +75 -75
- package/dist/src/archivist/index.js +9 -9
- package/dist/src/attendant/AttendantInstance.d.ts +3 -1
- package/dist/src/attendant/AttendantInstance.d.ts.map +1 -1
- package/dist/src/attendant/AttendantInstance.js +92 -64
- package/dist/src/attendant/AttendantInstance.js.map +1 -1
- package/dist/src/lib/cliHelpCatalog.d.ts.map +1 -1
- package/dist/src/lib/cliHelpCatalog.js +4 -3
- package/dist/src/lib/cliHelpCatalog.js.map +1 -1
- package/dist/src/lib/hostMemoryFormatting.d.ts.map +1 -1
- package/dist/src/lib/hostMemoryFormatting.js +1 -0
- package/dist/src/lib/hostMemoryFormatting.js.map +1 -1
- package/dist/src/lib/llm.d.ts.map +1 -1
- package/dist/src/lib/llm.js +3 -1
- package/dist/src/lib/llm.js.map +1 -1
- package/dist/src/lib/projectLearning.js +1 -1
- package/dist/src/lib/projectLearning.js.map +1 -1
- package/dist/src/librarian/index.js +51 -51
- package/dist/src/library/client.d.ts.map +1 -1
- package/dist/src/library/client.js +0 -1
- package/dist/src/library/client.js.map +1 -1
- package/dist/src/library/queries.js +56 -56
- package/package.json +1 -1
|
@@ -72,7 +72,7 @@ const ATTEND_EXPECTED_CALL_SEQUENCE = [
|
|
|
72
72
|
"Call iranti_attend(phase='post-response') after every response without exception — even short replies may contain durable findings. Omitting this call is a compliance violation.",
|
|
73
73
|
'Call iranti_attend again when the new knowledge should change what is loaded next.',
|
|
74
74
|
];
|
|
75
|
-
const ATTEND_USAGE_REMINDER = 'Iranti is a hive mind.
|
|
75
|
+
const ATTEND_USAGE_REMINDER = 'Iranti is a hive mind. MANDATORY: call iranti_attend before every reply and around knowledge discovery. MANDATORY: call iranti_write after every file edit, confirmed finding, environment state change, and subagent completion — write what changed, why, and what it means. Skipping writes means the next session starts blind and must rediscover everything from scratch.';
|
|
76
76
|
const OBSERVE_USAGE_NOTE = 'observe() is retrieval-only. It surfaces candidate facts for context and warm-up, but it does not persist memory, replace iranti_attend, or count as a checkpoint/write.';
|
|
77
77
|
function normalizeContinuityKey(key) {
|
|
78
78
|
return LEGACY_CONTINUITY_KEY_MAP[key] ?? key;
|
|
@@ -352,10 +352,20 @@ function advisoryTaskTokens(taskType) {
|
|
|
352
352
|
.map((token) => token.trim())
|
|
353
353
|
.filter((token) => token.length >= 4)));
|
|
354
354
|
}
|
|
355
|
-
function buildUsageGuidance(tool) {
|
|
355
|
+
function buildUsageGuidance(tool, turnsWithoutWrite = 0) {
|
|
356
|
+
let reminder = ATTEND_USAGE_REMINDER;
|
|
357
|
+
if (turnsWithoutWrite >= 3) {
|
|
358
|
+
reminder += ` NON-COMPLIANT: ${turnsWithoutWrite} turns have completed without a single iranti_write call. You are losing knowledge. Call iranti_write NOW for any findings, file changes, or decisions from recent turns.`;
|
|
359
|
+
}
|
|
360
|
+
else if (turnsWithoutWrite >= 2) {
|
|
361
|
+
reminder += ` WARNING: ${turnsWithoutWrite} turns without an iranti_write call. If you discovered, changed, or confirmed anything, write it now before it is lost.`;
|
|
362
|
+
}
|
|
363
|
+
else if (turnsWithoutWrite === 1) {
|
|
364
|
+
reminder += ' Reminder: if the previous turn produced durable findings, call iranti_write before continuing.';
|
|
365
|
+
}
|
|
356
366
|
return {
|
|
357
367
|
tool,
|
|
358
|
-
reminder
|
|
368
|
+
reminder,
|
|
359
369
|
expectedCallSequence: ATTEND_EXPECTED_CALL_SEQUENCE,
|
|
360
370
|
note: tool === 'observe'
|
|
361
371
|
? OBSERVE_USAGE_NOTE
|
|
@@ -587,6 +597,16 @@ function buildSessionComplianceState(input) {
|
|
|
587
597
|
requiredAction: 'Persist durable findings with iranti_write or iranti_checkpoint before the next turn if new knowledge, validation, or file changes occurred.',
|
|
588
598
|
});
|
|
589
599
|
}
|
|
600
|
+
if (input.turnsWithoutWrite >= 2) {
|
|
601
|
+
const severity = input.turnsWithoutWrite >= 3 ? 'error' : 'warn';
|
|
602
|
+
issues.push({
|
|
603
|
+
code: 'missing_writes_across_turns',
|
|
604
|
+
severity,
|
|
605
|
+
count: input.turnsWithoutWrite,
|
|
606
|
+
message: `${input.turnsWithoutWrite} completed turns without a single iranti_write or iranti_checkpoint call. Knowledge discovered during these turns is not being persisted.`,
|
|
607
|
+
requiredAction: 'Call iranti_write for each durable finding — file edits, confirmed facts, environment state, subagent results. Every turn that discovers something should write it.',
|
|
608
|
+
});
|
|
609
|
+
}
|
|
590
610
|
if (input.consecutiveUnusedMemoryInjections > 0) {
|
|
591
611
|
const severity = input.consecutiveUnusedMemoryInjections >= 2 ? 'error' : 'warn';
|
|
592
612
|
issues.push({
|
|
@@ -613,12 +633,12 @@ function buildSessionComplianceState(input) {
|
|
|
613
633
|
: status === 'degraded'
|
|
614
634
|
? input.consecutiveUnusedMemoryInjections > 0
|
|
615
635
|
? 'Lifecycle is degraded: injected memory was surfaced but not used.'
|
|
616
|
-
: 'Lifecycle is degraded:
|
|
636
|
+
: 'Lifecycle is degraded: iranti_write has not been called after recent knowledge-changing actions.'
|
|
617
637
|
: input.consecutivePreResponseWithoutPost > 0
|
|
618
638
|
? 'Lifecycle is non-compliant: the previous turn is still missing a post-response attend.'
|
|
619
639
|
: input.consecutiveUnusedMemoryInjections > 0
|
|
620
640
|
? 'Lifecycle is non-compliant: injected memory is being ignored instead of used or explicitly challenged.'
|
|
621
|
-
: 'Lifecycle is non-compliant:
|
|
641
|
+
: 'Lifecycle is non-compliant: iranti_write calls are missing — durable findings are not being persisted.';
|
|
622
642
|
return {
|
|
623
643
|
status,
|
|
624
644
|
summary,
|
|
@@ -626,6 +646,7 @@ function buildSessionComplianceState(input) {
|
|
|
626
646
|
lastUpdated: input.lastUpdated ?? new Date().toISOString(),
|
|
627
647
|
counters: {
|
|
628
648
|
attendsWithoutPersist: input.attendsWithoutPersist,
|
|
649
|
+
turnsWithoutWrite: input.turnsWithoutWrite,
|
|
629
650
|
consecutivePreResponseWithoutPost: input.consecutivePreResponseWithoutPost,
|
|
630
651
|
consecutiveUnusedMemoryInjections: input.consecutiveUnusedMemoryInjections,
|
|
631
652
|
pendingPostResponse,
|
|
@@ -1327,6 +1348,7 @@ class AttendantInstance {
|
|
|
1327
1348
|
this.advisoryLearningProfile = null;
|
|
1328
1349
|
this.contextCallCount = 0;
|
|
1329
1350
|
this.attendsWithoutPersist = 0;
|
|
1351
|
+
this.turnsWithoutWrite = 0;
|
|
1330
1352
|
this.consecutivePreResponseWithoutPost = 0;
|
|
1331
1353
|
this.consecutiveUnusedMemoryInjections = 0;
|
|
1332
1354
|
this.lastAttendPhase = undefined;
|
|
@@ -1792,6 +1814,7 @@ class AttendantInstance {
|
|
|
1792
1814
|
buildComplianceState(lastUpdated) {
|
|
1793
1815
|
return buildSessionComplianceState({
|
|
1794
1816
|
attendsWithoutPersist: this.attendsWithoutPersist,
|
|
1817
|
+
turnsWithoutWrite: this.turnsWithoutWrite,
|
|
1795
1818
|
consecutivePreResponseWithoutPost: this.consecutivePreResponseWithoutPost,
|
|
1796
1819
|
consecutiveUnusedMemoryInjections: this.consecutiveUnusedMemoryInjections,
|
|
1797
1820
|
lastAttendPhase: this.lastAttendPhase,
|
|
@@ -1800,6 +1823,7 @@ class AttendantInstance {
|
|
|
1800
1823
|
}
|
|
1801
1824
|
async notifyWriteOccurred() {
|
|
1802
1825
|
this.attendsWithoutPersist = 0;
|
|
1826
|
+
this.turnsWithoutWrite = 0;
|
|
1803
1827
|
this.lastAttendPhase = undefined;
|
|
1804
1828
|
this.consecutivePreResponseWithoutPost = 0;
|
|
1805
1829
|
this.complianceUpdatedAt = new Date().toISOString();
|
|
@@ -1816,6 +1840,7 @@ class AttendantInstance {
|
|
|
1816
1840
|
}
|
|
1817
1841
|
async checkpoint(input) {
|
|
1818
1842
|
this.attendsWithoutPersist = 0;
|
|
1843
|
+
this.turnsWithoutWrite = 0;
|
|
1819
1844
|
this.lastAttendPhase = undefined;
|
|
1820
1845
|
this.consecutivePreResponseWithoutPost = 0;
|
|
1821
1846
|
this.complianceUpdatedAt = new Date().toISOString();
|
|
@@ -2055,8 +2080,10 @@ class AttendantInstance {
|
|
|
2055
2080
|
let complianceWarning;
|
|
2056
2081
|
const ignoredMemoryWarning = 'COMPLIANCE: injected memory was surfaced but not used. On the next turn, either answer from injected facts directly or persist why the injected memory was insufficient before rediscovering the same state manually.';
|
|
2057
2082
|
if (phase === 'post-response') {
|
|
2058
|
-
// Correct post-response call — reset counters
|
|
2083
|
+
// Correct post-response call — reset attend counters but NOT turnsWithoutWrite
|
|
2084
|
+
// turnsWithoutWrite only resets on actual writes/checkpoints
|
|
2059
2085
|
this.attendsWithoutPersist = 0;
|
|
2086
|
+
this.turnsWithoutWrite++;
|
|
2060
2087
|
this.lastAttendPhase = 'post-response';
|
|
2061
2088
|
this.consecutivePreResponseWithoutPost = 0;
|
|
2062
2089
|
}
|
|
@@ -2143,7 +2170,7 @@ class AttendantInstance {
|
|
|
2143
2170
|
complianceWarning,
|
|
2144
2171
|
compliance,
|
|
2145
2172
|
memoryAttributions,
|
|
2146
|
-
usageGuidance: buildUsageGuidance('attend'),
|
|
2173
|
+
usageGuidance: buildUsageGuidance('attend', this.turnsWithoutWrite),
|
|
2147
2174
|
facts: [],
|
|
2148
2175
|
entitiesDetected: [],
|
|
2149
2176
|
alreadyPresent: 0,
|
|
@@ -2221,7 +2248,7 @@ class AttendantInstance {
|
|
|
2221
2248
|
complianceWarning,
|
|
2222
2249
|
compliance,
|
|
2223
2250
|
memoryAttributions: [],
|
|
2224
|
-
usageGuidance: buildUsageGuidance('attend'),
|
|
2251
|
+
usageGuidance: buildUsageGuidance('attend', this.turnsWithoutWrite),
|
|
2225
2252
|
facts: [],
|
|
2226
2253
|
entitiesDetected: [],
|
|
2227
2254
|
alreadyPresent: 0,
|
|
@@ -2313,7 +2340,7 @@ class AttendantInstance {
|
|
|
2313
2340
|
complianceWarning,
|
|
2314
2341
|
compliance,
|
|
2315
2342
|
memoryAttributions,
|
|
2316
|
-
usageGuidance: buildUsageGuidance('attend'),
|
|
2343
|
+
usageGuidance: buildUsageGuidance('attend', this.turnsWithoutWrite),
|
|
2317
2344
|
};
|
|
2318
2345
|
if (input.suppressEvents !== true) {
|
|
2319
2346
|
(0, staffEventRegistry_1.getStaffEventEmitter)().emit({
|
|
@@ -2426,29 +2453,29 @@ class AttendantInstance {
|
|
|
2426
2453
|
const entityResponse = await (0, router_1.route)('extraction', [
|
|
2427
2454
|
{
|
|
2428
2455
|
role: 'user',
|
|
2429
|
-
content: `Extract explicitly named entities from the text.
|
|
2430
|
-
An entity can be a person, organization, project, technology, or named concept.
|
|
2431
|
-
|
|
2432
|
-
Return ONLY valid JSON as an array of objects in this exact shape:
|
|
2433
|
-
[
|
|
2434
|
-
{
|
|
2435
|
-
"type": "project",
|
|
2436
|
-
"name": "Project Atlas",
|
|
2437
|
-
"id_guess": "project_atlas",
|
|
2438
|
-
"confidence": 0.92,
|
|
2439
|
-
"evidence": "Project Atlas",
|
|
2440
|
-
"start": 123,
|
|
2441
|
-
"end": 136
|
|
2442
|
-
}
|
|
2443
|
-
]
|
|
2444
|
-
|
|
2445
|
-
Rules:
|
|
2446
|
-
- Only include entities explicitly named in the provided text.
|
|
2447
|
-
- Do not infer or carry over entities not present in the text.
|
|
2448
|
-
- If uncertain, omit.
|
|
2449
|
-
- If none are present, return [].
|
|
2450
|
-
|
|
2451
|
-
Text:
|
|
2456
|
+
content: `Extract explicitly named entities from the text.
|
|
2457
|
+
An entity can be a person, organization, project, technology, or named concept.
|
|
2458
|
+
|
|
2459
|
+
Return ONLY valid JSON as an array of objects in this exact shape:
|
|
2460
|
+
[
|
|
2461
|
+
{
|
|
2462
|
+
"type": "project",
|
|
2463
|
+
"name": "Project Atlas",
|
|
2464
|
+
"id_guess": "project_atlas",
|
|
2465
|
+
"confidence": 0.92,
|
|
2466
|
+
"evidence": "Project Atlas",
|
|
2467
|
+
"start": 123,
|
|
2468
|
+
"end": 136
|
|
2469
|
+
}
|
|
2470
|
+
]
|
|
2471
|
+
|
|
2472
|
+
Rules:
|
|
2473
|
+
- Only include entities explicitly named in the provided text.
|
|
2474
|
+
- Do not infer or carry over entities not present in the text.
|
|
2475
|
+
- If uncertain, omit.
|
|
2476
|
+
- If none are present, return [].
|
|
2477
|
+
|
|
2478
|
+
Text:
|
|
2452
2479
|
${detectionWindow}`,
|
|
2453
2480
|
},
|
|
2454
2481
|
], 512);
|
|
@@ -2782,21 +2809,21 @@ ${detectionWindow}`,
|
|
|
2782
2809
|
const response = await (0, router_1.route)('classification', [
|
|
2783
2810
|
{
|
|
2784
2811
|
role: 'user',
|
|
2785
|
-
content: `Decide whether this assistant should fetch persistent memory before replying.
|
|
2786
|
-
|
|
2787
|
-
Latest user message:
|
|
2788
|
-
${input.latestMessage || '(none)'}
|
|
2789
|
-
|
|
2790
|
-
Recent context excerpt:
|
|
2791
|
-
${contextWindow || '(empty)'}
|
|
2792
|
-
|
|
2793
|
-
Return ONLY valid JSON with this exact shape:
|
|
2794
|
-
{"needsMemory":true,"confidence":0.81,"reason":"short_reason"}
|
|
2795
|
-
|
|
2796
|
-
Rules:
|
|
2797
|
-
- needsMemory=true when the message involves project context, technical decisions, code state, prior work, open tasks, bugs, architecture, preferences, or anything session- or project-specific.
|
|
2798
|
-
- needsMemory=true when in doubt — false positives are cheap, false negatives lose context.
|
|
2799
|
-
- needsMemory=false ONLY for clear one-word acks, simple greetings, or purely generic factual questions with no project relevance.
|
|
2812
|
+
content: `Decide whether this assistant should fetch persistent memory before replying.
|
|
2813
|
+
|
|
2814
|
+
Latest user message:
|
|
2815
|
+
${input.latestMessage || '(none)'}
|
|
2816
|
+
|
|
2817
|
+
Recent context excerpt:
|
|
2818
|
+
${contextWindow || '(empty)'}
|
|
2819
|
+
|
|
2820
|
+
Return ONLY valid JSON with this exact shape:
|
|
2821
|
+
{"needsMemory":true,"confidence":0.81,"reason":"short_reason"}
|
|
2822
|
+
|
|
2823
|
+
Rules:
|
|
2824
|
+
- needsMemory=true when the message involves project context, technical decisions, code state, prior work, open tasks, bugs, architecture, preferences, or anything session- or project-specific.
|
|
2825
|
+
- needsMemory=true when in doubt — false positives are cheap, false negatives lose context.
|
|
2826
|
+
- needsMemory=false ONLY for clear one-word acks, simple greetings, or purely generic factual questions with no project relevance.
|
|
2800
2827
|
- confidence is a float from 0 to 1.`,
|
|
2801
2828
|
},
|
|
2802
2829
|
], 128);
|
|
@@ -3159,14 +3186,14 @@ Rules:
|
|
|
3159
3186
|
const response = await (0, router_1.route)('task_inference', [
|
|
3160
3187
|
{
|
|
3161
3188
|
role: 'user',
|
|
3162
|
-
content: `You are analyzing what an AI agent is currently working on.
|
|
3163
|
-
|
|
3164
|
-
Agent ID: ${this.agentId}
|
|
3165
|
-
Task description: ${context.task}
|
|
3166
|
-
Recent messages:
|
|
3167
|
-
${context.recentMessages.map((m, i) => `${i + 1}. ${m}`).join('\n')}
|
|
3168
|
-
|
|
3169
|
-
In one short sentence, describe the specific type of task this agent is currently performing.
|
|
3189
|
+
content: `You are analyzing what an AI agent is currently working on.
|
|
3190
|
+
|
|
3191
|
+
Agent ID: ${this.agentId}
|
|
3192
|
+
Task description: ${context.task}
|
|
3193
|
+
Recent messages:
|
|
3194
|
+
${context.recentMessages.map((m, i) => `${i + 1}. ${m}`).join('\n')}
|
|
3195
|
+
|
|
3196
|
+
In one short sentence, describe the specific type of task this agent is currently performing.
|
|
3170
3197
|
Be specific and concrete.`,
|
|
3171
3198
|
},
|
|
3172
3199
|
], 256);
|
|
@@ -3199,15 +3226,15 @@ Be specific and concrete.`,
|
|
|
3199
3226
|
const response = await (0, router_1.route)('relevance_filtering', [
|
|
3200
3227
|
{
|
|
3201
3228
|
role: 'user',
|
|
3202
|
-
content: `You are deciding what knowledge an AI agent needs for its current task.
|
|
3203
|
-
|
|
3204
|
-
Agent task: ${taskType}
|
|
3205
|
-
|
|
3206
|
-
Available knowledge entries:
|
|
3207
|
-
${entryInputs.map((e, i) => `${i + 1}. [${e.key}] ${e.valueSummary} (confidence: ${e.confidence})`).join('\n')}
|
|
3208
|
-
|
|
3209
|
-
Return only the numbers of entries that are directly relevant to the current task.
|
|
3210
|
-
Format: comma-separated numbers only. Example: 1,3,5
|
|
3229
|
+
content: `You are deciding what knowledge an AI agent needs for its current task.
|
|
3230
|
+
|
|
3231
|
+
Agent task: ${taskType}
|
|
3232
|
+
|
|
3233
|
+
Available knowledge entries:
|
|
3234
|
+
${entryInputs.map((e, i) => `${i + 1}. [${e.key}] ${e.valueSummary} (confidence: ${e.confidence})`).join('\n')}
|
|
3235
|
+
|
|
3236
|
+
Return only the numbers of entries that are directly relevant to the current task.
|
|
3237
|
+
Format: comma-separated numbers only. Example: 1,3,5
|
|
3211
3238
|
If nothing is relevant, return: none`,
|
|
3212
3239
|
},
|
|
3213
3240
|
], 128);
|
|
@@ -3272,6 +3299,7 @@ If nothing is relevant, return: none`,
|
|
|
3272
3299
|
this.advisoryLearningProfile = null;
|
|
3273
3300
|
this.sharedStateObservedAt = state.briefGeneratedAt;
|
|
3274
3301
|
this.attendsWithoutPersist = state.compliance?.counters.attendsWithoutPersist ?? 0;
|
|
3302
|
+
this.turnsWithoutWrite = state.compliance?.counters.turnsWithoutWrite ?? 0;
|
|
3275
3303
|
this.consecutivePreResponseWithoutPost = state.compliance?.counters.consecutivePreResponseWithoutPost ?? 0;
|
|
3276
3304
|
this.consecutiveUnusedMemoryInjections = state.compliance?.counters.consecutiveUnusedMemoryInjections ?? 0;
|
|
3277
3305
|
this.lastAttendPhase = state.compliance?.counters.lastAttendPhase ?? undefined;
|