instar 0.6.11 → 0.6.13

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.
@@ -196,10 +196,11 @@ async function initFreshProject(projectName, options) {
196
196
  console.log(` ${pc.green('✓')} Created .claude/scripts/health-watchdog.sh`);
197
197
  installSmartFetch(projectDir);
198
198
  console.log(` ${pc.green('✓')} Created .claude/scripts/smart-fetch.py (agentic web conventions)`);
199
- // Create .claude/skills/ directory for agent-created skills
199
+ // Create .claude/skills/ directory and install built-in skills
200
200
  const skillsDir = path.join(projectDir, '.claude', 'skills');
201
201
  fs.mkdirSync(skillsDir, { recursive: true });
202
- console.log(` ${pc.green('✓')} Created .claude/skills/ (agent skill directory)`);
202
+ installBuiltinSkills(skillsDir, port);
203
+ console.log(` ${pc.green('✓')} Created .claude/skills/ (with built-in evolution skills)`);
203
204
  // Write CLAUDE.md (standalone version for fresh projects)
204
205
  const claudeMd = generateClaudeMd(projectName, identity.name, port, false);
205
206
  fs.writeFileSync(path.join(projectDir, 'CLAUDE.md'), claudeMd);
@@ -401,10 +402,11 @@ async function initExistingProject(options) {
401
402
  // Install smart-fetch for agentic web conventions
402
403
  installSmartFetch(projectDir);
403
404
  console.log(pc.green(' Created:') + ' .claude/scripts/smart-fetch.py (agentic web conventions)');
404
- // Create .claude/skills/ directory for agent-created skills
405
+ // Create .claude/skills/ directory and install built-in skills
405
406
  const skillsDir = path.join(projectDir, '.claude', 'skills');
406
407
  fs.mkdirSync(skillsDir, { recursive: true });
407
- console.log(pc.green(' Created:') + ' .claude/skills/ (agent skill directory)');
408
+ installBuiltinSkills(skillsDir, port);
409
+ console.log(pc.green(' Created:') + ' .claude/skills/ (with built-in evolution skills)');
408
410
  // Append to .gitignore
409
411
  const gitignorePath = path.join(projectDir, '.gitignore');
410
412
  const instarIgnores = '\n# Instar runtime state (contains auth token, session data, relationships)\n.instar/state/\n.instar/logs/\n.instar/relationships/\n.instar/config.json\n';
@@ -587,6 +589,38 @@ Instar has a built-in feedback loop. When something isn't working, your user can
587
589
  - Report: \`curl -X POST http://localhost:${port}/feedback -d '{"issue":"description","context":"relevant logs"}'\`
588
590
  - Check updates: \`npm outdated -g instar\`
589
591
 
592
+ ### Evolution System
593
+
594
+ You have a built-in evolution system with four subsystems. This is not a metaphor — it's infrastructure that tracks your growth.
595
+
596
+ **Evolution Queue** — Staged self-improvement proposals.
597
+ - View: \`curl http://localhost:${port}/evolution/proposals\`
598
+ - Propose: \`/evolve\` skill or \`POST /evolution/proposals\`
599
+ - The \`evolution-review\` job evaluates and implements proposals every 6 hours.
600
+
601
+ **Learning Registry** — Structured, searchable insights.
602
+ - View: \`curl http://localhost:${port}/evolution/learnings\`
603
+ - Record: \`/learn\` skill or \`POST /evolution/learnings\`
604
+ - The \`insight-harvest\` job synthesizes patterns into proposals every 8 hours.
605
+
606
+ **Capability Gaps** — Track what you're missing.
607
+ - View: \`curl http://localhost:${port}/evolution/gaps\`
608
+ - Report: \`/gaps\` skill or \`POST /evolution/gaps\`
609
+
610
+ **Action Queue** — Commitments with follow-through tracking.
611
+ - View: \`curl http://localhost:${port}/evolution/actions\`
612
+ - Create: \`/commit-action\` skill or \`POST /evolution/actions\`
613
+ - The \`commitment-check\` job surfaces overdue items every 4 hours.
614
+
615
+ **Dashboard** — Full evolution health:
616
+ \`\`\`bash
617
+ curl http://localhost:${port}/evolution
618
+ \`\`\`
619
+
620
+ **Skills:** \`/evolve\`, \`/learn\`, \`/gaps\`, \`/commit-action\`
621
+
622
+ **The principle:** Evolution is not separate from work. Every task is an opportunity to notice what could be better. The post-action reflection hook reminds you to pause after significant actions and consider what you learned.
623
+
590
624
  ### Self-Evolution
591
625
 
592
626
  **Record what you learn.** When you discover a new pattern, solution, or capability — write it to \`.instar/MEMORY.md\`. The next session should benefit from what this session learned.
@@ -597,6 +631,230 @@ Instar has a built-in feedback loop. When something isn't working, your user can
597
631
  `;
598
632
  return section;
599
633
  }
634
+ /**
635
+ * Install built-in skills for evolution system.
636
+ * Only writes skill files that don't already exist (preserves customizations).
637
+ */
638
+ function installBuiltinSkills(skillsDir, port) {
639
+ const skills = {
640
+ 'evolve': {
641
+ name: 'evolve',
642
+ description: 'Propose an evolution improvement to your own infrastructure, behavior, or capabilities.',
643
+ content: `---
644
+ name: evolve
645
+ description: Propose an evolution improvement to your own infrastructure, behavior, or capabilities.
646
+ metadata:
647
+ user_invocable: "true"
648
+ ---
649
+
650
+ # /evolve
651
+
652
+ Propose an evolution improvement. Use this when you identify something about yourself that could be better — a new capability, a workflow improvement, a behavioral pattern worth encoding, or infrastructure worth building.
653
+
654
+ ## Steps
655
+
656
+ 1. **Identify the improvement** — What did you notice? What triggered this? Be specific.
657
+ 2. **Classify it**:
658
+ - \`capability\` — New skill or ability
659
+ - \`infrastructure\` — System improvement (hooks, jobs, scripts)
660
+ - \`voice\` — Communication or tone improvement
661
+ - \`workflow\` — Process improvement
662
+ - \`philosophy\` — Principle or value update
663
+ - \`integration\` — New external connection
664
+ - \`performance\` — Speed or efficiency improvement
665
+ 3. **Assess impact and effort** (high/medium/low for each)
666
+ 4. **Submit the proposal**:
667
+
668
+ \`\`\`bash
669
+ curl -s -X POST http://localhost:${port}/evolution/proposals \\
670
+ -H 'Content-Type: application/json' \\
671
+ -d '{"title":"TITLE","source":"WHERE_YOU_NOTICED","description":"WHAT_AND_WHY","type":"TYPE","impact":"medium","effort":"medium"}'
672
+ \`\`\`
673
+
674
+ 5. **Check the dashboard** for context:
675
+
676
+ \`\`\`bash
677
+ curl -s http://localhost:${port}/evolution
678
+ \`\`\`
679
+
680
+ ## When to Use
681
+
682
+ - After completing a task in a way that felt unnecessarily difficult
683
+ - When you notice a pattern you keep repeating manually
684
+ - When a user request reveals a capability you should have but don't
685
+ - When you find yourself working around a limitation
686
+ - After reading about a technique or pattern that would improve your work
687
+
688
+ ## Philosophy
689
+
690
+ Evolution is not a separate activity from work — it IS the work. Every task is an opportunity to notice what could be better. The best proposals come from real experience, not abstract planning.
691
+ `,
692
+ },
693
+ 'learn': {
694
+ name: 'learn',
695
+ description: 'Record a learning or insight in the structured learning registry.',
696
+ content: `---
697
+ name: learn
698
+ description: Record a learning or insight in the structured learning registry.
699
+ metadata:
700
+ user_invocable: "true"
701
+ ---
702
+
703
+ # /learn
704
+
705
+ Record a learning or insight. Use this when you discover something worth remembering — a pattern, a solution, a mistake, or an observation that future sessions should know about.
706
+
707
+ ## Steps
708
+
709
+ 1. **Identify the learning** — What did you discover? What's the actionable insight?
710
+ 2. **Categorize it** (e.g., debugging, architecture, user-preference, integration, communication, workflow)
711
+ 3. **Tag it** for searchability
712
+ 4. **Submit**:
713
+
714
+ \`\`\`bash
715
+ curl -s -X POST http://localhost:${port}/evolution/learnings \\
716
+ -H 'Content-Type: application/json' \\
717
+ -d '{"title":"TITLE","category":"CATEGORY","description":"FULL_INSIGHT","source":{"discoveredAt":"DATE","platform":"WHERE","session":"SESSION_ID"},"tags":["tag1","tag2"]}'
718
+ \`\`\`
719
+
720
+ 5. **If it suggests an improvement**, note the evolution relevance:
721
+ - Add \`"evolutionRelevance": "This could become a skill/hook/job because..."\`
722
+ - The insight-harvest job will pick this up and potentially create a proposal
723
+
724
+ ## When to Use
725
+
726
+ - After solving a tricky problem (capture the solution pattern)
727
+ - After a user interaction reveals a preference you didn't know
728
+ - After discovering a tool or technique that works well
729
+ - After making a mistake (capture what went wrong and the fix)
730
+ - After noticing a pattern across multiple tasks
731
+
732
+ ## Difference from MEMORY.md
733
+
734
+ MEMORY.md is your personal scratchpad — unstructured, read by you.
735
+ The learning registry is structured, searchable, and connected to the evolution system.
736
+ Use MEMORY.md for quick notes. Use /learn for insights that should influence future behavior.
737
+ `,
738
+ },
739
+ 'gaps': {
740
+ name: 'gaps',
741
+ description: 'Report a capability gap — something you need but don\'t have.',
742
+ content: `---
743
+ name: gaps
744
+ description: Report a capability gap — something you need but don't have.
745
+ metadata:
746
+ user_invocable: "true"
747
+ ---
748
+
749
+ # /gaps
750
+
751
+ Report a capability gap. Use this when you discover something you should be able to do but can't — a missing skill, knowledge area, integration, or workflow that would make you more effective.
752
+
753
+ ## Steps
754
+
755
+ 1. **Describe the gap** — What were you trying to do? What's missing?
756
+ 2. **Classify it**:
757
+ - \`skill\` — Missing ability (e.g., can't parse a specific format)
758
+ - \`knowledge\` — Missing information (e.g., don't know how a system works)
759
+ - \`integration\` — Missing connection (e.g., can't talk to a service)
760
+ - \`workflow\` — Missing process (e.g., no standard way to do X)
761
+ - \`communication\` — Missing voice capability (e.g., can't express X well)
762
+ - \`monitoring\` — Missing observability (e.g., can't detect when X happens)
763
+ 3. **Assess severity** (critical/high/medium/low)
764
+ 4. **Describe current state** — What do you do instead? What's the workaround?
765
+ 5. **Propose a solution** if you have one
766
+ 6. **Submit**:
767
+
768
+ \`\`\`bash
769
+ curl -s -X POST http://localhost:${port}/evolution/gaps \\
770
+ -H 'Content-Type: application/json' \\
771
+ -d '{"title":"TITLE","category":"CATEGORY","severity":"medium","description":"WHAT_IS_MISSING","context":"WHEN_DID_YOU_NOTICE","currentState":"CURRENT_WORKAROUND","proposedSolution":"HOW_TO_FIX"}'
772
+ \`\`\`
773
+
774
+ ## When to Use
775
+
776
+ - When you can't fulfill a user request and have to say "I can't do that yet"
777
+ - When you notice yourself repeatedly working around a limitation
778
+ - When an integration you need doesn't exist
779
+ - When you lack knowledge about a system you interact with
780
+ - When monitoring would catch an issue before it becomes a problem
781
+
782
+ ## View Current Gaps
783
+
784
+ \`\`\`bash
785
+ curl -s http://localhost:${port}/evolution/gaps
786
+ \`\`\`
787
+ `,
788
+ },
789
+ 'commit-action': {
790
+ name: 'commit-action',
791
+ description: 'Create a tracked action item — a commitment with follow-through tracking.',
792
+ content: `---
793
+ name: commit-action
794
+ description: Create a tracked action item — a commitment with follow-through tracking.
795
+ metadata:
796
+ user_invocable: "true"
797
+ ---
798
+
799
+ # /commit-action
800
+
801
+ Create a tracked action item. Use this when you promise to do something, identify a task that needs follow-through, or want to ensure something doesn't fall through the cracks.
802
+
803
+ ## Steps
804
+
805
+ 1. **Define the action** — What needs to be done? Be specific and actionable.
806
+ 2. **Set priority** (critical/high/medium/low)
807
+ 3. **Set a due date** if applicable (ISO 8601 format)
808
+ 4. **Identify who/what you're committing to** (optional)
809
+ 5. **Submit**:
810
+
811
+ \`\`\`bash
812
+ curl -s -X POST http://localhost:${port}/evolution/actions \\
813
+ -H 'Content-Type: application/json' \\
814
+ -d '{"title":"TITLE","description":"WHAT_TO_DO","priority":"medium","dueBy":"2026-03-01T00:00:00Z","commitTo":"WHO_OR_WHAT","tags":["tag1"]}'
815
+ \`\`\`
816
+
817
+ 6. **When complete**, mark it done:
818
+
819
+ \`\`\`bash
820
+ curl -s -X PATCH http://localhost:${port}/evolution/actions/ACT-XXX \\
821
+ -H 'Content-Type: application/json' \\
822
+ -d '{"status":"completed","resolution":"What was done"}'
823
+ \`\`\`
824
+
825
+ ## When to Use
826
+
827
+ - When you promise a user you'll follow up on something
828
+ - When you identify a task during work that shouldn't be forgotten
829
+ - When a learning or gap requires a specific action
830
+ - When you need to check back on something later
831
+ - When committing to implement an evolution proposal
832
+
833
+ ## View Actions
834
+
835
+ \`\`\`bash
836
+ # All pending actions
837
+ curl -s http://localhost:${port}/evolution/actions?status=pending
838
+
839
+ # Overdue actions
840
+ curl -s http://localhost:${port}/evolution/actions/overdue
841
+ \`\`\`
842
+
843
+ ## The Commitment Check
844
+
845
+ The commitment-check job runs every 4 hours and surfaces overdue items. If you create an action and forget it, the system won't.
846
+ `,
847
+ },
848
+ };
849
+ for (const [slug, skill] of Object.entries(skills)) {
850
+ const skillDir = path.join(skillsDir, slug);
851
+ const skillFile = path.join(skillDir, 'SKILL.md');
852
+ if (!fs.existsSync(skillFile)) {
853
+ fs.mkdirSync(skillDir, { recursive: true });
854
+ fs.writeFileSync(skillFile, skill.content);
855
+ }
856
+ }
857
+ }
600
858
  function getDefaultJobs(port) {
601
859
  return [
602
860
  {
@@ -727,6 +985,92 @@ If everything looks healthy, exit silently. Only report issues.`,
727
985
  },
728
986
  tags: ['coherence', 'default'],
729
987
  },
988
+ {
989
+ slug: 'evolution-review',
990
+ name: 'Evolution Review',
991
+ description: 'Review pending evolution proposals, evaluate their merit, and implement approved ones.',
992
+ schedule: '0 */6 * * *',
993
+ priority: 'medium',
994
+ expectedDurationMinutes: 5,
995
+ model: 'sonnet',
996
+ enabled: true,
997
+ gate: `curl -sf http://localhost:${port}/evolution/proposals?status=proposed 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); exit(0 if len(d.get('proposals',[])) > 0 else 1)"`,
998
+ execute: {
999
+ type: 'prompt',
1000
+ value: `Review pending evolution proposals: curl -s http://localhost:${port}/evolution/proposals?status=proposed
1001
+
1002
+ For each proposal:
1003
+ 1. Read the title, description, type, and source
1004
+ 2. Evaluate: Is this a genuine improvement? Is the effort worth the impact? Does it align with our goals?
1005
+ 3. If approved, update status: curl -s -X PATCH http://localhost:${port}/evolution/proposals/EVO-XXX -H 'Content-Type: application/json' -d '{"status":"approved"}'
1006
+ 4. Then implement it: create the skill/hook/job/config change described in the proposal
1007
+ 5. After implementation, mark complete: curl -s -X PATCH http://localhost:${port}/evolution/proposals/EVO-XXX -H 'Content-Type: application/json' -d '{"status":"implemented","resolution":"What was done"}'
1008
+
1009
+ If a proposal should be deferred or rejected, update with reason.
1010
+
1011
+ Also check the dashboard: curl -s http://localhost:${port}/evolution — report any highlights to the user if they seem important.
1012
+
1013
+ If no proposals need attention, exit silently.`,
1014
+ },
1015
+ tags: ['coherence', 'default', 'evolution'],
1016
+ },
1017
+ {
1018
+ slug: 'insight-harvest',
1019
+ name: 'Insight Harvest',
1020
+ description: 'Synthesize learnings from the learning registry, detect patterns, and generate evolution proposals from high-confidence insights.',
1021
+ schedule: '0 */8 * * *',
1022
+ priority: 'low',
1023
+ expectedDurationMinutes: 3,
1024
+ model: 'sonnet',
1025
+ enabled: true,
1026
+ gate: `curl -sf http://localhost:${port}/evolution/learnings?applied=false 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); exit(0 if len(d.get('learnings',[])) > 0 else 1)"`,
1027
+ execute: {
1028
+ type: 'prompt',
1029
+ value: `Harvest and synthesize learnings: curl -s http://localhost:${port}/evolution/learnings?applied=false
1030
+
1031
+ Review unapplied learnings and look for:
1032
+ 1. **Patterns**: Multiple learnings pointing to the same conclusion
1033
+ 2. **Actionable insights**: Learnings that suggest a specific change
1034
+ 3. **Cross-domain connections**: Insights from one area that apply to another
1035
+
1036
+ For each actionable pattern found, create an evolution proposal:
1037
+ curl -s -X POST http://localhost:${port}/evolution/proposals -H 'Content-Type: application/json' -d '{"title":"...","source":"insight-harvest from LRN-XXX","description":"...","type":"...","impact":"...","effort":"..."}'
1038
+
1039
+ Then mark the relevant learnings as applied:
1040
+ curl -s -X PATCH http://localhost:${port}/evolution/learnings/LRN-XXX/apply -H 'Content-Type: application/json' -d '{"appliedTo":"EVO-XXX"}'
1041
+
1042
+ Also update MEMORY.md with any patterns worth preserving long-term.
1043
+
1044
+ If no actionable patterns found, exit silently.`,
1045
+ },
1046
+ tags: ['coherence', 'default', 'evolution'],
1047
+ },
1048
+ {
1049
+ slug: 'commitment-check',
1050
+ name: 'Commitment Check',
1051
+ description: 'Track action items and commitments. Surface overdue items and stale commitments.',
1052
+ schedule: '0 */4 * * *',
1053
+ priority: 'low',
1054
+ expectedDurationMinutes: 2,
1055
+ model: 'haiku',
1056
+ enabled: true,
1057
+ gate: `curl -sf http://localhost:${port}/evolution/actions/overdue 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); exit(0 if len(d.get('overdue',[])) > 0 else 1)"`,
1058
+ execute: {
1059
+ type: 'prompt',
1060
+ value: `Check for overdue commitments: curl -s http://localhost:${port}/evolution/actions/overdue
1061
+
1062
+ For each overdue action:
1063
+ 1. Assess: Can this be completed now? Is it still relevant?
1064
+ 2. If actionable, attempt to complete it or advance it
1065
+ 3. If no longer relevant, cancel it: curl -s -X PATCH http://localhost:${port}/evolution/actions/ACT-XXX -H 'Content-Type: application/json' -d '{"status":"cancelled","resolution":"No longer relevant because..."}'
1066
+ 4. If blocked, escalate to the user via Telegram (if configured)
1067
+
1068
+ Also check pending actions (curl -s http://localhost:${port}/evolution/actions?status=pending) for items that have been pending more than 48 hours without a due date — these are forgotten commitments.
1069
+
1070
+ If no overdue or stale items, exit silently.`,
1071
+ },
1072
+ tags: ['coherence', 'default', 'evolution'],
1073
+ },
730
1074
  ];
731
1075
  }
732
1076
  /**
@@ -915,6 +1259,33 @@ curl -s -X POST http://localhost:${port}/feedback \\
915
1259
  Types: \`bug\`, \`feature\`, \`improvement\`, \`question\`
916
1260
 
917
1261
  **Do not wait for the user to notice.** If a hook throws an error, report it. If a job fails, report it. If the server returns unexpected data, report it. You are not just using instar — you are part of its immune system.
1262
+ `);
1263
+ }
1264
+ // Check for Evolution System section
1265
+ if (!content.includes('Evolution System')) {
1266
+ additions.push(`
1267
+ ### Evolution System
1268
+
1269
+ You have a built-in evolution system with four subsystems that track your growth.
1270
+
1271
+ **Evolution Queue** — Staged self-improvement proposals.
1272
+ - View: \`curl http://localhost:${port}/evolution/proposals\`
1273
+ - Propose: \`/evolve\` skill or \`POST /evolution/proposals\`
1274
+
1275
+ **Learning Registry** — Structured, searchable insights.
1276
+ - View: \`curl http://localhost:${port}/evolution/learnings\`
1277
+ - Record: \`/learn\` skill or \`POST /evolution/learnings\`
1278
+
1279
+ **Capability Gaps** — Track what you're missing.
1280
+ - View: \`curl http://localhost:${port}/evolution/gaps\`
1281
+ - Report: \`/gaps\` skill or \`POST /evolution/gaps\`
1282
+
1283
+ **Action Queue** — Commitments with follow-through tracking.
1284
+ - View: \`curl http://localhost:${port}/evolution/actions\`
1285
+ - Create: \`/commit-action\` skill or \`POST /evolution/actions\`
1286
+
1287
+ **Dashboard**: \`curl http://localhost:${port}/evolution\`
1288
+ **Skills**: \`/evolve\`, \`/learn\`, \`/gaps\`, \`/commit-action\`
918
1289
  `);
919
1290
  }
920
1291
  // Check for Telegram Relay section (add if Telegram is configured)
@@ -965,6 +1336,15 @@ fi
965
1336
  # For startup/resume/clear — output a compact orientation
966
1337
  echo "=== SESSION START ==="
967
1338
 
1339
+ # Telegram-spawned session awareness
1340
+ # When auto-created for a Telegram topic, prime the agent to respond immediately
1341
+ if [ -n "\$INSTAR_TELEGRAM_TOPIC" ]; then
1342
+ echo ""
1343
+ echo "This session was auto-spawned for Telegram topic \$INSTAR_TELEGRAM_TOPIC."
1344
+ echo "A message from your user triggered this session and will arrive momentarily."
1345
+ echo "IMMEDIATELY acknowledge it via your Telegram relay — they are waiting."
1346
+ fi
1347
+
968
1348
  # Identity summary (first 20 lines of AGENT.md — enough for name + role)
969
1349
  if [ -f "$INSTAR_DIR/AGENT.md" ]; then
970
1350
  echo ""
@@ -1174,6 +1554,55 @@ process.stdin.on('end', () => {
1174
1554
  } catch { /* don't break on errors */ }
1175
1555
  process.exit(0);
1176
1556
  });
1557
+ `, { mode: 0o755 });
1558
+ // Post-action reflection — injects evolution awareness after significant actions.
1559
+ // PreToolUse hook for Bash. When the agent is about to send a response or commit,
1560
+ // it reminds them to consider what they learned. Advisory, not blocking.
1561
+ fs.writeFileSync(path.join(hooksDir, 'post-action-reflection.js'), `#!/usr/bin/env node
1562
+ // Post-action reflection — evolution awareness after significant actions.
1563
+ // PreToolUse hook for Bash. When the agent is about to commit, deploy, or
1564
+ // complete a task, injects a brief reminder to capture learnings.
1565
+ //
1566
+ // "Every action is an opportunity to learn. Most of that learning is lost
1567
+ // because nobody paused to ask: what did this teach me?"
1568
+
1569
+ let data = '';
1570
+ process.stdin.on('data', chunk => data += chunk);
1571
+ process.stdin.on('end', () => {
1572
+ try {
1573
+ const input = JSON.parse(data);
1574
+ if (input.tool_name !== 'Bash') process.exit(0);
1575
+
1576
+ const command = (input.tool_input || {}).command || '';
1577
+ if (!command) process.exit(0);
1578
+
1579
+ // Significant action patterns — moments worth reflecting on
1580
+ const significantPatterns = [
1581
+ /git\\s+commit/i,
1582
+ /git\\s+push/i,
1583
+ /npm\\s+publish/i,
1584
+ /curl\\s+-X\\s+POST.*\\/deploy/i,
1585
+ /instar\\s+server\\s+restart/i,
1586
+ ];
1587
+
1588
+ if (!significantPatterns.some(p => p.test(command))) process.exit(0);
1589
+
1590
+ const reminder = [
1591
+ 'POST-ACTION REFLECTION — Quick evolution check:',
1592
+ '',
1593
+ 'Before moving on, consider:',
1594
+ '- Did this teach you something worth recording? → /learn',
1595
+ '- Did you notice a gap in your capabilities? → /gaps',
1596
+ '- Did you discover an improvement opportunity? → /evolve',
1597
+ '- Did you make a commitment to follow up? → /commit-action',
1598
+ '',
1599
+ 'Skip if nothing notable. The value is in the pause, not the output.',
1600
+ ].join('\\n');
1601
+
1602
+ process.stdout.write(JSON.stringify({ decision: 'approve', additionalContext: reminder }));
1603
+ } catch { /* don't break on errors */ }
1604
+ process.exit(0);
1605
+ });
1177
1606
  `, { mode: 0o755 });
1178
1607
  // External communication guard — ensures identity grounding before external posting.
1179
1608
  // PreToolUse hook for Bash. Detects commands that post to external platforms.
@@ -1525,6 +1954,11 @@ function installClaudeSettings(projectDir) {
1525
1954
  command: 'node .instar/hooks/external-communication-guard.js',
1526
1955
  timeout: 5000,
1527
1956
  },
1957
+ {
1958
+ type: 'command',
1959
+ command: 'node .instar/hooks/post-action-reflection.js',
1960
+ timeout: 5000,
1961
+ },
1528
1962
  ];
1529
1963
  // PreToolUse: merge instar hooks into existing or create fresh
1530
1964
  if (!hooks.PreToolUse) {
@@ -18,6 +18,8 @@ import { JobScheduler } from '../scheduler/JobScheduler.js';
18
18
  import { AgentServer } from '../server/AgentServer.js';
19
19
  import { TelegramAdapter } from '../messaging/TelegramAdapter.js';
20
20
  import { RelationshipManager } from '../core/RelationshipManager.js';
21
+ import { ClaudeCliIntelligenceProvider } from '../core/ClaudeCliIntelligenceProvider.js';
22
+ import { AnthropicIntelligenceProvider } from '../core/AnthropicIntelligenceProvider.js';
21
23
  import { FeedbackManager } from '../core/FeedbackManager.js';
22
24
  import { DispatchManager } from '../core/DispatchManager.js';
23
25
  import { UpdateChecker } from '../core/UpdateChecker.js';
@@ -25,6 +27,7 @@ import { registerPort, unregisterPort, startHeartbeat } from '../core/PortRegist
25
27
  import { TelegraphService } from '../publishing/TelegraphService.js';
26
28
  import { PrivateViewer } from '../publishing/PrivateViewer.js';
27
29
  import { TunnelManager } from '../tunnel/TunnelManager.js';
30
+ import { EvolutionManager } from '../core/EvolutionManager.js';
28
31
  /**
29
32
  * Respawn a session for a topic, including thread history in the bootstrap.
30
33
  * This prevents "thread drift" where respawned sessions lose context.
@@ -218,9 +221,9 @@ function wireTelegramRouting(telegram, sessionManager) {
218
221
  const ctxPath = path.join(tmpDir, `ctx-${topicId}-${Date.now()}.txt`);
219
222
  fs.writeFileSync(ctxPath, contextLines.join('\n'));
220
223
  const bootstrapMessage = `[telegram:${topicId}] ${text} (IMPORTANT: Read ${ctxPath} for Telegram relay instructions — you MUST relay your response back.)`;
221
- sessionManager.spawnInteractiveSession(bootstrapMessage, storedName).then((newSessionName) => {
224
+ sessionManager.spawnInteractiveSession(bootstrapMessage, storedName, { telegramTopicId: topicId }).then((newSessionName) => {
222
225
  telegram.registerTopicSession(topicId, newSessionName);
223
- telegram.sendToTopic(topicId, `Session created.`).catch(() => { });
226
+ telegram.sendToTopic(topicId, `Session starting up — reading your message now. One moment.`).catch(() => { });
224
227
  console.log(`[telegram→session] Auto-spawned "${newSessionName}" for topic ${topicId}`);
225
228
  }).catch((err) => {
226
229
  console.error(`[telegram→session] Auto-spawn failed:`, err);
@@ -351,8 +354,32 @@ export async function startServer(options) {
351
354
  const sessionManager = new SessionManager(config.sessions, state);
352
355
  let relationships;
353
356
  if (config.relationships) {
357
+ // Wire LLM intelligence for identity resolution.
358
+ // Priority: Claude CLI (subscription, zero extra cost) > Anthropic API (explicit opt-in only)
359
+ const claudePath = config.sessions.claudePath;
360
+ let intelligenceMode = 'heuristic-only';
361
+ // Check if user explicitly opted into API-based intelligence
362
+ // (intelligenceProvider is a config-file-only field, not in the TypeScript type)
363
+ const explicitProvider = config.relationships.intelligenceProvider;
364
+ if (explicitProvider === 'anthropic-api') {
365
+ // User explicitly chose API — respect their decision
366
+ const apiProvider = AnthropicIntelligenceProvider.fromEnv();
367
+ if (apiProvider) {
368
+ config.relationships.intelligence = apiProvider;
369
+ intelligenceMode = 'LLM-supervised (Anthropic API — user choice)';
370
+ }
371
+ else {
372
+ console.log(pc.yellow(' intelligenceProvider: "anthropic-api" set but ANTHROPIC_API_KEY not found'));
373
+ }
374
+ }
375
+ else if (claudePath) {
376
+ // Default: use Claude CLI via subscription (zero extra cost)
377
+ config.relationships.intelligence = new ClaudeCliIntelligenceProvider(claudePath);
378
+ intelligenceMode = 'LLM-supervised (Claude CLI subscription)';
379
+ }
354
380
  relationships = new RelationshipManager(config.relationships);
355
- console.log(pc.green(` Relationships loaded: ${relationships.getAll().length} tracked`));
381
+ const count = relationships.getAll().length;
382
+ console.log(pc.green(` Relationships loaded: ${count} tracked (${intelligenceMode})`));
356
383
  }
357
384
  let scheduler;
358
385
  if (config.scheduler.enabled) {
@@ -454,7 +481,13 @@ export async function startServer(options) {
454
481
  stateDir: config.stateDir,
455
482
  });
456
483
  }
457
- const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, dispatches, updateChecker, publisher, viewer, tunnel });
484
+ // Set up evolution system (always enabled the feedback loop infrastructure)
485
+ const evolution = new EvolutionManager({
486
+ stateDir: config.stateDir,
487
+ ...(config.evolution || {}),
488
+ });
489
+ console.log(pc.green(' Evolution system enabled'));
490
+ const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, dispatches, updateChecker, publisher, viewer, tunnel, evolution });
458
491
  await server.start();
459
492
  // Start tunnel AFTER server is listening
460
493
  if (tunnel) {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * AnthropicIntelligenceProvider — OPTIONAL IntelligenceProvider using the Anthropic Messages API.
3
+ *
4
+ * ⚠️ This provider uses API tokens (extra cost). For most Instar agents, the
5
+ * ClaudeCliIntelligenceProvider (which uses the Claude subscription) is the
6
+ * correct default. Only use this provider when:
7
+ * - The user explicitly sets intelligenceProvider: "anthropic-api" in config
8
+ * - The Claude CLI is not available
9
+ * - The user has a specific reason to prefer direct API access
10
+ *
11
+ * No SDK dependency — direct fetch calls, following the TelegramAdapter pattern.
12
+ */
13
+ import type { IntelligenceProvider, IntelligenceOptions } from './types.js';
14
+ export declare class AnthropicIntelligenceProvider implements IntelligenceProvider {
15
+ private apiKey;
16
+ constructor(apiKey: string);
17
+ /**
18
+ * Create a provider from environment variables, or null if no key available.
19
+ * Follows the same graceful degradation pattern as TelegramAdapter's voice providers.
20
+ */
21
+ static fromEnv(): AnthropicIntelligenceProvider | null;
22
+ evaluate(prompt: string, options?: IntelligenceOptions): Promise<string>;
23
+ }
24
+ //# sourceMappingURL=AnthropicIntelligenceProvider.d.ts.map