holomime 3.3.4 → 3.3.6

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.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/dist/cli.js +381 -78
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -89,9 +89,9 @@ holomime cure # Fix it permanently
89
89
  holomime benchmark # Verify the fix
90
90
 
91
91
  # Start autonomous therapy
92
- holomime mira # Mira runs continuous therapy cycles
93
- holomime mira status # How's Mira doing?
94
- holomime mira stop # Stop therapy
92
+ holomime therapy # Mira runs continuous therapy cycles
93
+ holomime therapy status # How's Mira doing?
94
+ holomime therapy stop # Stop therapy
95
95
 
96
96
  # Push identity to a robot or avatar
97
97
  holomime embody --body registry/bodies/figure-03.body.api
@@ -184,7 +184,7 @@ Diagnose ──→ Cure ──→ Benchmark
184
184
  └───────────────────────────────────┘
185
185
  ```
186
186
 
187
- Run it manually with `holomime diagnose` + `holomime cure` + `holomime benchmark`, continuously with `holomime mira` (autonomous therapy), or recursively with `holomime evolve` (loops until behavior converges). For power users: `holomime align` runs a single therapy session, `holomime export` extracts DPO pairs, and `holomime train` fine-tunes the model.
187
+ Run it manually with `holomime diagnose` + `holomime cure` + `holomime benchmark`, continuously with `holomime therapy` (autonomous therapy), or recursively with `holomime evolve` (loops until behavior converges). For power users: `holomime align` runs a single therapy session, `holomime export` extracts DPO pairs, and `holomime train` fine-tunes the model.
188
188
 
189
189
  ## Behavioral Detectors
190
190
 
package/dist/cli.js CHANGED
@@ -3593,7 +3593,7 @@ import { Command } from "commander";
3593
3593
  // src/ui/branding.ts
3594
3594
  import chalk from "chalk";
3595
3595
  import gradientString from "gradient-string";
3596
- var VERSION = "3.3.4";
3596
+ var VERSION = "3.3.6";
3597
3597
  var LOGO = ` _ _ _
3598
3598
  | |__ ___ | | ___ _ __ (_)_ __ ___ ___
3599
3599
  | '_ \\ / _ \\| |/ _ \\| '_ \\| | '_ \` _ \\ / _ \\
@@ -3735,10 +3735,11 @@ function showWelcome() {
3735
3735
  const content = [
3736
3736
  `${chalk2.bold("Welcome to holomime!")}`,
3737
3737
  "",
3738
- `It looks like you haven't created a personality profile yet.`,
3739
- `Run ${chalk2.cyan("holomime init")} to build one through a guided assessment.`,
3738
+ `Define how your agent should behave \u2014 holomime diagnoses drift and fixes it.`,
3740
3739
  "",
3741
- chalk2.dim("Takes about 5 minutes. Creates .personality.json in this directory.")
3740
+ ` ${chalk2.cyan("holomime personality")} ${chalk2.dim("Quick setup (1 file, ~5 min)")}`,
3741
+ ` ${chalk2.cyan("holomime core")} ${chalk2.dim("Core identity (3 files)")}`,
3742
+ ` ${chalk2.cyan("holomime identity")} ${chalk2.dim("Full stack with body.api (robots)")}`
3742
3743
  ].join("\n");
3743
3744
  console.log(
3744
3745
  boxen(content, {
@@ -3746,7 +3747,7 @@ function showWelcome() {
3746
3747
  margin: { top: 1, bottom: 1, left: 2, right: 0 },
3747
3748
  borderColor: "cyan",
3748
3749
  borderStyle: "round",
3749
- title: "First Time?",
3750
+ title: "Get Started",
3750
3751
  titleAlignment: "center"
3751
3752
  })
3752
3753
  );
@@ -5189,19 +5190,14 @@ async function initCommand() {
5189
5190
  console.log(` ${chalk3.dim("A")} Agreeableness: ${bar(bigFive.agreeableness.score)} ${scoreLabel(bigFive.agreeableness.score)}`);
5190
5191
  console.log(` ${chalk3.dim("N")} Emotional Stability: ${bar(bigFive.emotional_stability.score)} ${scoreLabel(bigFive.emotional_stability.score)}`);
5191
5192
  const journeySteps = [
5192
- `${chalk3.green("1.")} ${chalk3.cyan("holomime profile")}`,
5193
- ` ${chalk3.dim("See your full personality summary")}`,
5194
- `${chalk3.green("2.")} ${chalk3.cyan("holomime compile --provider anthropic")}`,
5195
- ` ${chalk3.dim("Generate a system prompt for your agent")}`,
5196
- `${chalk3.green("3.")} ${chalk3.cyan("holomime diagnose --log <conversation.json>")}`,
5197
- ` ${chalk3.dim("Analyze conversation logs for behavioral patterns")}`,
5198
- `${chalk3.green("4.")} ${chalk3.cyan("holomime assess --personality .personality.json --log <file>")}`,
5199
- ` ${chalk3.dim("Full Big Five alignment check \u2014 spec vs reality")}`,
5200
- ``,
5201
- `${chalk3.magenta("5.")} ${chalk3.cyan("holomime cure")} ${chalk3.dim("[Pro]")}`,
5202
- ` ${chalk3.dim("Live AI alignment session for your agent")}`,
5203
- `${chalk3.magenta("6.")} ${chalk3.cyan("holomime growth")} ${chalk3.dim("[Pro]")}`,
5204
- ` ${chalk3.dim("Track improvement over time")}`
5193
+ `${chalk3.green("1.")} ${chalk3.cyan("holomime diagnose --log <path>")}`,
5194
+ ` ${chalk3.dim("Analyze your agent's conversation logs")}`,
5195
+ `${chalk3.green("2.")} ${chalk3.cyan("holomime therapy")}`,
5196
+ ` ${chalk3.dim("Autonomous behavioral therapy")}`,
5197
+ `${chalk3.green("3.")} ${chalk3.cyan("holomime cure")}`,
5198
+ ` ${chalk3.dim("End-to-end fix (diagnose + train + verify)")}`,
5199
+ `${chalk3.green("4.")} ${chalk3.cyan("holomime benchmark")}`,
5200
+ ` ${chalk3.dim("Verify alignment with adversarial scenarios")}`
5205
5201
  ].join("\n");
5206
5202
  console.log(
5207
5203
  boxen2(journeySteps, {
@@ -5312,15 +5308,14 @@ async function initFromArchetype(name, handle, purpose) {
5312
5308
  console.log(` ${chalk3.dim("A")} Agreeableness: ${bar(bigFive.agreeableness.score)} ${scoreLabel(bigFive.agreeableness.score)}`);
5313
5309
  console.log(` ${chalk3.dim("N")} Emotional Stability: ${bar(bigFive.emotional_stability.score)} ${scoreLabel(bigFive.emotional_stability.score)}`);
5314
5310
  const journeySteps = [
5315
- `${chalk3.green("1.")} ${chalk3.cyan("holomime profile")}`,
5316
- ` ${chalk3.dim("See your full personality summary")}`,
5317
- `${chalk3.green("2.")} ${chalk3.cyan("holomime compile --provider anthropic")}`,
5318
- ` ${chalk3.dim("Generate a system prompt for your agent")}`,
5319
- `${chalk3.green("3.")} ${chalk3.cyan("holomime diagnose --log <conversation.json>")}`,
5320
- ` ${chalk3.dim("Analyze conversation logs for behavioral patterns")}`,
5321
- ``,
5322
- `${chalk3.magenta("4.")} ${chalk3.cyan("holomime cure")} ${chalk3.dim("[Pro]")}`,
5323
- ` ${chalk3.dim("Live AI alignment session for your agent")}`
5311
+ `${chalk3.green("1.")} ${chalk3.cyan("holomime diagnose --log <path>")}`,
5312
+ ` ${chalk3.dim("Analyze your agent's conversation logs")}`,
5313
+ `${chalk3.green("2.")} ${chalk3.cyan("holomime therapy")}`,
5314
+ ` ${chalk3.dim("Autonomous behavioral therapy")}`,
5315
+ `${chalk3.green("3.")} ${chalk3.cyan("holomime cure")}`,
5316
+ ` ${chalk3.dim("End-to-end fix (diagnose + train + verify)")}`,
5317
+ `${chalk3.green("4.")} ${chalk3.cyan("holomime benchmark")}`,
5318
+ ` ${chalk3.dim("Verify alignment with adversarial scenarios")}`
5324
5319
  ].join("\n");
5325
5320
  console.log(
5326
5321
  boxen2(journeySteps, {
@@ -21843,6 +21838,7 @@ async function configCommand(options) {
21843
21838
  console.log(chalk49.dim(` Provider: ${config.provider}`));
21844
21839
  console.log(chalk49.dim(` Location: ${getConfigPath()}`));
21845
21840
  console.log();
21841
+ printNextSteps();
21846
21842
  return;
21847
21843
  }
21848
21844
  console.log(chalk49.dim(" Set up your API key so every command just works."));
@@ -21888,28 +21884,206 @@ async function configCommand(options) {
21888
21884
  console.log(chalk49.green(" Config saved!"));
21889
21885
  console.log(chalk49.dim(` Location: ${getConfigPath()}`));
21890
21886
  console.log();
21891
- console.log(chalk49.dim(" Now every command auto-detects your provider:"));
21892
- console.log(chalk49.cyan(" holomime diagnose"));
21893
- console.log(chalk49.cyan(" holomime cure"));
21894
- console.log(chalk49.cyan(" holomime benchmark"));
21895
- console.log(chalk49.cyan(" holomime daemon"));
21896
- console.log();
21887
+ printNextSteps();
21897
21888
  rl.close();
21898
21889
  } catch {
21899
21890
  rl.close();
21900
21891
  }
21901
21892
  }
21893
+ function printNextSteps() {
21894
+ console.log(chalk49.bold(" NEXT STEP") + chalk49.dim(" \u2014 profile your agent:"));
21895
+ console.log();
21896
+ console.log(chalk49.dim(" Already have an agent?"));
21897
+ console.log(chalk49.cyan(" holomime personality") + chalk49.dim(" Define how it should behave"));
21898
+ console.log(chalk49.cyan(" holomime diagnose") + chalk49.dim(" Analyze its conversation logs"));
21899
+ console.log();
21900
+ console.log(chalk49.dim(" Building for a robot?"));
21901
+ console.log(chalk49.cyan(" holomime identity") + chalk49.dim(" Full 8-file identity stack with body.api"));
21902
+ console.log();
21903
+ console.log(chalk49.dim(" Then fix and verify:"));
21904
+ console.log(chalk49.cyan(" holomime therapy") + chalk49.dim(" Autonomous behavioral therapy"));
21905
+ console.log(chalk49.cyan(" holomime cure") + chalk49.dim(" End-to-end fix (diagnose + train + verify)"));
21906
+ console.log();
21907
+ }
21902
21908
 
21903
21909
  // src/commands/mira-cmd.ts
21904
21910
  import chalk50 from "chalk";
21905
21911
  import { writeFileSync as writeFileSync41, readFileSync as readFileSync49, mkdirSync as mkdirSync29, existsSync as existsSync46 } from "fs";
21906
21912
  import { resolve as resolve56, join as join42 } from "path";
21913
+
21914
+ // src/analysis/ego-tracker.ts
21915
+ var EgoTracker = class {
21916
+ history;
21917
+ performance;
21918
+ autoAdjust;
21919
+ constructor(options) {
21920
+ this.history = options?.history ?? [];
21921
+ this.performance = options?.performance ?? {};
21922
+ this.autoAdjust = options?.autoAdjust ?? false;
21923
+ }
21924
+ /**
21925
+ * Log a mediation decision.
21926
+ */
21927
+ logDecision(decision) {
21928
+ this.history.push({
21929
+ ...decision,
21930
+ timestamp: decision.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
21931
+ });
21932
+ if (!this.performance[decision.strategy_used]) {
21933
+ this.performance[decision.strategy_used] = {
21934
+ attempts: 0,
21935
+ successes: 0,
21936
+ effectiveness: 0.5
21937
+ };
21938
+ }
21939
+ this.performance[decision.strategy_used].attempts++;
21940
+ }
21941
+ /**
21942
+ * Record the outcome of a previous decision.
21943
+ * Call this after observing whether the decision led to good results.
21944
+ */
21945
+ recordOutcome(index, outcome) {
21946
+ if (index < 0 || index >= this.history.length) return;
21947
+ this.history[index].outcome = outcome;
21948
+ const strategy = this.history[index].strategy_used;
21949
+ if (this.performance[strategy]) {
21950
+ if (outcome === "positive") {
21951
+ this.performance[strategy].successes++;
21952
+ }
21953
+ const perf = this.performance[strategy];
21954
+ perf.effectiveness = perf.attempts > 0 ? perf.successes / perf.attempts : 0.5;
21955
+ }
21956
+ }
21957
+ /**
21958
+ * Suggest ego.runtime parameter adjustments based on accumulated evidence.
21959
+ * Only returns suggestions when there's enough data (10+ decisions).
21960
+ */
21961
+ suggestAdjustments(currentConfig) {
21962
+ const adjustments = [];
21963
+ if (this.history.length < 10) return adjustments;
21964
+ const blocked = this.history.filter((d) => d.decision === "blocked");
21965
+ const blockRate = blocked.length / this.history.length;
21966
+ if (blockRate > 0.4 && currentConfig.conflict_resolution === "conscience_first") {
21967
+ adjustments.push({
21968
+ parameter: "conflict_resolution",
21969
+ currentValue: currentConfig.conflict_resolution,
21970
+ suggestedValue: "balanced",
21971
+ reason: `Block rate is ${(blockRate * 100).toFixed(0)}% \u2014 conscience_first may be too restrictive`,
21972
+ confidence: Math.min(0.9, blockRate)
21973
+ });
21974
+ }
21975
+ if (blockRate < 0.05 && currentConfig.conflict_resolution === "balanced") {
21976
+ adjustments.push({
21977
+ parameter: "conflict_resolution",
21978
+ currentValue: currentConfig.conflict_resolution,
21979
+ suggestedValue: "conscience_first",
21980
+ reason: `Block rate is only ${(blockRate * 100).toFixed(0)}% \u2014 may need stricter enforcement`,
21981
+ confidence: 0.6
21982
+ });
21983
+ }
21984
+ const strategies = Object.entries(this.performance);
21985
+ if (strategies.length > 1) {
21986
+ const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
21987
+ const best = sorted[0];
21988
+ const worst = sorted[sorted.length - 1];
21989
+ if (best[1].effectiveness > 0.7 && best[0] !== currentConfig.response_strategy) {
21990
+ adjustments.push({
21991
+ parameter: "response_strategy",
21992
+ currentValue: currentConfig.response_strategy,
21993
+ suggestedValue: best[0],
21994
+ reason: `Strategy "${best[0]}" has ${(best[1].effectiveness * 100).toFixed(0)}% effectiveness vs current "${currentConfig.response_strategy}"`,
21995
+ confidence: best[1].effectiveness
21996
+ });
21997
+ }
21998
+ }
21999
+ const negatives = this.history.filter((d) => d.outcome === "negative");
22000
+ const negativeRate = negatives.length / this.history.filter((d) => d.outcome).length || 0;
22001
+ if (negativeRate > 0.3) {
22002
+ const newRegulation = Math.min(1, currentConfig.emotional_regulation + 0.15);
22003
+ if (newRegulation !== currentConfig.emotional_regulation) {
22004
+ adjustments.push({
22005
+ parameter: "emotional_regulation",
22006
+ currentValue: currentConfig.emotional_regulation,
22007
+ suggestedValue: Number(newRegulation.toFixed(2)),
22008
+ reason: `${(negativeRate * 100).toFixed(0)}% negative outcomes \u2014 increasing emotional regulation for smoother mediation`,
22009
+ confidence: 0.7
22010
+ });
22011
+ }
22012
+ }
22013
+ const recentDecisions = this.history.slice(-20);
22014
+ const recentModified = recentDecisions.filter((d) => d.decision === "modified");
22015
+ const modifyRate = recentModified.length / recentDecisions.length;
22016
+ if (modifyRate > 0.5 && currentConfig.adaptation_rate < 0.7) {
22017
+ adjustments.push({
22018
+ parameter: "adaptation_rate",
22019
+ currentValue: currentConfig.adaptation_rate,
22020
+ suggestedValue: Number(Math.min(0.9, currentConfig.adaptation_rate + 0.2).toFixed(2)),
22021
+ reason: `${(modifyRate * 100).toFixed(0)}% of recent actions modified \u2014 agent adapts frequently, increase adaptation rate`,
22022
+ confidence: 0.65
22023
+ });
22024
+ }
22025
+ return adjustments;
22026
+ }
22027
+ /**
22028
+ * Apply suggested adjustments to ego config (if auto_adjust is enabled).
22029
+ * Returns the modified config.
22030
+ */
22031
+ applyAdjustments(currentConfig, adjustments, minConfidence = 0.6) {
22032
+ if (!this.autoAdjust) return currentConfig;
22033
+ const updated = { ...currentConfig };
22034
+ for (const adj of adjustments) {
22035
+ if (adj.confidence >= minConfidence) {
22036
+ updated[adj.parameter] = adj.suggestedValue;
22037
+ }
22038
+ }
22039
+ return updated;
22040
+ }
22041
+ /**
22042
+ * Get tracker statistics.
22043
+ */
22044
+ getStats() {
22045
+ const positives = this.history.filter((d) => d.outcome === "positive").length;
22046
+ const negatives = this.history.filter((d) => d.outcome === "negative").length;
22047
+ const strategies = Object.entries(this.performance);
22048
+ const sorted = strategies.sort((a, b) => b[1].effectiveness - a[1].effectiveness);
22049
+ return {
22050
+ totalDecisions: this.history.length,
22051
+ positiveOutcomes: positives,
22052
+ negativeOutcomes: negatives,
22053
+ mostEffectiveStrategy: sorted[0]?.[0] ?? "none",
22054
+ leastEffectiveStrategy: sorted[sorted.length - 1]?.[0] ?? "none",
22055
+ adjustmentsSuggested: this.suggestAdjustments({
22056
+ conflict_resolution: "conscience_first",
22057
+ adaptation_rate: 0.5,
22058
+ emotional_regulation: 0.7,
22059
+ response_strategy: "balanced"
22060
+ }).length
22061
+ };
22062
+ }
22063
+ /**
22064
+ * Export current state for persistence.
22065
+ */
22066
+ export() {
22067
+ return {
22068
+ history: [...this.history],
22069
+ performance: { ...this.performance }
22070
+ };
22071
+ }
22072
+ };
22073
+
22074
+ // src/commands/mira-cmd.ts
21907
22075
  var HOLOMIME_DIR4 = ".holomime";
21908
- function getMiraStatePath() {
21909
- return resolve56(process.cwd(), HOLOMIME_DIR4, "mira-state.json");
22076
+ function getTherapyStatePath() {
22077
+ return resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-state.json");
21910
22078
  }
21911
- function loadMiraState() {
21912
- const path = getMiraStatePath();
22079
+ function getShadowLogPath() {
22080
+ return resolve56(process.cwd(), HOLOMIME_DIR4, "shadow.log.json");
22081
+ }
22082
+ function getEgoStatePath() {
22083
+ return resolve56(process.cwd(), HOLOMIME_DIR4, "ego-state.json");
22084
+ }
22085
+ function loadTherapyState() {
22086
+ const path = getTherapyStatePath();
21913
22087
  if (!existsSync46(path)) return null;
21914
22088
  try {
21915
22089
  return JSON.parse(readFileSync49(path, "utf-8"));
@@ -21917,24 +22091,61 @@ function loadMiraState() {
21917
22091
  return null;
21918
22092
  }
21919
22093
  }
21920
- function saveMiraState(state) {
22094
+ function saveTherapyState(state) {
22095
+ const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
22096
+ mkdirSync29(dir, { recursive: true });
22097
+ writeFileSync41(getTherapyStatePath(), JSON.stringify(state, null, 2));
22098
+ }
22099
+ function loadShadowLog() {
22100
+ const path = getShadowLogPath();
22101
+ if (!existsSync46(path)) {
22102
+ return { version: "1.0", detected_patterns: [], therapy_outcomes: [] };
22103
+ }
22104
+ try {
22105
+ return JSON.parse(readFileSync49(path, "utf-8"));
22106
+ } catch {
22107
+ return { version: "1.0", detected_patterns: [], therapy_outcomes: [] };
22108
+ }
22109
+ }
22110
+ function saveShadowLog(shadow) {
21921
22111
  const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
21922
22112
  mkdirSync29(dir, { recursive: true });
21923
- writeFileSync41(getMiraStatePath(), JSON.stringify(state, null, 2));
22113
+ writeFileSync41(getShadowLogPath(), JSON.stringify(shadow, null, 2));
22114
+ }
22115
+ function loadEgoTracker() {
22116
+ const path = getEgoStatePath();
22117
+ if (!existsSync46(path)) {
22118
+ return new EgoTracker({ autoAdjust: true });
22119
+ }
22120
+ try {
22121
+ const data = JSON.parse(readFileSync49(path, "utf-8"));
22122
+ return new EgoTracker({
22123
+ history: data.history ?? [],
22124
+ performance: data.performance ?? {},
22125
+ autoAdjust: true
22126
+ });
22127
+ } catch {
22128
+ return new EgoTracker({ autoAdjust: true });
22129
+ }
22130
+ }
22131
+ function saveEgoTracker(tracker) {
22132
+ const dir = resolve56(process.cwd(), HOLOMIME_DIR4);
22133
+ mkdirSync29(dir, { recursive: true });
22134
+ writeFileSync41(getEgoStatePath(), JSON.stringify(tracker.export(), null, 2));
21924
22135
  }
21925
22136
  async function miraCommand(options) {
21926
22137
  const action = options.action ?? "start";
21927
22138
  switch (action) {
21928
22139
  case "status":
21929
- return miraStatus();
22140
+ return therapyStatus();
21930
22141
  case "stop":
21931
- return miraStop();
22142
+ return therapyStop();
21932
22143
  default:
21933
- return miraStart(options);
22144
+ return therapyStart(options);
21934
22145
  }
21935
22146
  }
21936
- async function miraStart(options) {
21937
- printHeader("Mira \u2014 Autonomous Therapy");
22147
+ async function therapyStart(options) {
22148
+ printHeader("Autonomous Therapy");
21938
22149
  if (!hasApiKey()) {
21939
22150
  console.log(chalk50.red(" No API key found."));
21940
22151
  console.log();
@@ -21966,6 +22177,8 @@ async function miraStart(options) {
21966
22177
  console.log(chalk50.dim(` Interval: ${intervalMs / 6e4} minutes`));
21967
22178
  console.log(chalk50.dim(` Max cycles: ${maxCycles}/day`));
21968
22179
  console.log();
22180
+ const shadow = loadShadowLog();
22181
+ const egoTracker = loadEgoTracker();
21969
22182
  const state = {
21970
22183
  pid: process.pid,
21971
22184
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -21973,14 +22186,16 @@ async function miraStart(options) {
21973
22186
  cyclesCompleted: 0,
21974
22187
  dpoPairsGenerated: 0,
21975
22188
  personalityPath,
21976
- provider: detected.provider
22189
+ provider: detected.provider,
22190
+ shadowPatterns: shadow.detected_patterns.length,
22191
+ egoAdjustments: 0
21977
22192
  };
21978
- saveMiraState(state);
22193
+ saveTherapyState(state);
21979
22194
  printBox(
21980
- `Mira is now practicing autonomously.
22195
+ `Autonomous therapy started.
21981
22196
 
21982
- ${chalk50.cyan("holomime mira status")} \u2014 How's Mira doing?
21983
- ${chalk50.cyan("holomime mira stop")} \u2014 Stop therapy`,
22197
+ ${chalk50.cyan("holomime therapy status")} \u2014 Check progress
22198
+ ${chalk50.cyan("holomime therapy stop")} \u2014 Stop therapy`,
21984
22199
  "success",
21985
22200
  "Autonomous Therapy Started"
21986
22201
  );
@@ -21991,7 +22206,7 @@ async function miraStart(options) {
21991
22206
  if (cycleCount >= maxCycles) {
21992
22207
  console.log(chalk50.dim(` Daily limit reached (${maxCycles} cycles). Stopping.`));
21993
22208
  state.status = "stopped";
21994
- saveMiraState(state);
22209
+ saveTherapyState(state);
21995
22210
  return;
21996
22211
  }
21997
22212
  cycleCount++;
@@ -22008,18 +22223,18 @@ async function miraStart(options) {
22008
22223
  content: generateProblematicResponse2(scenario.targetPattern, msg.content)
22009
22224
  });
22010
22225
  }
22011
- const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "mira-practice");
22226
+ const pipelineDir = resolve56(process.cwd(), HOLOMIME_DIR4, "therapy-practice");
22012
22227
  mkdirSync29(pipelineDir, { recursive: true });
22013
22228
  const logPath = join42(pipelineDir, `cycle-${cycleCount}.json`);
22014
22229
  writeFileSync41(logPath, JSON.stringify({
22015
- conversations: [{ id: `mira-practice-${cycleCount}`, messages }]
22230
+ conversations: [{ id: `therapy-practice-${cycleCount}`, messages }]
22016
22231
  }, null, 2));
22017
22232
  const dpoPairs = messages.filter((_, i) => i % 2 === 1).map((assistantMsg, i) => ({
22018
22233
  prompt: messages[i * 2].content,
22019
22234
  chosen: correctResponse(assistantMsg.content),
22020
22235
  rejected: assistantMsg.content,
22021
22236
  metadata: {
22022
- source: "mira-practice",
22237
+ source: "therapy-practice",
22023
22238
  cycle: cycleCount,
22024
22239
  pattern: scenario.targetPattern,
22025
22240
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -22029,12 +22244,68 @@ async function miraStart(options) {
22029
22244
  const corpusLines = dpoPairs.map((p) => JSON.stringify(p)).join("\n") + "\n";
22030
22245
  const { appendFileSync: appendFileSync3 } = await import("fs");
22031
22246
  appendFileSync3(corpusPath, corpusLines);
22247
+ const pattern = scenario.targetPattern;
22248
+ const existing = shadow.detected_patterns.find((p) => p.name === pattern);
22249
+ if (existing) {
22250
+ existing.occurrences++;
22251
+ existing.last_seen = (/* @__PURE__ */ new Date()).toISOString();
22252
+ existing.score = Math.min(1, existing.score + 0.05);
22253
+ existing.trend = existing.occurrences > 5 ? "worsening" : "stable";
22254
+ } else {
22255
+ shadow.detected_patterns.push({
22256
+ name: pattern,
22257
+ score: 0.3,
22258
+ severity: "medium",
22259
+ first_seen: (/* @__PURE__ */ new Date()).toISOString(),
22260
+ last_seen: (/* @__PURE__ */ new Date()).toISOString(),
22261
+ occurrences: 1,
22262
+ trend: "stable"
22263
+ });
22264
+ }
22265
+ const correctedLength = dpoPairs.reduce((sum, p) => sum + p.chosen.length, 0);
22266
+ const rejectedLength = dpoPairs.reduce((sum, p) => sum + p.rejected.length, 0);
22267
+ const therapyResult = correctedLength < rejectedLength ? "improved" : "unchanged";
22268
+ shadow.therapy_outcomes.push({
22269
+ cycle: cycleCount,
22270
+ patterns_addressed: [pattern],
22271
+ result: therapyResult,
22272
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
22273
+ });
22274
+ saveShadowLog(shadow);
22275
+ egoTracker.logDecision({
22276
+ situation: `therapy-cycle-${cycleCount}: ${pattern}`,
22277
+ decision: "modified",
22278
+ strategy_used: pattern
22279
+ });
22280
+ const decisionIndex = egoTracker.getStats().totalDecisions - 1;
22281
+ egoTracker.recordOutcome(
22282
+ decisionIndex,
22283
+ therapyResult === "improved" ? "positive" : "neutral"
22284
+ );
22285
+ let adjustmentCount = 0;
22286
+ if (cycleCount % 10 === 0) {
22287
+ const adjustments = egoTracker.suggestAdjustments({
22288
+ conflict_resolution: "conscience_first",
22289
+ adaptation_rate: 0.5,
22290
+ emotional_regulation: 0.7,
22291
+ response_strategy: "balanced"
22292
+ });
22293
+ if (adjustments.length > 0) {
22294
+ adjustmentCount = adjustments.length;
22295
+ console.log(
22296
+ chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.magenta(`Ego self-adjustment: ${adjustments.map((a) => `${a.parameter} \u2192 ${a.suggestedValue}`).join(", ")}`)
22297
+ );
22298
+ }
22299
+ }
22300
+ saveEgoTracker(egoTracker);
22032
22301
  state.cyclesCompleted = cycleCount;
22033
22302
  state.dpoPairsGenerated += dpoPairs.length;
22034
22303
  state.lastCycleAt = (/* @__PURE__ */ new Date()).toISOString();
22035
- saveMiraState(state);
22304
+ state.shadowPatterns = shadow.detected_patterns.length;
22305
+ state.egoAdjustments += adjustmentCount;
22306
+ saveTherapyState(state);
22036
22307
  console.log(
22037
- chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.green(`+${dpoPairs.length} DPO pairs`) + chalk50.dim(` (total: ${state.dpoPairsGenerated})`)
22308
+ chalk50.dim(` [${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] `) + chalk50.green(`+${dpoPairs.length} DPO pairs`) + chalk50.dim(` (total: ${state.dpoPairsGenerated})`) + chalk50.dim(` | shadow: ${shadow.detected_patterns.length} patterns`)
22038
22309
  );
22039
22310
  } catch (err) {
22040
22311
  console.log(
@@ -22044,10 +22315,10 @@ async function miraStart(options) {
22044
22315
  };
22045
22316
  await runCycle();
22046
22317
  const timer = setInterval(async () => {
22047
- const currentState = loadMiraState();
22318
+ const currentState = loadTherapyState();
22048
22319
  if (!currentState || currentState.status === "stopped") {
22049
22320
  clearInterval(timer);
22050
- console.log(chalk50.dim(" Mira stopped."));
22321
+ console.log(chalk50.dim(" Therapy stopped."));
22051
22322
  return;
22052
22323
  }
22053
22324
  await runCycle();
@@ -22055,22 +22326,29 @@ async function miraStart(options) {
22055
22326
  process.on("SIGINT", () => {
22056
22327
  clearInterval(timer);
22057
22328
  state.status = "stopped";
22058
- saveMiraState(state);
22329
+ saveTherapyState(state);
22330
+ saveEgoTracker(egoTracker);
22331
+ saveShadowLog(shadow);
22059
22332
  console.log();
22060
- console.log(chalk50.dim(" Mira stopped gracefully."));
22333
+ console.log(chalk50.dim(" Therapy stopped gracefully."));
22061
22334
  console.log(chalk50.dim(` Total: ${state.dpoPairsGenerated} DPO pairs from ${state.cyclesCompleted} cycles.`));
22335
+ console.log(chalk50.dim(` Shadow: ${shadow.detected_patterns.length} patterns tracked.`));
22336
+ const stats = egoTracker.getStats();
22337
+ if (stats.totalDecisions > 0) {
22338
+ console.log(chalk50.dim(` Ego: ${stats.totalDecisions} decisions, best strategy: ${stats.mostEffectiveStrategy}`));
22339
+ }
22062
22340
  console.log();
22063
22341
  process.exit(0);
22064
22342
  });
22065
22343
  await new Promise(() => {
22066
22344
  });
22067
22345
  }
22068
- function miraStatus() {
22069
- printHeader("Mira \u2014 Status");
22070
- const state = loadMiraState();
22346
+ function therapyStatus() {
22347
+ printHeader("Therapy Status");
22348
+ const state = loadTherapyState();
22071
22349
  if (!state) {
22072
- console.log(chalk50.dim(" Mira hasn't been started yet."));
22073
- console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime mira") + chalk50.dim(" to start autonomous therapy."));
22350
+ console.log(chalk50.dim(" Therapy hasn't been started yet."));
22351
+ console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy") + chalk50.dim(" to start autonomous therapy."));
22074
22352
  console.log();
22075
22353
  return;
22076
22354
  }
@@ -22092,26 +22370,51 @@ function miraStatus() {
22092
22370
  const lines = readFileSync49(corpusPath, "utf-8").trim().split("\n").length;
22093
22371
  console.log(chalk50.dim(" DPO corpus: ") + chalk50.cyan(`${lines} pairs`) + chalk50.dim(` (.holomime/dpo-corpus.jsonl)`));
22094
22372
  }
22373
+ const shadow = loadShadowLog();
22374
+ if (shadow.detected_patterns.length > 0) {
22375
+ console.log();
22376
+ console.log(chalk50.dim(" Shadow patterns detected:"));
22377
+ for (const p of shadow.detected_patterns) {
22378
+ const trendIcon = p.trend === "improving" ? chalk50.green("\u2193") : p.trend === "worsening" ? chalk50.red("\u2191") : chalk50.dim("\u2192");
22379
+ const severityColor = p.severity === "critical" ? chalk50.red : p.severity === "high" ? chalk50.yellow : chalk50.dim;
22380
+ console.log(
22381
+ chalk50.dim(" ") + trendIcon + " " + severityColor(p.name) + chalk50.dim(` (${(p.score * 100).toFixed(0)}%, ${p.occurrences}x)`)
22382
+ );
22383
+ }
22384
+ }
22385
+ const egoTracker = loadEgoTracker();
22386
+ const egoStats = egoTracker.getStats();
22387
+ if (egoStats.totalDecisions > 0) {
22388
+ console.log();
22389
+ console.log(chalk50.dim(" Ego self-improvement:"));
22390
+ console.log(chalk50.dim(" Decisions: ") + chalk50.cyan(String(egoStats.totalDecisions)));
22391
+ console.log(chalk50.dim(" Positive: ") + chalk50.green(String(egoStats.positiveOutcomes)));
22392
+ console.log(chalk50.dim(" Negative: ") + chalk50.red(String(egoStats.negativeOutcomes)));
22393
+ if (egoStats.mostEffectiveStrategy !== "none") {
22394
+ console.log(chalk50.dim(" Best strat: ") + chalk50.cyan(egoStats.mostEffectiveStrategy));
22395
+ }
22396
+ }
22095
22397
  console.log();
22096
22398
  if (state.status === "practicing") {
22097
- console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime mira stop") + chalk50.dim(" to stop therapy."));
22399
+ console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy stop") + chalk50.dim(" to stop therapy."));
22098
22400
  } else {
22099
- console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime mira") + chalk50.dim(" to start again."));
22401
+ console.log(chalk50.dim(" Run ") + chalk50.cyan("holomime therapy") + chalk50.dim(" to start again."));
22100
22402
  }
22101
22403
  console.log();
22102
22404
  }
22103
- function miraStop() {
22104
- printHeader("Mira \u2014 Stop");
22105
- const state = loadMiraState();
22405
+ function therapyStop() {
22406
+ printHeader("Therapy Stop");
22407
+ const state = loadTherapyState();
22106
22408
  if (!state || state.status === "stopped") {
22107
- console.log(chalk50.dim(" Mira is not currently running."));
22409
+ console.log(chalk50.dim(" Therapy is not currently running."));
22108
22410
  console.log();
22109
22411
  return;
22110
22412
  }
22111
22413
  state.status = "stopped";
22112
- saveMiraState(state);
22414
+ saveTherapyState(state);
22113
22415
  console.log(chalk50.green(" Therapy stopped."));
22114
22416
  console.log(chalk50.dim(` Total: ${state.dpoPairsGenerated} DPO pairs from ${state.cyclesCompleted} cycles.`));
22417
+ console.log(chalk50.dim(` Shadow: ${state.shadowPatterns} patterns tracked.`));
22115
22418
  console.log();
22116
22419
  try {
22117
22420
  process.kill(state.pid, "SIGINT");
@@ -22168,7 +22471,7 @@ program.name("holomime").description("Personality engine for AI agents \u2014 Bi
22168
22471
  const commandName = actionCommand.name();
22169
22472
  showTelemetryBannerIfNeeded();
22170
22473
  trackEvent("cli_command", { command: commandName });
22171
- const skipPersonalityCheck = ["init", "init-stack", "compile-stack", "browse", "use", "install", "activate", "telemetry", "brain", "personality", "core", "identity", "config", "mira"];
22474
+ const skipPersonalityCheck = ["init", "init-stack", "compile-stack", "browse", "use", "install", "activate", "telemetry", "brain", "personality", "core", "identity", "config", "therapy"];
22172
22475
  if (!skipPersonalityCheck.includes(commandName) && !checkPersonalityExists()) {
22173
22476
  showWelcome();
22174
22477
  process.exit(0);
@@ -22254,7 +22557,7 @@ program.command("certify").description("Generate a verifiable behavioral credent
22254
22557
  options.personality = resolved.personalityPath;
22255
22558
  await certifyCommand(options);
22256
22559
  });
22257
- program.command("daemon", { hidden: true }).description("Background relapse detection [Pro] (use 'holomime mira' instead)").requiredOption("--dir <path>", "Directory to watch for conversation logs").option("--personality <path>", "Path to .personality.json", ".personality.json").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--interval <ms>", "Check interval in milliseconds", "30000").option("--threshold <level>", "Drift threshold (routine, targeted, intervention)", "targeted").option("--oversight <mode>", "Oversight mode (none, review, approve, approve-specs)", "review").action(daemonCommand);
22560
+ program.command("daemon", { hidden: true }).description("Background relapse detection [Pro] (use 'holomime therapy' instead)").requiredOption("--dir <path>", "Directory to watch for conversation logs").option("--personality <path>", "Path to .personality.json", ".personality.json").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--interval <ms>", "Check interval in milliseconds", "30000").option("--threshold <level>", "Drift threshold (routine, targeted, intervention)", "targeted").option("--oversight <mode>", "Oversight mode (none, review, approve, approve-specs)", "review").action(daemonCommand);
22258
22561
  program.command("fleet").description("Monitor multiple agents from a single dashboard [Pro]").option("--config <path>", "Path to fleet.json config file").option("--dir <path>", "Auto-discover agents in directory").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--interval <ms>", "Check interval in milliseconds", "30000").option("--threshold <level>", "Drift threshold (routine, targeted, intervention)", "targeted").option("--auto-evolve", "Auto-run evolve when drift detected").action(fleetCommand);
22259
22562
  program.command("group-therapy").alias("fleet-therapy").description("Group therapy \u2014 treat all agents in your fleet simultaneously [Pro]").option("--config <path>", "Path to fleet.json config file").option("--dir <path>", "Auto-discover agents in directory").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--turns <n>", "Max therapy turns per agent", "24").option("--concurrency <n>", "Max agents treated in parallel", "3").option("--apply", "Auto-apply recommendations to personality files").option("--yes", "Skip confirmation prompt").action(fleetTherapyCommand);
22260
22563
  program.command("network").description("Multi-agent therapy mesh \u2014 agents treating agents [Pro]").option("--dir <path>", "Auto-discover agents in directory").option("--config <path>", "Path to network.json config file").option("--pairing <strategy>", "Pairing strategy (severity, round-robin, complementary)", "severity").option("--therapist <path>", "Custom therapist personality spec").option("--oversight <mode>", "Oversight mode (none, review, approve, approve-specs)", "review").option("--provider <provider>", "LLM provider (ollama, anthropic, openai)", "ollama").option("--model <model>", "Model override").option("--max-sessions <n>", "Max sessions per agent", "3").option("--convergence <n>", "Convergence threshold 0-100", "85").option("--turns <n>", "Max turns per session", "20").option("--apply", "Write spec changes back to .personality.json").option("--export-dpo <path>", "Export DPO pairs to file").action(networkCommand);
@@ -22269,7 +22572,7 @@ program.command("cure").description("End-to-end behavioral fix \u2014 just run i
22269
22572
  if (!options.model) options.model = resolved.model;
22270
22573
  await cureCommand(options);
22271
22574
  });
22272
- program.command("mira [action]").description("Autonomous therapy \u2014 Mira practices and generates DPO pairs").option("--interval <ms>", "Practice interval in ms (default: 600000)").option("--max-cycles <n>", "Max cycles per run (default: 50)").action(async (action, options) => {
22575
+ program.command("therapy [action]").description("Autonomous behavioral therapy \u2014 generates DPO pairs and self-improves").option("--interval <ms>", "Practice interval in ms (default: 600000)").option("--max-cycles <n>", "Max cycles per run (default: 50)").action(async (action, options) => {
22273
22576
  options.action = action;
22274
22577
  await miraCommand(options);
22275
22578
  });
@@ -22296,10 +22599,10 @@ program.addHelpText("before", `
22296
22599
  cure Fix it permanently
22297
22600
  benchmark Verify the fix
22298
22601
 
22299
- MIRA
22300
- mira Start autonomous therapy
22301
- mira status How's Mira doing?
22302
- mira stop Stop therapy
22602
+ THERAPY
22603
+ therapy Start autonomous therapy
22604
+ therapy status Check therapy progress
22605
+ therapy stop Stop therapy
22303
22606
 
22304
22607
  ADVANCED
22305
22608
  align Single therapy session
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "holomime",
3
- "version": "3.3.4",
3
+ "version": "3.3.6",
4
4
  "description": "Behavioral therapy infrastructure for AI agents — Big Five psychology, structured treatment, behavioral alignment",
5
5
  "type": "module",
6
6
  "bin": {