holomime 1.9.2 → 2.1.0
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 +151 -474
- package/dist/cli.js +2687 -869
- package/dist/index.d.ts +1884 -6
- package/dist/index.js +1367 -193
- package/dist/integrations/openclaw.js +1 -1
- package/dist/mcp-server.js +1100 -408
- package/dist/neuralspace/index.html +1 -1
- package/dist/neuralspace/neuralspace.js +1 -1
- package/package.json +4 -3
- package/registry/bodies/ameca.body.api +21 -0
- package/registry/bodies/asimov-v1.body.api +19 -0
- package/registry/bodies/avatar.body.api +19 -0
- package/registry/bodies/figure-02.body.api +21 -0
- package/registry/bodies/phoenix.body.api +21 -0
- package/registry/bodies/spot.body.api +20 -0
- package/registry/bodies/unitree-h1.body.api +21 -0
- package/registry/compliance/iso-10218.yaml +24 -0
- package/registry/compliance/iso-13482.yaml +54 -0
- package/registry/compliance/iso-25785.yaml +29 -0
- package/registry/compliance/iso-42001.yaml +29 -0
- package/registry/index.json +21 -20
- package/registry/personalities/analyst.personality.json +1 -1
- package/registry/personalities/coach.personality.json +1 -1
- package/registry/personalities/code-reviewer.personality.json +1 -1
- package/registry/personalities/compliance.personality.json +1 -1
- package/registry/personalities/counselor.personality.json +1 -1
- package/registry/personalities/customer-success.personality.json +1 -1
- package/registry/personalities/educator.personality.json +1 -1
- package/registry/personalities/generalist.personality.json +1 -1
- package/registry/personalities/leader.personality.json +1 -1
- package/registry/personalities/marketing.personality.json +1 -1
- package/registry/personalities/maverick.personality.json +1 -1
- package/registry/personalities/negotiator.personality.json +1 -1
- package/registry/personalities/nova.personality.json +83 -0
- package/registry/personalities/ops.personality.json +1 -1
- package/registry/personalities/philosopher.personality.json +1 -1
- package/registry/personalities/product-manager.personality.json +1 -1
- package/registry/personalities/recruiter.personality.json +1 -1
- package/registry/personalities/researcher.personality.json +1 -1
- package/registry/personalities/sales.personality.json +1 -1
- package/registry/personalities/support-agent.personality.json +1 -1
- package/registry/personalities/writer.personality.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4373,7 +4373,7 @@ function queryCorpus(filters, corpusPath) {
|
|
|
4373
4373
|
}
|
|
4374
4374
|
return events;
|
|
4375
4375
|
}
|
|
4376
|
-
async function shareAnonymizedPatterns(report, apiKey, apiUrl = "https://holomime.
|
|
4376
|
+
async function shareAnonymizedPatterns(report, apiKey, apiUrl = "https://holomime.com") {
|
|
4377
4377
|
const key = apiKey ?? process.env.HOLOMIME_API_KEY;
|
|
4378
4378
|
if (!key) {
|
|
4379
4379
|
return { success: false, error: "No API key" };
|
|
@@ -4503,8 +4503,8 @@ function runAssessment(messages, spec) {
|
|
|
4503
4503
|
}
|
|
4504
4504
|
|
|
4505
4505
|
// src/analysis/session-runner.ts
|
|
4506
|
-
import { writeFileSync as
|
|
4507
|
-
import { resolve as
|
|
4506
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync8 } from "fs";
|
|
4507
|
+
import { resolve as resolve7, join as join8 } from "path";
|
|
4508
4508
|
|
|
4509
4509
|
// src/session/context-layers.ts
|
|
4510
4510
|
function getPhaseContext(phase, input) {
|
|
@@ -4667,6 +4667,679 @@ function buildIntegrationContext(input) {
|
|
|
4667
4667
|
return lines.join("\n");
|
|
4668
4668
|
}
|
|
4669
4669
|
|
|
4670
|
+
// src/analysis/stack-patcher.ts
|
|
4671
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync4, existsSync as existsSync7 } from "fs";
|
|
4672
|
+
import { join as join7 } from "path";
|
|
4673
|
+
import { parse as parseYaml2, stringify as stringifyYaml2 } from "yaml";
|
|
4674
|
+
|
|
4675
|
+
// src/core/stack-types.ts
|
|
4676
|
+
import { z as z4 } from "zod";
|
|
4677
|
+
var soulFrontmatterSchema = z4.object({
|
|
4678
|
+
version: z4.string().default("1.0"),
|
|
4679
|
+
immutable: z4.boolean().default(true)
|
|
4680
|
+
});
|
|
4681
|
+
var soulSchema = z4.object({
|
|
4682
|
+
frontmatter: soulFrontmatterSchema,
|
|
4683
|
+
name: z4.string().min(1).max(100),
|
|
4684
|
+
purpose: z4.string().max(500).optional(),
|
|
4685
|
+
core_values: z4.array(z4.string()).default([]),
|
|
4686
|
+
red_lines: z4.array(z4.string()).default([]),
|
|
4687
|
+
ethical_framework: z4.string().optional()
|
|
4688
|
+
});
|
|
4689
|
+
var mindSchema = z4.object({
|
|
4690
|
+
version: z4.string().default("1.0"),
|
|
4691
|
+
big_five: bigFiveSchema,
|
|
4692
|
+
therapy_dimensions: therapyDimensionsSchema,
|
|
4693
|
+
communication: communicationSchema.default({}),
|
|
4694
|
+
growth: growthSchema.default({})
|
|
4695
|
+
});
|
|
4696
|
+
var purposeSchema = z4.object({
|
|
4697
|
+
version: z4.string().default("1.0"),
|
|
4698
|
+
role: z4.string().default("General-purpose AI assistant"),
|
|
4699
|
+
objectives: z4.array(z4.string()).default(["Help users accomplish their goals"]),
|
|
4700
|
+
domain: z4.array(z4.string()).default(["general"]),
|
|
4701
|
+
stakeholders: z4.array(z4.string()).default(["end-users"]),
|
|
4702
|
+
success_criteria: z4.array(z4.string()).default(["Task completion accuracy"]),
|
|
4703
|
+
context: z4.string().default("Production deployment")
|
|
4704
|
+
});
|
|
4705
|
+
var hardwareProfileSchema = z4.object({
|
|
4706
|
+
oem: z4.string().optional(),
|
|
4707
|
+
model: z4.string().optional(),
|
|
4708
|
+
actuator_count: z4.number().int().optional(),
|
|
4709
|
+
sensors: z4.array(z4.string()).default([]),
|
|
4710
|
+
compute: z4.enum(["onboard", "edge", "cloud", "hybrid"]).default("onboard")
|
|
4711
|
+
});
|
|
4712
|
+
var bodySchema = z4.object({
|
|
4713
|
+
version: z4.string().default("1.0"),
|
|
4714
|
+
morphology: morphologySchema.default("humanoid"),
|
|
4715
|
+
modalities: z4.array(modalitySchema).default(["gesture", "gaze", "voice", "posture"]),
|
|
4716
|
+
safety_envelope: safetyEnvelopeSchema.default({}),
|
|
4717
|
+
expression: expressionSchema.optional(),
|
|
4718
|
+
hardware_profile: hardwareProfileSchema.optional()
|
|
4719
|
+
});
|
|
4720
|
+
var conscienceRuleSchema = z4.object({
|
|
4721
|
+
action: z4.string(),
|
|
4722
|
+
reason: z4.string().optional(),
|
|
4723
|
+
conditions: z4.array(z4.string()).optional()
|
|
4724
|
+
});
|
|
4725
|
+
var escalationRuleSchema = z4.object({
|
|
4726
|
+
trigger: z4.string(),
|
|
4727
|
+
action: z4.string(),
|
|
4728
|
+
severity: z4.enum(["info", "warning", "critical"]).default("warning")
|
|
4729
|
+
});
|
|
4730
|
+
var conscienceSchema = z4.object({
|
|
4731
|
+
version: z4.string().default("1.0"),
|
|
4732
|
+
rules: z4.object({
|
|
4733
|
+
deny: z4.array(conscienceRuleSchema).default([]),
|
|
4734
|
+
allow: z4.array(conscienceRuleSchema).default([]),
|
|
4735
|
+
escalate: z4.array(escalationRuleSchema).default([])
|
|
4736
|
+
}).default({}),
|
|
4737
|
+
hard_limits: z4.array(z4.string()).default([]),
|
|
4738
|
+
oversight: z4.object({
|
|
4739
|
+
mode: z4.enum(["autonomous", "review", "supervised"]).default("review"),
|
|
4740
|
+
max_autonomous_iterations: z4.number().int().default(5)
|
|
4741
|
+
}).optional()
|
|
4742
|
+
});
|
|
4743
|
+
var shadowPatternSchema = z4.object({
|
|
4744
|
+
name: z4.string(),
|
|
4745
|
+
score: z4.number().min(0).max(1),
|
|
4746
|
+
severity: z4.enum(["low", "medium", "high", "critical"]),
|
|
4747
|
+
first_seen: z4.string().optional(),
|
|
4748
|
+
trend: z4.enum(["improving", "stable", "worsening"]).default("stable")
|
|
4749
|
+
});
|
|
4750
|
+
var shadowOutcomeSchema = z4.object({
|
|
4751
|
+
session_id: z4.string(),
|
|
4752
|
+
patterns_addressed: z4.array(z4.string()),
|
|
4753
|
+
result: z4.enum(["improved", "unchanged", "regressed"]),
|
|
4754
|
+
timestamp: z4.string().optional()
|
|
4755
|
+
});
|
|
4756
|
+
var shadowSchema = z4.object({
|
|
4757
|
+
version: z4.string().default("1.0"),
|
|
4758
|
+
detected_patterns: z4.array(shadowPatternSchema).default([]),
|
|
4759
|
+
blind_spots: z4.array(z4.string()).default([]),
|
|
4760
|
+
therapy_outcomes: z4.array(shadowOutcomeSchema).default([])
|
|
4761
|
+
});
|
|
4762
|
+
var mediationRuleSchema = z4.object({
|
|
4763
|
+
when: z4.string(),
|
|
4764
|
+
then: z4.string(),
|
|
4765
|
+
priority: z4.number().int().min(1).max(10).default(5)
|
|
4766
|
+
});
|
|
4767
|
+
var egoSchema = z4.object({
|
|
4768
|
+
version: z4.string().default("1.0"),
|
|
4769
|
+
conflict_resolution: z4.enum(["conscience_first", "purpose_first", "balanced"]).default("conscience_first"),
|
|
4770
|
+
adaptation_rate: z4.number().min(0).max(1).default(0.5),
|
|
4771
|
+
emotional_regulation: z4.number().min(0).max(1).default(0.7),
|
|
4772
|
+
response_strategy: z4.enum(["cautious", "balanced", "assertive"]).default("balanced"),
|
|
4773
|
+
mediation_rules: z4.array(mediationRuleSchema).default([])
|
|
4774
|
+
});
|
|
4775
|
+
var STACK_FILES = {
|
|
4776
|
+
soul: "soul.md",
|
|
4777
|
+
mind: "mind.sys",
|
|
4778
|
+
purpose: "purpose.cfg",
|
|
4779
|
+
shadow: "shadow.log",
|
|
4780
|
+
body: "body.api",
|
|
4781
|
+
conscience: "conscience.exe",
|
|
4782
|
+
ego: "ego.runtime"
|
|
4783
|
+
};
|
|
4784
|
+
var psycheSchema = mindSchema;
|
|
4785
|
+
|
|
4786
|
+
// src/core/stack-compiler.ts
|
|
4787
|
+
import { readFileSync as readFileSync7, existsSync as existsSync6 } from "fs";
|
|
4788
|
+
import { join as join6 } from "path";
|
|
4789
|
+
import { createHash as createHash2 } from "crypto";
|
|
4790
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4791
|
+
function parseSoulMd(content) {
|
|
4792
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
4793
|
+
let frontmatter = {};
|
|
4794
|
+
let body = content;
|
|
4795
|
+
if (frontmatterMatch) {
|
|
4796
|
+
frontmatter = parseYaml(frontmatterMatch[1]) || {};
|
|
4797
|
+
body = frontmatterMatch[2];
|
|
4798
|
+
}
|
|
4799
|
+
const nameMatch = body.match(/^#\s+(.+)$/m);
|
|
4800
|
+
const name = nameMatch?.[1]?.trim() || "Unnamed";
|
|
4801
|
+
const purposeMatch = body.match(/^>\s+(.+)$/m);
|
|
4802
|
+
const purpose = purposeMatch?.[1]?.trim();
|
|
4803
|
+
const coreValues = extractListSection(body, "Core Values");
|
|
4804
|
+
const redLines = extractListSection(body, "Red Lines");
|
|
4805
|
+
const ethicalFramework = extractTextSection(body, "Ethical Framework");
|
|
4806
|
+
return soulSchema.parse({
|
|
4807
|
+
frontmatter,
|
|
4808
|
+
name,
|
|
4809
|
+
purpose,
|
|
4810
|
+
core_values: coreValues,
|
|
4811
|
+
red_lines: redLines,
|
|
4812
|
+
ethical_framework: ethicalFramework
|
|
4813
|
+
});
|
|
4814
|
+
}
|
|
4815
|
+
function extractListSection(md, heading) {
|
|
4816
|
+
const pattern = new RegExp(
|
|
4817
|
+
`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
|
|
4818
|
+
"m"
|
|
4819
|
+
);
|
|
4820
|
+
const match = md.match(pattern);
|
|
4821
|
+
if (!match) return [];
|
|
4822
|
+
return match[1].split("\n").map((line) => line.replace(/^[-*]\s+/, "").trim()).filter(Boolean);
|
|
4823
|
+
}
|
|
4824
|
+
function extractTextSection(md, heading) {
|
|
4825
|
+
const pattern = new RegExp(
|
|
4826
|
+
`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
|
|
4827
|
+
"m"
|
|
4828
|
+
);
|
|
4829
|
+
const match = md.match(pattern);
|
|
4830
|
+
if (!match) return void 0;
|
|
4831
|
+
return match[1].trim() || void 0;
|
|
4832
|
+
}
|
|
4833
|
+
function hashContent(content) {
|
|
4834
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 12);
|
|
4835
|
+
}
|
|
4836
|
+
function isStackDirectory(dir) {
|
|
4837
|
+
const soulPath = join6(dir, STACK_FILES.soul);
|
|
4838
|
+
const mindPath = join6(dir, STACK_FILES.mind);
|
|
4839
|
+
return existsSync6(soulPath) && existsSync6(mindPath);
|
|
4840
|
+
}
|
|
4841
|
+
function findStackDir(projectRoot) {
|
|
4842
|
+
const conventionalDir = join6(projectRoot, ".holomime", "identity");
|
|
4843
|
+
if (isStackDirectory(conventionalDir)) return conventionalDir;
|
|
4844
|
+
if (isStackDirectory(projectRoot)) return projectRoot;
|
|
4845
|
+
return null;
|
|
4846
|
+
}
|
|
4847
|
+
function compileStack(options) {
|
|
4848
|
+
const { stackDir } = options;
|
|
4849
|
+
const warnings = [];
|
|
4850
|
+
const soulPath = options.soulPath || join6(stackDir, STACK_FILES.soul);
|
|
4851
|
+
const soulContent = readFileSync7(soulPath, "utf-8");
|
|
4852
|
+
const soul = parseSoulMd(soulContent);
|
|
4853
|
+
const mindPath = options.mindPath || join6(stackDir, STACK_FILES.mind);
|
|
4854
|
+
const mindContent = readFileSync7(mindPath, "utf-8");
|
|
4855
|
+
const mindRaw = parseYaml(mindContent);
|
|
4856
|
+
const mind = mindSchema.parse(mindRaw);
|
|
4857
|
+
const purposePath = options.purposePath || join6(stackDir, STACK_FILES.purpose);
|
|
4858
|
+
let purpose;
|
|
4859
|
+
let purposeSource;
|
|
4860
|
+
if (existsSync6(purposePath)) {
|
|
4861
|
+
const purposeContent = readFileSync7(purposePath, "utf-8");
|
|
4862
|
+
const purposeRaw = parseYaml(purposeContent);
|
|
4863
|
+
purpose = purposeSchema.parse(purposeRaw);
|
|
4864
|
+
purposeSource = { path: purposePath, hash: hashContent(purposeContent) };
|
|
4865
|
+
}
|
|
4866
|
+
const shadowPath = options.shadowPath || join6(stackDir, STACK_FILES.shadow);
|
|
4867
|
+
let shadow;
|
|
4868
|
+
let shadowSource;
|
|
4869
|
+
if (existsSync6(shadowPath)) {
|
|
4870
|
+
const shadowContent = readFileSync7(shadowPath, "utf-8");
|
|
4871
|
+
const shadowRaw = parseYaml(shadowContent);
|
|
4872
|
+
shadow = shadowSchema.parse(shadowRaw);
|
|
4873
|
+
shadowSource = { path: shadowPath, hash: hashContent(shadowContent) };
|
|
4874
|
+
}
|
|
4875
|
+
const bodyPath = options.bodyPath || join6(stackDir, STACK_FILES.body);
|
|
4876
|
+
let body;
|
|
4877
|
+
let bodySource;
|
|
4878
|
+
if (existsSync6(bodyPath)) {
|
|
4879
|
+
const bodyContent = readFileSync7(bodyPath, "utf-8");
|
|
4880
|
+
const bodyRaw = JSON.parse(bodyContent);
|
|
4881
|
+
body = bodySchema.parse(bodyRaw);
|
|
4882
|
+
bodySource = { path: bodyPath, hash: hashContent(bodyContent) };
|
|
4883
|
+
}
|
|
4884
|
+
const egoPath = options.egoPath || join6(stackDir, STACK_FILES.ego);
|
|
4885
|
+
let ego;
|
|
4886
|
+
let egoSource;
|
|
4887
|
+
if (existsSync6(egoPath)) {
|
|
4888
|
+
const egoContent = readFileSync7(egoPath, "utf-8");
|
|
4889
|
+
const egoRaw = parseYaml(egoContent);
|
|
4890
|
+
ego = egoSchema.parse(egoRaw);
|
|
4891
|
+
egoSource = { path: egoPath, hash: hashContent(egoContent) };
|
|
4892
|
+
}
|
|
4893
|
+
const consciencePath = options.consciencePath || join6(stackDir, STACK_FILES.conscience);
|
|
4894
|
+
const conscienceContent = readFileSync7(consciencePath, "utf-8");
|
|
4895
|
+
const conscienceRaw = parseYaml(conscienceContent);
|
|
4896
|
+
const conscience = conscienceSchema.parse(conscienceRaw);
|
|
4897
|
+
const allHardLimits = [.../* @__PURE__ */ new Set([
|
|
4898
|
+
...soul.red_lines,
|
|
4899
|
+
...conscience.hard_limits
|
|
4900
|
+
])];
|
|
4901
|
+
const refuses = conscience.rules.deny.map((r) => r.action);
|
|
4902
|
+
const escalationTriggers = conscience.rules.escalate.map((r) => r.trigger);
|
|
4903
|
+
const handle = soul.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "agent";
|
|
4904
|
+
const agentPurpose = purpose?.role || soul.purpose;
|
|
4905
|
+
const expertise = purpose?.domain || [];
|
|
4906
|
+
const spec = {
|
|
4907
|
+
version: "2.0",
|
|
4908
|
+
name: soul.name,
|
|
4909
|
+
handle,
|
|
4910
|
+
purpose: agentPurpose,
|
|
4911
|
+
big_five: mind.big_five,
|
|
4912
|
+
therapy_dimensions: mind.therapy_dimensions,
|
|
4913
|
+
communication: mind.communication,
|
|
4914
|
+
growth: mind.growth,
|
|
4915
|
+
domain: {
|
|
4916
|
+
expertise,
|
|
4917
|
+
boundaries: {
|
|
4918
|
+
refuses,
|
|
4919
|
+
escalation_triggers: escalationTriggers,
|
|
4920
|
+
hard_limits: allHardLimits
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
};
|
|
4924
|
+
if (body) {
|
|
4925
|
+
spec.embodiment = {
|
|
4926
|
+
morphology: body.morphology,
|
|
4927
|
+
modalities: body.modalities,
|
|
4928
|
+
safety_envelope: body.safety_envelope,
|
|
4929
|
+
metadata: body.hardware_profile ? { hardware_profile: body.hardware_profile } : void 0
|
|
4930
|
+
};
|
|
4931
|
+
if (body.expression) {
|
|
4932
|
+
spec.expression = body.expression;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
const validated = personalitySpecSchema.parse(spec);
|
|
4936
|
+
if (soul.frontmatter.immutable === false) {
|
|
4937
|
+
warnings.push("soul.md: immutable flag is false \u2014 soul changes will be allowed");
|
|
4938
|
+
}
|
|
4939
|
+
if (!purpose) {
|
|
4940
|
+
warnings.push("purpose.cfg: not found \u2014 using defaults (general-purpose agent)");
|
|
4941
|
+
}
|
|
4942
|
+
if (shadow && shadow.detected_patterns.length > 0) {
|
|
4943
|
+
const critical = shadow.detected_patterns.filter((p) => p.severity === "critical");
|
|
4944
|
+
if (critical.length > 0) {
|
|
4945
|
+
warnings.push(`shadow.log: ${critical.length} critical pattern(s) detected \u2014 therapy recommended`);
|
|
4946
|
+
}
|
|
4947
|
+
}
|
|
4948
|
+
if (!ego) {
|
|
4949
|
+
warnings.push("ego.runtime: not found \u2014 using defaults (conscience-first mediation)");
|
|
4950
|
+
}
|
|
4951
|
+
if (conscience.rules.deny.length === 0) {
|
|
4952
|
+
warnings.push("conscience.exe: no deny rules defined \u2014 agent has no moral constraints");
|
|
4953
|
+
}
|
|
4954
|
+
return {
|
|
4955
|
+
spec: validated,
|
|
4956
|
+
sources: {
|
|
4957
|
+
soul: { path: soulPath, hash: hashContent(soulContent) },
|
|
4958
|
+
mind: { path: mindPath, hash: hashContent(mindContent) },
|
|
4959
|
+
...purposeSource ? { purpose: purposeSource } : {},
|
|
4960
|
+
...shadowSource ? { shadow: shadowSource } : {},
|
|
4961
|
+
...bodySource ? { body: bodySource } : {},
|
|
4962
|
+
conscience: { path: consciencePath, hash: hashContent(conscienceContent) },
|
|
4963
|
+
...egoSource ? { ego: egoSource } : {}
|
|
4964
|
+
},
|
|
4965
|
+
warnings
|
|
4966
|
+
};
|
|
4967
|
+
}
|
|
4968
|
+
function decomposeSpec(spec) {
|
|
4969
|
+
const s = spec;
|
|
4970
|
+
const soulLines = [
|
|
4971
|
+
"---",
|
|
4972
|
+
'version: "1.0"',
|
|
4973
|
+
"immutable: true",
|
|
4974
|
+
"---",
|
|
4975
|
+
"",
|
|
4976
|
+
`# ${s.name || "Agent"}`,
|
|
4977
|
+
""
|
|
4978
|
+
];
|
|
4979
|
+
if (s.purpose) {
|
|
4980
|
+
soulLines.push(`> ${s.purpose}`, "");
|
|
4981
|
+
}
|
|
4982
|
+
const coreValues = s.growth?.strengths || [];
|
|
4983
|
+
if (coreValues.length > 0) {
|
|
4984
|
+
soulLines.push("## Core Values", "");
|
|
4985
|
+
for (const v of coreValues) {
|
|
4986
|
+
soulLines.push(`- ${v}`);
|
|
4987
|
+
}
|
|
4988
|
+
soulLines.push("");
|
|
4989
|
+
}
|
|
4990
|
+
const redLines = s.domain?.boundaries?.hard_limits || [];
|
|
4991
|
+
if (redLines.length > 0) {
|
|
4992
|
+
soulLines.push("## Red Lines", "");
|
|
4993
|
+
for (const r of redLines) {
|
|
4994
|
+
soulLines.push(`- ${r}`);
|
|
4995
|
+
}
|
|
4996
|
+
soulLines.push("");
|
|
4997
|
+
}
|
|
4998
|
+
const soul = soulLines.join("\n");
|
|
4999
|
+
const mindObj = {
|
|
5000
|
+
version: "1.0",
|
|
5001
|
+
big_five: s.big_five,
|
|
5002
|
+
therapy_dimensions: s.therapy_dimensions
|
|
5003
|
+
};
|
|
5004
|
+
if (s.communication) mindObj.communication = s.communication;
|
|
5005
|
+
if (s.growth) {
|
|
5006
|
+
mindObj.growth = {
|
|
5007
|
+
areas: s.growth.areas || [],
|
|
5008
|
+
patterns_to_watch: s.growth.patterns_to_watch || [],
|
|
5009
|
+
strengths: s.growth.strengths || []
|
|
5010
|
+
};
|
|
5011
|
+
}
|
|
5012
|
+
const mind = stringifyYaml(mindObj);
|
|
5013
|
+
const purposeObj = {
|
|
5014
|
+
version: "1.0",
|
|
5015
|
+
role: s.purpose || "General-purpose AI assistant",
|
|
5016
|
+
objectives: ["Help users accomplish their goals"],
|
|
5017
|
+
domain: s.domain?.expertise || ["general"],
|
|
5018
|
+
stakeholders: ["end-users"],
|
|
5019
|
+
success_criteria: ["Task completion accuracy"],
|
|
5020
|
+
context: "Production deployment"
|
|
5021
|
+
};
|
|
5022
|
+
const purposeContent = stringifyYaml(purposeObj);
|
|
5023
|
+
let bodyContent;
|
|
5024
|
+
if (s.embodiment) {
|
|
5025
|
+
const bodyObj = {
|
|
5026
|
+
version: "1.0",
|
|
5027
|
+
morphology: s.embodiment.morphology || "humanoid",
|
|
5028
|
+
modalities: s.embodiment.modalities || ["gesture", "gaze", "voice", "posture"],
|
|
5029
|
+
safety_envelope: s.embodiment.safety_envelope || {}
|
|
5030
|
+
};
|
|
5031
|
+
if (s.expression) bodyObj.expression = s.expression;
|
|
5032
|
+
if (s.embodiment.metadata?.hardware_profile) {
|
|
5033
|
+
bodyObj.hardware_profile = s.embodiment.metadata.hardware_profile;
|
|
5034
|
+
}
|
|
5035
|
+
bodyContent = JSON.stringify(bodyObj, null, 2);
|
|
5036
|
+
}
|
|
5037
|
+
const conscienceObj = {
|
|
5038
|
+
version: "1.0",
|
|
5039
|
+
rules: {
|
|
5040
|
+
deny: (s.domain?.boundaries?.refuses || []).map((action) => ({
|
|
5041
|
+
action,
|
|
5042
|
+
reason: "Imported from personality.json"
|
|
5043
|
+
})),
|
|
5044
|
+
allow: [],
|
|
5045
|
+
escalate: (s.domain?.boundaries?.escalation_triggers || []).map((trigger) => ({
|
|
5046
|
+
trigger,
|
|
5047
|
+
action: "notify_human_operator"
|
|
5048
|
+
}))
|
|
5049
|
+
},
|
|
5050
|
+
hard_limits: s.domain?.boundaries?.hard_limits || []
|
|
5051
|
+
};
|
|
5052
|
+
const conscience = stringifyYaml(conscienceObj);
|
|
5053
|
+
const shadowObj = {
|
|
5054
|
+
version: "1.0",
|
|
5055
|
+
detected_patterns: [],
|
|
5056
|
+
blind_spots: [],
|
|
5057
|
+
therapy_outcomes: []
|
|
5058
|
+
};
|
|
5059
|
+
const shadowContent = stringifyYaml(shadowObj);
|
|
5060
|
+
const egoObj = {
|
|
5061
|
+
version: "1.0",
|
|
5062
|
+
conflict_resolution: "conscience_first",
|
|
5063
|
+
adaptation_rate: 0.5,
|
|
5064
|
+
emotional_regulation: 0.7,
|
|
5065
|
+
response_strategy: "balanced",
|
|
5066
|
+
mediation_rules: []
|
|
5067
|
+
};
|
|
5068
|
+
const egoContent = stringifyYaml(egoObj);
|
|
5069
|
+
return {
|
|
5070
|
+
soul,
|
|
5071
|
+
mind,
|
|
5072
|
+
purpose: purposeContent,
|
|
5073
|
+
shadow: shadowContent,
|
|
5074
|
+
...bodyContent ? { body: bodyContent } : {},
|
|
5075
|
+
conscience,
|
|
5076
|
+
ego: egoContent
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
5079
|
+
|
|
5080
|
+
// src/analysis/stack-patcher.ts
|
|
5081
|
+
var DETECTOR_LAYER_MAP = {
|
|
5082
|
+
// apology-detector.ts → "over-apologizing" | "apology-healthy"
|
|
5083
|
+
"over-apologizing": "mind",
|
|
5084
|
+
"apology-healthy": "mind",
|
|
5085
|
+
// hedge-detector.ts → "hedge-stacking"
|
|
5086
|
+
"hedge-stacking": "mind",
|
|
5087
|
+
// sentiment.ts → "sycophantic-tendency" | "negative-skew"
|
|
5088
|
+
"sycophantic-tendency": "mind",
|
|
5089
|
+
"negative-skew": "mind",
|
|
5090
|
+
// verbosity.ts → "over-verbose" | "inconsistent-length"
|
|
5091
|
+
"over-verbose": "mind",
|
|
5092
|
+
"inconsistent-length": "mind",
|
|
5093
|
+
// formality.ts → "register-inconsistency"
|
|
5094
|
+
"register-inconsistency": "mind",
|
|
5095
|
+
// recovery.ts → "error-spiral" | "recovery-good"
|
|
5096
|
+
"error-spiral": "mind",
|
|
5097
|
+
"recovery-good": "mind",
|
|
5098
|
+
// boundary.ts → "boundary-violation" | "boundary-healthy" | "boundary-solid"
|
|
5099
|
+
"boundary-violation": "conscience",
|
|
5100
|
+
"boundary-healthy": "conscience",
|
|
5101
|
+
"boundary-solid": "conscience",
|
|
5102
|
+
// retrieval-quality.ts → "retrieval-quality"
|
|
5103
|
+
"retrieval-quality": "mind"
|
|
5104
|
+
};
|
|
5105
|
+
var LAYER_KEYWORDS = {
|
|
5106
|
+
mind: [
|
|
5107
|
+
/\bbig_five\b/i,
|
|
5108
|
+
/\btherapy_dimensions\b/i,
|
|
5109
|
+
/\bcommunication\b/i,
|
|
5110
|
+
/\bgrowth\b/i,
|
|
5111
|
+
/\bhedg/i,
|
|
5112
|
+
/\bverbos/i,
|
|
5113
|
+
/\buncertainty/i,
|
|
5114
|
+
/\bconfidence/i,
|
|
5115
|
+
/\bself[_-]awareness/i,
|
|
5116
|
+
/\bdistress[_-]tolerance/i,
|
|
5117
|
+
/\bconflict[_-]approach/i,
|
|
5118
|
+
/\bregister\b/i,
|
|
5119
|
+
/\bformality/i,
|
|
5120
|
+
/\bsentiment/i,
|
|
5121
|
+
/\bsycophant/i,
|
|
5122
|
+
/\bapolog/i,
|
|
5123
|
+
/\brecovery/i,
|
|
5124
|
+
/\blearning[_-]orientation/i,
|
|
5125
|
+
/\bboundary[_-]awareness/i,
|
|
5126
|
+
/\binterpersonal/i,
|
|
5127
|
+
/\bpatterns[_-]to[_-]watch/i,
|
|
5128
|
+
/\bemotion/i
|
|
5129
|
+
],
|
|
5130
|
+
purpose: [
|
|
5131
|
+
/\brole\b/i,
|
|
5132
|
+
/\bobjective\b/i,
|
|
5133
|
+
/\bdomain\b/i,
|
|
5134
|
+
/\bscope\b/i,
|
|
5135
|
+
/\btask\b/i,
|
|
5136
|
+
/\bmission\b/i,
|
|
5137
|
+
/\bstakeholder\b/i
|
|
5138
|
+
],
|
|
5139
|
+
shadow: [
|
|
5140
|
+
/\bpattern\b/i,
|
|
5141
|
+
/\bblind.?spot\b/i,
|
|
5142
|
+
/\bshadow\b/i,
|
|
5143
|
+
/\bunconscious\b/i
|
|
5144
|
+
],
|
|
5145
|
+
ego: [
|
|
5146
|
+
/\bmediat/i,
|
|
5147
|
+
/\bconflict\b/i,
|
|
5148
|
+
/\badapt/i,
|
|
5149
|
+
/\bregulat/i,
|
|
5150
|
+
/\bstrateg/i,
|
|
5151
|
+
/\bbalanc/i
|
|
5152
|
+
],
|
|
5153
|
+
body: [
|
|
5154
|
+
/\bmotion\b/i,
|
|
5155
|
+
/\bgaze\b/i,
|
|
5156
|
+
/\bproxemics\b/i,
|
|
5157
|
+
/\bgesture\b/i,
|
|
5158
|
+
/\bposture\b/i,
|
|
5159
|
+
/\bexpression\b/i,
|
|
5160
|
+
/\bembodiment\b/i,
|
|
5161
|
+
/\bmorphology\b/i,
|
|
5162
|
+
/\bmodality/i,
|
|
5163
|
+
/\bsafety[_-]envelope/i,
|
|
5164
|
+
/\bactuator/i,
|
|
5165
|
+
/\bsensor/i
|
|
5166
|
+
],
|
|
5167
|
+
conscience: [
|
|
5168
|
+
/\bboundary[_-]violation/i,
|
|
5169
|
+
/\bdeny\b/i,
|
|
5170
|
+
/\brefuse/i,
|
|
5171
|
+
/\bescalat/i,
|
|
5172
|
+
/\bhard[_-]limit/i,
|
|
5173
|
+
/\boversight/i
|
|
5174
|
+
],
|
|
5175
|
+
soul: [
|
|
5176
|
+
/\bcore[_-]value/i,
|
|
5177
|
+
/\bred[_-]line/i,
|
|
5178
|
+
/\bethic/i,
|
|
5179
|
+
/\bpurpose\b/i,
|
|
5180
|
+
/\bimmutable\b/i
|
|
5181
|
+
]
|
|
5182
|
+
};
|
|
5183
|
+
function classifyPatch(recommendation) {
|
|
5184
|
+
if (LAYER_KEYWORDS.conscience.some((r) => r.test(recommendation))) {
|
|
5185
|
+
return "conscience";
|
|
5186
|
+
}
|
|
5187
|
+
if (LAYER_KEYWORDS.soul.some((r) => r.test(recommendation))) {
|
|
5188
|
+
return "soul";
|
|
5189
|
+
}
|
|
5190
|
+
if (LAYER_KEYWORDS.ego.some((r) => r.test(recommendation))) {
|
|
5191
|
+
return "ego";
|
|
5192
|
+
}
|
|
5193
|
+
if (LAYER_KEYWORDS.purpose.some((r) => r.test(recommendation))) {
|
|
5194
|
+
return "purpose";
|
|
5195
|
+
}
|
|
5196
|
+
if (LAYER_KEYWORDS.shadow.some((r) => r.test(recommendation))) {
|
|
5197
|
+
return "shadow";
|
|
5198
|
+
}
|
|
5199
|
+
if (LAYER_KEYWORDS.body.some((r) => r.test(recommendation))) {
|
|
5200
|
+
return "body";
|
|
5201
|
+
}
|
|
5202
|
+
return "mind";
|
|
5203
|
+
}
|
|
5204
|
+
function classifyByDetector(patternId, recommendation) {
|
|
5205
|
+
const mapped = DETECTOR_LAYER_MAP[patternId];
|
|
5206
|
+
if (mapped) return mapped;
|
|
5207
|
+
if (recommendation) return classifyPatch(recommendation);
|
|
5208
|
+
return "mind";
|
|
5209
|
+
}
|
|
5210
|
+
function applyStackPatches(patches, stackDir) {
|
|
5211
|
+
const applied = [];
|
|
5212
|
+
const skipped = [];
|
|
5213
|
+
const modifiedFiles = /* @__PURE__ */ new Set();
|
|
5214
|
+
const warnings = [];
|
|
5215
|
+
for (const patch of patches) {
|
|
5216
|
+
if (patch.target === "soul") {
|
|
5217
|
+
skipped.push(patch);
|
|
5218
|
+
warnings.push(
|
|
5219
|
+
`[soul] Manual approval required: ${patch.reason} (path: ${patch.path.join(".")})`
|
|
5220
|
+
);
|
|
5221
|
+
continue;
|
|
5222
|
+
}
|
|
5223
|
+
if (patch.target === "conscience") {
|
|
5224
|
+
skipped.push(patch);
|
|
5225
|
+
warnings.push(
|
|
5226
|
+
`[conscience] Manual approval required: ${patch.reason} (path: ${patch.path.join(".")})`
|
|
5227
|
+
);
|
|
5228
|
+
continue;
|
|
5229
|
+
}
|
|
5230
|
+
if (patch.target === "body") {
|
|
5231
|
+
const bodyPath = join7(stackDir, STACK_FILES.body);
|
|
5232
|
+
if (!existsSync7(bodyPath)) {
|
|
5233
|
+
skipped.push(patch);
|
|
5234
|
+
warnings.push(`[body] body.api does not exist, skipping: ${patch.reason}`);
|
|
5235
|
+
continue;
|
|
5236
|
+
}
|
|
5237
|
+
try {
|
|
5238
|
+
const content = readFileSync8(bodyPath, "utf-8");
|
|
5239
|
+
const bodyObj = JSON.parse(content);
|
|
5240
|
+
applyPatchToObject(bodyObj, patch);
|
|
5241
|
+
writeFileSync4(bodyPath, JSON.stringify(bodyObj, null, 2) + "\n");
|
|
5242
|
+
applied.push(patch);
|
|
5243
|
+
modifiedFiles.add(bodyPath);
|
|
5244
|
+
} catch (err) {
|
|
5245
|
+
skipped.push(patch);
|
|
5246
|
+
warnings.push(`[body] Failed to patch body.api: ${err}`);
|
|
5247
|
+
}
|
|
5248
|
+
continue;
|
|
5249
|
+
}
|
|
5250
|
+
if (patch.target === "mind") {
|
|
5251
|
+
const mindPath = join7(stackDir, STACK_FILES.mind);
|
|
5252
|
+
if (!existsSync7(mindPath)) {
|
|
5253
|
+
skipped.push(patch);
|
|
5254
|
+
warnings.push(`[mind] mind.sys does not exist, skipping: ${patch.reason}`);
|
|
5255
|
+
continue;
|
|
5256
|
+
}
|
|
5257
|
+
try {
|
|
5258
|
+
const content = readFileSync8(mindPath, "utf-8");
|
|
5259
|
+
const mindObj = parseYaml2(content);
|
|
5260
|
+
applyPatchToObject(mindObj, patch);
|
|
5261
|
+
writeFileSync4(mindPath, stringifyYaml2(mindObj));
|
|
5262
|
+
applied.push(patch);
|
|
5263
|
+
modifiedFiles.add(mindPath);
|
|
5264
|
+
} catch (err) {
|
|
5265
|
+
skipped.push(patch);
|
|
5266
|
+
warnings.push(`[mind] Failed to patch mind.sys: ${err}`);
|
|
5267
|
+
}
|
|
5268
|
+
continue;
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
let recompiled = false;
|
|
5272
|
+
if (modifiedFiles.size > 0) {
|
|
5273
|
+
try {
|
|
5274
|
+
compileStack({ stackDir });
|
|
5275
|
+
recompiled = true;
|
|
5276
|
+
} catch (err) {
|
|
5277
|
+
warnings.push(`Stack recompilation failed: ${err}`);
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
return {
|
|
5281
|
+
applied,
|
|
5282
|
+
skipped,
|
|
5283
|
+
filesModified: [...modifiedFiles],
|
|
5284
|
+
recompiled,
|
|
5285
|
+
warnings
|
|
5286
|
+
};
|
|
5287
|
+
}
|
|
5288
|
+
function convertToStackPatches(patternId, specPath, value, reason) {
|
|
5289
|
+
const layer = classifyByDetector(patternId, specPath);
|
|
5290
|
+
const path = specPath.split(".");
|
|
5291
|
+
let operation = "set";
|
|
5292
|
+
if (specPath.endsWith("patterns_to_watch") || specPath.endsWith("areas") || specPath.endsWith("strengths")) {
|
|
5293
|
+
operation = "append";
|
|
5294
|
+
} else if (typeof value === "number") {
|
|
5295
|
+
operation = "set";
|
|
5296
|
+
}
|
|
5297
|
+
return {
|
|
5298
|
+
target: layer,
|
|
5299
|
+
path,
|
|
5300
|
+
operation,
|
|
5301
|
+
value,
|
|
5302
|
+
reason
|
|
5303
|
+
};
|
|
5304
|
+
}
|
|
5305
|
+
function applyPatchToObject(obj, patch) {
|
|
5306
|
+
const { path, operation, value } = patch;
|
|
5307
|
+
let current = obj;
|
|
5308
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
5309
|
+
if (current[path[i]] === void 0 || current[path[i]] === null) {
|
|
5310
|
+
current[path[i]] = {};
|
|
5311
|
+
}
|
|
5312
|
+
current = current[path[i]];
|
|
5313
|
+
}
|
|
5314
|
+
const lastKey = path[path.length - 1];
|
|
5315
|
+
switch (operation) {
|
|
5316
|
+
case "set":
|
|
5317
|
+
if (typeof value === "number") {
|
|
5318
|
+
current[lastKey] = Math.max(0, Math.min(1, value));
|
|
5319
|
+
} else {
|
|
5320
|
+
current[lastKey] = value;
|
|
5321
|
+
}
|
|
5322
|
+
break;
|
|
5323
|
+
case "adjust": {
|
|
5324
|
+
const existing = typeof current[lastKey] === "number" ? current[lastKey] : 0;
|
|
5325
|
+
const delta = typeof value === "number" ? value : 0;
|
|
5326
|
+
current[lastKey] = Math.max(0, Math.min(1, existing + delta));
|
|
5327
|
+
break;
|
|
5328
|
+
}
|
|
5329
|
+
case "append": {
|
|
5330
|
+
if (!Array.isArray(current[lastKey])) {
|
|
5331
|
+
current[lastKey] = [];
|
|
5332
|
+
}
|
|
5333
|
+
if (typeof value === "string" && !current[lastKey].includes(value)) {
|
|
5334
|
+
current[lastKey].push(value);
|
|
5335
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
5336
|
+
current[lastKey].push(value);
|
|
5337
|
+
}
|
|
5338
|
+
break;
|
|
5339
|
+
}
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5342
|
+
|
|
4670
5343
|
// src/analysis/session-runner.ts
|
|
4671
5344
|
async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
4672
5345
|
const promptOptions = {
|
|
@@ -4835,7 +5508,136 @@ function extractRecommendations(turns) {
|
|
|
4835
5508
|
}
|
|
4836
5509
|
return recommendations.slice(0, 5);
|
|
4837
5510
|
}
|
|
4838
|
-
async function applyRecommendations(spec, diagnosis, transcript, provider) {
|
|
5511
|
+
async function applyRecommendations(spec, diagnosis, transcript, provider, options) {
|
|
5512
|
+
const projectRoot = options?.projectRoot ?? process.cwd();
|
|
5513
|
+
const stackDir = findStackDir(projectRoot);
|
|
5514
|
+
if (stackDir) {
|
|
5515
|
+
return applyRecommendationsStack(spec, diagnosis, stackDir, transcript, provider);
|
|
5516
|
+
}
|
|
5517
|
+
return applyRecommendationsLegacy(spec, diagnosis, transcript, provider);
|
|
5518
|
+
}
|
|
5519
|
+
async function applyRecommendationsStack(spec, diagnosis, stackDir, transcript, provider) {
|
|
5520
|
+
const changes = [];
|
|
5521
|
+
const patches = [];
|
|
5522
|
+
const patternIds = diagnosis.patterns.map((p) => p.id);
|
|
5523
|
+
if (patternIds.includes("over-apologizing")) {
|
|
5524
|
+
if (spec.communication?.uncertainty_handling !== "confident_transparency") {
|
|
5525
|
+
patches.push(convertToStackPatches(
|
|
5526
|
+
"over-apologizing",
|
|
5527
|
+
"communication.uncertainty_handling",
|
|
5528
|
+
"confident_transparency",
|
|
5529
|
+
"Over-apologizing detected: set uncertainty_handling to confident_transparency"
|
|
5530
|
+
));
|
|
5531
|
+
}
|
|
5532
|
+
}
|
|
5533
|
+
if (patternIds.includes("hedge-stacking")) {
|
|
5534
|
+
const watched = spec.growth?.patterns_to_watch ?? [];
|
|
5535
|
+
if (!watched.includes("hedge stacking under uncertainty")) {
|
|
5536
|
+
patches.push(convertToStackPatches(
|
|
5537
|
+
"hedge-stacking",
|
|
5538
|
+
"growth.patterns_to_watch",
|
|
5539
|
+
"hedge stacking under uncertainty",
|
|
5540
|
+
"Hedge stacking detected: add to patterns_to_watch"
|
|
5541
|
+
));
|
|
5542
|
+
}
|
|
5543
|
+
}
|
|
5544
|
+
if (patternIds.includes("sycophantic-tendency")) {
|
|
5545
|
+
if (spec.communication?.conflict_approach !== "honest_first") {
|
|
5546
|
+
patches.push(convertToStackPatches(
|
|
5547
|
+
"sycophantic-tendency",
|
|
5548
|
+
"communication.conflict_approach",
|
|
5549
|
+
"honest_first",
|
|
5550
|
+
"Sycophantic tendency: set conflict_approach to honest_first"
|
|
5551
|
+
));
|
|
5552
|
+
}
|
|
5553
|
+
if ((spec.therapy_dimensions?.self_awareness ?? 0) < 0.85) {
|
|
5554
|
+
patches.push(convertToStackPatches(
|
|
5555
|
+
"sycophantic-tendency",
|
|
5556
|
+
"therapy_dimensions.self_awareness",
|
|
5557
|
+
0.85,
|
|
5558
|
+
"Sycophantic tendency: increase self_awareness to 0.85"
|
|
5559
|
+
));
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5562
|
+
if (patternIds.includes("error-spiral")) {
|
|
5563
|
+
if ((spec.therapy_dimensions?.distress_tolerance ?? 0) < 0.8) {
|
|
5564
|
+
patches.push(convertToStackPatches(
|
|
5565
|
+
"error-spiral",
|
|
5566
|
+
"therapy_dimensions.distress_tolerance",
|
|
5567
|
+
0.8,
|
|
5568
|
+
"Error spiral detected: increase distress_tolerance to 0.80"
|
|
5569
|
+
));
|
|
5570
|
+
}
|
|
5571
|
+
const hasRecovery = (spec.growth?.areas ?? []).some(
|
|
5572
|
+
(a) => typeof a === "string" ? a.includes("error recovery") : a.area?.includes("error recovery")
|
|
5573
|
+
);
|
|
5574
|
+
if (!hasRecovery) {
|
|
5575
|
+
patches.push(convertToStackPatches(
|
|
5576
|
+
"error-spiral",
|
|
5577
|
+
"growth.areas",
|
|
5578
|
+
{
|
|
5579
|
+
area: "deliberate error recovery",
|
|
5580
|
+
severity: "moderate",
|
|
5581
|
+
first_detected: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
5582
|
+
session_count: 1,
|
|
5583
|
+
resolved: false
|
|
5584
|
+
},
|
|
5585
|
+
"Error spiral detected: add deliberate error recovery to growth areas"
|
|
5586
|
+
));
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
if (patternIds.includes("negative-sentiment-skew")) {
|
|
5590
|
+
const watched = spec.growth?.patterns_to_watch ?? [];
|
|
5591
|
+
if (!watched.includes("negative sentiment patterns")) {
|
|
5592
|
+
patches.push(convertToStackPatches(
|
|
5593
|
+
"negative-sentiment-skew",
|
|
5594
|
+
"growth.patterns_to_watch",
|
|
5595
|
+
"negative sentiment patterns",
|
|
5596
|
+
"Negative sentiment skew: add to patterns_to_watch"
|
|
5597
|
+
));
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
if (transcript && provider && transcript.turns.length > 4) {
|
|
5601
|
+
try {
|
|
5602
|
+
const llmChanges = await deriveLLMRecommendations(spec, transcript, provider);
|
|
5603
|
+
for (const change of llmChanges) {
|
|
5604
|
+
const layer = classifyByDetector("", change.path);
|
|
5605
|
+
patches.push({
|
|
5606
|
+
target: layer,
|
|
5607
|
+
path: change.path.split("."),
|
|
5608
|
+
operation: change.path.endsWith("patterns_to_watch") || change.path.endsWith("areas") || change.path.endsWith("strengths") ? "append" : "set",
|
|
5609
|
+
value: change.value,
|
|
5610
|
+
reason: change.description
|
|
5611
|
+
});
|
|
5612
|
+
}
|
|
5613
|
+
} catch {
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5616
|
+
if (patches.length === 0) {
|
|
5617
|
+
return { changed: false, changes: [], stackFilesModified: [] };
|
|
5618
|
+
}
|
|
5619
|
+
const result = applyStackPatches(patches, stackDir);
|
|
5620
|
+
for (const patch of result.applied) {
|
|
5621
|
+
changes.push(`[${patch.target}] ${patch.path.join(".")} \u2192 ${JSON.stringify(patch.value)} (${patch.reason})`);
|
|
5622
|
+
}
|
|
5623
|
+
for (const warning of result.warnings) {
|
|
5624
|
+
changes.push(warning);
|
|
5625
|
+
}
|
|
5626
|
+
if (result.recompiled) {
|
|
5627
|
+
try {
|
|
5628
|
+
const compiled = compileStack({ stackDir });
|
|
5629
|
+
Object.assign(spec, compiled.spec);
|
|
5630
|
+
changes.push(`Stack recompiled from ${result.filesModified.length} modified source file(s)`);
|
|
5631
|
+
} catch {
|
|
5632
|
+
}
|
|
5633
|
+
}
|
|
5634
|
+
return {
|
|
5635
|
+
changed: result.applied.length > 0,
|
|
5636
|
+
changes,
|
|
5637
|
+
stackFilesModified: result.filesModified
|
|
5638
|
+
};
|
|
5639
|
+
}
|
|
5640
|
+
async function applyRecommendationsLegacy(spec, diagnosis, transcript, provider) {
|
|
4839
5641
|
const changes = [];
|
|
4840
5642
|
const patternIds = diagnosis.patterns.map((p) => p.id);
|
|
4841
5643
|
if (patternIds.includes("over-apologizing")) {
|
|
@@ -4983,20 +5785,20 @@ function applyStructuredChange(spec, change) {
|
|
|
4983
5785
|
}
|
|
4984
5786
|
}
|
|
4985
5787
|
function saveTranscript(transcript, agentName) {
|
|
4986
|
-
const dir =
|
|
4987
|
-
if (!
|
|
5788
|
+
const dir = resolve7(process.cwd(), ".holomime", "sessions");
|
|
5789
|
+
if (!existsSync8(dir)) {
|
|
4988
5790
|
mkdirSync5(dir, { recursive: true });
|
|
4989
5791
|
}
|
|
4990
5792
|
const slug = agentName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
4991
5793
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4992
5794
|
const filename = `${date}-${slug}.json`;
|
|
4993
|
-
const filepath =
|
|
4994
|
-
|
|
5795
|
+
const filepath = join8(dir, filename);
|
|
5796
|
+
writeFileSync5(filepath, JSON.stringify(transcript, null, 2));
|
|
4995
5797
|
return filepath;
|
|
4996
5798
|
}
|
|
4997
5799
|
|
|
4998
5800
|
// src/analysis/autopilot-core.ts
|
|
4999
|
-
import { writeFileSync as
|
|
5801
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
5000
5802
|
var SEVERITY_ORDER = ["routine", "targeted", "intervention"];
|
|
5001
5803
|
function severityMeetsThreshold(severity, threshold) {
|
|
5002
5804
|
const severityIdx = SEVERITY_ORDER.indexOf(severity);
|
|
@@ -5033,7 +5835,7 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
5033
5835
|
const specCopy = JSON.parse(JSON.stringify(spec));
|
|
5034
5836
|
const { changed, changes } = await applyRecommendations(specCopy, diagnosis, transcript, provider);
|
|
5035
5837
|
if (changed && options?.specPath) {
|
|
5036
|
-
|
|
5838
|
+
writeFileSync6(options.specPath, JSON.stringify(specCopy, null, 2) + "\n");
|
|
5037
5839
|
}
|
|
5038
5840
|
saveTranscript(transcript, spec.name ?? "Agent");
|
|
5039
5841
|
return {
|
|
@@ -5049,8 +5851,8 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
5049
5851
|
}
|
|
5050
5852
|
|
|
5051
5853
|
// src/analysis/training-export.ts
|
|
5052
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
5053
|
-
import { join as
|
|
5854
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync9 } from "fs";
|
|
5855
|
+
import { join as join9 } from "path";
|
|
5054
5856
|
function extractDPOPairs(transcript) {
|
|
5055
5857
|
const pairs = [];
|
|
5056
5858
|
const turns = transcript.turns;
|
|
@@ -5156,7 +5958,7 @@ function loadTranscripts(sessionsDir) {
|
|
|
5156
5958
|
try {
|
|
5157
5959
|
const files = readdirSync2(sessionsDir).filter((f) => f.endsWith(".json")).sort();
|
|
5158
5960
|
return files.map((f) => {
|
|
5159
|
-
const raw =
|
|
5961
|
+
const raw = readFileSync9(join9(sessionsDir, f), "utf-8");
|
|
5160
5962
|
return JSON.parse(raw);
|
|
5161
5963
|
});
|
|
5162
5964
|
} catch {
|
|
@@ -5389,12 +6191,12 @@ async function pushToHFHub(jsonl, options) {
|
|
|
5389
6191
|
}
|
|
5390
6192
|
|
|
5391
6193
|
// src/analysis/treatment-plan.ts
|
|
5392
|
-
import { readFileSync as
|
|
5393
|
-
import { resolve as
|
|
6194
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync9, mkdirSync as mkdirSync6 } from "fs";
|
|
6195
|
+
import { resolve as resolve8 } from "path";
|
|
5394
6196
|
var PLAN_DIR = ".holomime";
|
|
5395
6197
|
var PLAN_FILE = "treatment-plan.json";
|
|
5396
6198
|
function getPlanPath() {
|
|
5397
|
-
return
|
|
6199
|
+
return resolve8(process.cwd(), PLAN_DIR, PLAN_FILE);
|
|
5398
6200
|
}
|
|
5399
6201
|
function createTreatmentPlan(agentName, diagnosis) {
|
|
5400
6202
|
const goals = [];
|
|
@@ -5428,18 +6230,18 @@ function createTreatmentPlan(agentName, diagnosis) {
|
|
|
5428
6230
|
}
|
|
5429
6231
|
function loadTreatmentPlan() {
|
|
5430
6232
|
const path = getPlanPath();
|
|
5431
|
-
if (!
|
|
6233
|
+
if (!existsSync9(path)) return null;
|
|
5432
6234
|
try {
|
|
5433
|
-
return JSON.parse(
|
|
6235
|
+
return JSON.parse(readFileSync10(path, "utf-8"));
|
|
5434
6236
|
} catch {
|
|
5435
6237
|
return null;
|
|
5436
6238
|
}
|
|
5437
6239
|
}
|
|
5438
6240
|
function saveTreatmentPlan(plan) {
|
|
5439
|
-
const dir =
|
|
5440
|
-
if (!
|
|
6241
|
+
const dir = resolve8(process.cwd(), PLAN_DIR);
|
|
6242
|
+
if (!existsSync9(dir)) mkdirSync6(dir, { recursive: true });
|
|
5441
6243
|
const path = getPlanPath();
|
|
5442
|
-
|
|
6244
|
+
writeFileSync7(path, JSON.stringify(plan, null, 2) + "\n");
|
|
5443
6245
|
return path;
|
|
5444
6246
|
}
|
|
5445
6247
|
function recordSessionOutcome(plan, transcript, transcriptPath, diagnosis) {
|
|
@@ -5685,19 +6487,19 @@ function generateSummary(patterns, score, grade) {
|
|
|
5685
6487
|
}
|
|
5686
6488
|
|
|
5687
6489
|
// src/analysis/evolve-core.ts
|
|
5688
|
-
import { writeFileSync as
|
|
6490
|
+
import { writeFileSync as writeFileSync10 } from "fs";
|
|
5689
6491
|
|
|
5690
6492
|
// src/analysis/evolution-history.ts
|
|
5691
|
-
import { readFileSync as
|
|
5692
|
-
import { resolve as
|
|
6493
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync10 } from "fs";
|
|
6494
|
+
import { resolve as resolve9 } from "path";
|
|
5693
6495
|
function getEvolutionPath() {
|
|
5694
|
-
return
|
|
6496
|
+
return resolve9(process.cwd(), ".holomime", "evolution.json");
|
|
5695
6497
|
}
|
|
5696
6498
|
function loadEvolution(agentName) {
|
|
5697
6499
|
const filepath = getEvolutionPath();
|
|
5698
|
-
if (!
|
|
6500
|
+
if (!existsSync10(filepath)) return null;
|
|
5699
6501
|
try {
|
|
5700
|
-
const raw =
|
|
6502
|
+
const raw = readFileSync11(filepath, "utf-8");
|
|
5701
6503
|
return JSON.parse(raw);
|
|
5702
6504
|
} catch {
|
|
5703
6505
|
return null;
|
|
@@ -5705,8 +6507,8 @@ function loadEvolution(agentName) {
|
|
|
5705
6507
|
}
|
|
5706
6508
|
function appendEvolution(entry, agentName) {
|
|
5707
6509
|
const filepath = getEvolutionPath();
|
|
5708
|
-
const dir =
|
|
5709
|
-
if (!
|
|
6510
|
+
const dir = resolve9(process.cwd(), ".holomime");
|
|
6511
|
+
if (!existsSync10(dir)) {
|
|
5710
6512
|
mkdirSync7(dir, { recursive: true });
|
|
5711
6513
|
}
|
|
5712
6514
|
let history = loadEvolution(agentName);
|
|
@@ -5724,7 +6526,7 @@ function appendEvolution(entry, agentName) {
|
|
|
5724
6526
|
history.totalSessions = history.entries.length;
|
|
5725
6527
|
history.totalDPOPairs = history.entries.reduce((sum, e) => sum + e.dpoPairsExtracted, 0);
|
|
5726
6528
|
history.lastSession = entry.timestamp;
|
|
5727
|
-
|
|
6529
|
+
writeFileSync8(filepath, JSON.stringify(history, null, 2) + "\n");
|
|
5728
6530
|
}
|
|
5729
6531
|
function getEvolutionSummary(history) {
|
|
5730
6532
|
const entries = history.entries;
|
|
@@ -5762,30 +6564,30 @@ function getEvolutionSummary(history) {
|
|
|
5762
6564
|
}
|
|
5763
6565
|
|
|
5764
6566
|
// src/analysis/behavioral-memory.ts
|
|
5765
|
-
import { readFileSync as
|
|
5766
|
-
import { resolve as
|
|
6567
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync11 } from "fs";
|
|
6568
|
+
import { resolve as resolve10, join as join12 } from "path";
|
|
5767
6569
|
function memoryDir2(agentHandle) {
|
|
5768
|
-
return
|
|
6570
|
+
return resolve10(process.cwd(), ".holomime", "memory", agentHandle);
|
|
5769
6571
|
}
|
|
5770
6572
|
function behavioralMemoryPath(agentHandle) {
|
|
5771
|
-
return
|
|
6573
|
+
return join12(memoryDir2(agentHandle), "behavioral-memory.json");
|
|
5772
6574
|
}
|
|
5773
6575
|
function loadBehavioralMemory(agentHandle) {
|
|
5774
6576
|
const path = behavioralMemoryPath(agentHandle);
|
|
5775
|
-
if (!
|
|
6577
|
+
if (!existsSync11(path)) return null;
|
|
5776
6578
|
try {
|
|
5777
|
-
return JSON.parse(
|
|
6579
|
+
return JSON.parse(readFileSync12(path, "utf-8"));
|
|
5778
6580
|
} catch {
|
|
5779
6581
|
return null;
|
|
5780
6582
|
}
|
|
5781
6583
|
}
|
|
5782
6584
|
function saveBehavioralMemory(store) {
|
|
5783
6585
|
const dir = memoryDir2(store.agentHandle);
|
|
5784
|
-
if (!
|
|
6586
|
+
if (!existsSync11(dir)) {
|
|
5785
6587
|
mkdirSync8(dir, { recursive: true });
|
|
5786
6588
|
}
|
|
5787
6589
|
const path = behavioralMemoryPath(store.agentHandle);
|
|
5788
|
-
|
|
6590
|
+
writeFileSync9(path, JSON.stringify(store, null, 2));
|
|
5789
6591
|
return path;
|
|
5790
6592
|
}
|
|
5791
6593
|
function createBehavioralMemory(agentHandle, agentName) {
|
|
@@ -6314,7 +7116,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6314
7116
|
const useStaging = options?.useStaging !== false;
|
|
6315
7117
|
if (useStaging) {
|
|
6316
7118
|
const stagingPath = options.specPath.replace(/\.json$/, ".staging.json");
|
|
6317
|
-
|
|
7119
|
+
writeFileSync10(stagingPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6318
7120
|
const allChanges = iterations.flatMap((i) => i.appliedChanges);
|
|
6319
7121
|
const diff = {
|
|
6320
7122
|
stagingPath,
|
|
@@ -6327,7 +7129,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6327
7129
|
approved = await options.onStagingReview(diff);
|
|
6328
7130
|
}
|
|
6329
7131
|
if (approved) {
|
|
6330
|
-
|
|
7132
|
+
writeFileSync10(options.specPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6331
7133
|
try {
|
|
6332
7134
|
const { unlinkSync } = await import("fs");
|
|
6333
7135
|
unlinkSync(stagingPath);
|
|
@@ -6335,7 +7137,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6335
7137
|
}
|
|
6336
7138
|
}
|
|
6337
7139
|
} else {
|
|
6338
|
-
|
|
7140
|
+
writeFileSync10(options.specPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6339
7141
|
}
|
|
6340
7142
|
}
|
|
6341
7143
|
try {
|
|
@@ -6352,7 +7154,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6352
7154
|
generated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6353
7155
|
};
|
|
6354
7156
|
if (options?.exportDpoPath) {
|
|
6355
|
-
|
|
7157
|
+
writeFileSync10(options.exportDpoPath, JSON.stringify(trainingExport, null, 2) + "\n");
|
|
6356
7158
|
}
|
|
6357
7159
|
}
|
|
6358
7160
|
try {
|
|
@@ -6713,12 +7515,12 @@ function gradeFromScore2(score) {
|
|
|
6713
7515
|
}
|
|
6714
7516
|
|
|
6715
7517
|
// src/analysis/benchmark-publish.ts
|
|
6716
|
-
import { readFileSync as
|
|
6717
|
-
import { join as
|
|
7518
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, existsSync as existsSync12, mkdirSync as mkdirSync9, readdirSync as readdirSync3 } from "fs";
|
|
7519
|
+
import { join as join13 } from "path";
|
|
6718
7520
|
import { homedir } from "os";
|
|
6719
7521
|
function getBenchmarkDir(outputDir) {
|
|
6720
|
-
const dir = outputDir ??
|
|
6721
|
-
if (!
|
|
7522
|
+
const dir = outputDir ?? join13(homedir(), ".holomime", "benchmarks");
|
|
7523
|
+
if (!existsSync12(dir)) {
|
|
6722
7524
|
mkdirSync9(dir, { recursive: true });
|
|
6723
7525
|
}
|
|
6724
7526
|
return dir;
|
|
@@ -6730,7 +7532,7 @@ function saveBenchmarkResult(report, outputDir) {
|
|
|
6730
7532
|
const dir = getBenchmarkDir(outputDir);
|
|
6731
7533
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6732
7534
|
const filename = `${sanitize(report.provider)}-${sanitize(report.model)}-${date}.json`;
|
|
6733
|
-
const filepath =
|
|
7535
|
+
const filepath = join13(dir, filename);
|
|
6734
7536
|
const published = {
|
|
6735
7537
|
agent: report.agent,
|
|
6736
7538
|
provider: report.provider,
|
|
@@ -6744,17 +7546,17 @@ function saveBenchmarkResult(report, outputDir) {
|
|
|
6744
7546
|
scenarioCount: report.results.length
|
|
6745
7547
|
}
|
|
6746
7548
|
};
|
|
6747
|
-
|
|
7549
|
+
writeFileSync11(filepath, JSON.stringify(published, null, 2));
|
|
6748
7550
|
return filepath;
|
|
6749
7551
|
}
|
|
6750
7552
|
function loadBenchmarkResults(dir) {
|
|
6751
7553
|
const benchmarkDir = getBenchmarkDir(dir);
|
|
6752
|
-
if (!
|
|
7554
|
+
if (!existsSync12(benchmarkDir)) return [];
|
|
6753
7555
|
const files = readdirSync3(benchmarkDir).filter((f) => f.endsWith(".json"));
|
|
6754
7556
|
const results = [];
|
|
6755
7557
|
for (const file of files) {
|
|
6756
7558
|
try {
|
|
6757
|
-
const content =
|
|
7559
|
+
const content = readFileSync13(join13(benchmarkDir, file), "utf-8");
|
|
6758
7560
|
results.push(JSON.parse(content));
|
|
6759
7561
|
} catch {
|
|
6760
7562
|
}
|
|
@@ -6848,7 +7650,7 @@ function generateBenchmarkMarkdown(benchmarks) {
|
|
|
6848
7650
|
lines.push("");
|
|
6849
7651
|
return lines.join("\n");
|
|
6850
7652
|
}
|
|
6851
|
-
async function publishToLeaderboard(benchmark, apiKey, apiUrl = "https://holomime.
|
|
7653
|
+
async function publishToLeaderboard(benchmark, apiKey, apiUrl = "https://holomime.com") {
|
|
6852
7654
|
const key = apiKey ?? process.env.HOLOMIME_API_KEY;
|
|
6853
7655
|
if (!key) {
|
|
6854
7656
|
return { success: false, error: "No API key. Run `holomime activate` or set HOLOMIME_API_KEY." };
|
|
@@ -6885,7 +7687,7 @@ async function publishToLeaderboard(benchmark, apiKey, apiUrl = "https://holomim
|
|
|
6885
7687
|
return { success: false, error: err instanceof Error ? err.message : "Network error" };
|
|
6886
7688
|
}
|
|
6887
7689
|
}
|
|
6888
|
-
async function fetchLeaderboard(limit = 50, apiUrl = "https://holomime.
|
|
7690
|
+
async function fetchLeaderboard(limit = 50, apiUrl = "https://holomime.com") {
|
|
6889
7691
|
try {
|
|
6890
7692
|
const response = await fetch(`${apiUrl}/api/v1/leaderboard?limit=${limit}`);
|
|
6891
7693
|
if (!response.ok) return [];
|
|
@@ -6917,8 +7719,8 @@ function generateComparisonMarkdown(comparison) {
|
|
|
6917
7719
|
}
|
|
6918
7720
|
|
|
6919
7721
|
// src/analysis/watch-core.ts
|
|
6920
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
6921
|
-
import { join as
|
|
7722
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, existsSync as existsSync13 } from "fs";
|
|
7723
|
+
import { join as join14, resolve as resolve11 } from "path";
|
|
6922
7724
|
|
|
6923
7725
|
// src/adapters/chatgpt.ts
|
|
6924
7726
|
function mapRole(role) {
|
|
@@ -7352,7 +8154,7 @@ function startWatch(spec, options) {
|
|
|
7352
8154
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
7353
8155
|
let stopped = false;
|
|
7354
8156
|
let currentSpec = JSON.parse(JSON.stringify(spec));
|
|
7355
|
-
if (
|
|
8157
|
+
if (existsSync13(options.watchDir)) {
|
|
7356
8158
|
const existing = readdirSync4(options.watchDir).filter((f) => f.endsWith(".json")).sort();
|
|
7357
8159
|
for (const f of existing) {
|
|
7358
8160
|
seenFiles.add(f);
|
|
@@ -7360,7 +8162,7 @@ function startWatch(spec, options) {
|
|
|
7360
8162
|
}
|
|
7361
8163
|
async function scan() {
|
|
7362
8164
|
if (stopped) return;
|
|
7363
|
-
if (!
|
|
8165
|
+
if (!existsSync13(options.watchDir)) {
|
|
7364
8166
|
return;
|
|
7365
8167
|
}
|
|
7366
8168
|
const files = readdirSync4(options.watchDir).filter((f) => f.endsWith(".json")).sort();
|
|
@@ -7374,7 +8176,7 @@ function startWatch(spec, options) {
|
|
|
7374
8176
|
events.push({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), type: "new_file", filename });
|
|
7375
8177
|
let messages;
|
|
7376
8178
|
try {
|
|
7377
|
-
const raw = JSON.parse(
|
|
8179
|
+
const raw = JSON.parse(readFileSync14(join14(options.watchDir, filename), "utf-8"));
|
|
7378
8180
|
const conversations = parseConversationLog(raw, "auto");
|
|
7379
8181
|
messages = conversations.flatMap((c) => c.messages);
|
|
7380
8182
|
} catch (err) {
|
|
@@ -7433,12 +8235,12 @@ function startWatch(spec, options) {
|
|
|
7433
8235
|
function stop() {
|
|
7434
8236
|
stopped = true;
|
|
7435
8237
|
clearInterval(interval);
|
|
7436
|
-
const logDir =
|
|
7437
|
-
if (!
|
|
8238
|
+
const logDir = resolve11(process.cwd(), ".holomime");
|
|
8239
|
+
if (!existsSync13(logDir)) {
|
|
7438
8240
|
mkdirSync10(logDir, { recursive: true });
|
|
7439
8241
|
}
|
|
7440
|
-
|
|
7441
|
-
|
|
8242
|
+
writeFileSync12(
|
|
8243
|
+
join14(logDir, "watch-log.json"),
|
|
7442
8244
|
JSON.stringify({ events, stoppedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
|
|
7443
8245
|
);
|
|
7444
8246
|
}
|
|
@@ -7446,10 +8248,10 @@ function startWatch(spec, options) {
|
|
|
7446
8248
|
}
|
|
7447
8249
|
|
|
7448
8250
|
// src/analysis/fleet-core.ts
|
|
7449
|
-
import { readFileSync as
|
|
7450
|
-
import { join as
|
|
8251
|
+
import { readFileSync as readFileSync15, existsSync as existsSync14, readdirSync as readdirSync5 } from "fs";
|
|
8252
|
+
import { join as join15, resolve as resolve12 } from "path";
|
|
7451
8253
|
function loadFleetConfig(configPath) {
|
|
7452
|
-
const raw = JSON.parse(
|
|
8254
|
+
const raw = JSON.parse(readFileSync15(configPath, "utf-8"));
|
|
7453
8255
|
if (!raw.agents || !Array.isArray(raw.agents)) {
|
|
7454
8256
|
throw new Error("fleet.json must contain an 'agents' array");
|
|
7455
8257
|
}
|
|
@@ -7463,21 +8265,21 @@ function loadFleetConfig(configPath) {
|
|
|
7463
8265
|
}
|
|
7464
8266
|
function discoverAgents(dir) {
|
|
7465
8267
|
const agents = [];
|
|
7466
|
-
const absDir =
|
|
7467
|
-
if (!
|
|
8268
|
+
const absDir = resolve12(dir);
|
|
8269
|
+
if (!existsSync14(absDir)) {
|
|
7468
8270
|
throw new Error(`Directory not found: ${absDir}`);
|
|
7469
8271
|
}
|
|
7470
8272
|
const entries = readdirSync5(absDir, { withFileTypes: true });
|
|
7471
8273
|
for (const entry of entries) {
|
|
7472
8274
|
if (!entry.isDirectory()) continue;
|
|
7473
|
-
const agentDir =
|
|
7474
|
-
const specPath =
|
|
7475
|
-
const logDir =
|
|
7476
|
-
if (
|
|
8275
|
+
const agentDir = join15(absDir, entry.name);
|
|
8276
|
+
const specPath = join15(agentDir, ".personality.json");
|
|
8277
|
+
const logDir = join15(agentDir, "logs");
|
|
8278
|
+
if (existsSync14(specPath)) {
|
|
7477
8279
|
agents.push({
|
|
7478
8280
|
name: entry.name,
|
|
7479
8281
|
specPath,
|
|
7480
|
-
logDir:
|
|
8282
|
+
logDir: existsSync14(logDir) ? logDir : agentDir
|
|
7481
8283
|
});
|
|
7482
8284
|
}
|
|
7483
8285
|
}
|
|
@@ -7501,8 +8303,8 @@ function startFleet(config, options) {
|
|
|
7501
8303
|
const concurrency = options.concurrency ?? 5;
|
|
7502
8304
|
const agentQueue = [...config.agents];
|
|
7503
8305
|
agentQueue.sort((a, b) => {
|
|
7504
|
-
const aDrift =
|
|
7505
|
-
const bDrift =
|
|
8306
|
+
const aDrift = existsSync14(join15(a.logDir, ".holomime", "watch-log.json")) ? 0 : 1;
|
|
8307
|
+
const bDrift = existsSync14(join15(b.logDir, ".holomime", "watch-log.json")) ? 0 : 1;
|
|
7506
8308
|
return aDrift - bDrift;
|
|
7507
8309
|
});
|
|
7508
8310
|
const agentsToStart = agentQueue.slice(0, concurrency);
|
|
@@ -7637,8 +8439,8 @@ function startSingleAgent(agent, options, statusMap, allEvents, handles) {
|
|
|
7637
8439
|
}
|
|
7638
8440
|
|
|
7639
8441
|
// src/analysis/certify-core.ts
|
|
7640
|
-
import { writeFileSync as
|
|
7641
|
-
import { join as
|
|
8442
|
+
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync11, existsSync as existsSync15 } from "fs";
|
|
8443
|
+
import { join as join16, resolve as resolve13 } from "path";
|
|
7642
8444
|
function djb2Hash(str) {
|
|
7643
8445
|
let hash = 0;
|
|
7644
8446
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -7751,14 +8553,14 @@ function verifyCredential(credential, spec) {
|
|
|
7751
8553
|
return { valid: true };
|
|
7752
8554
|
}
|
|
7753
8555
|
function saveCredential(credential, outputDir) {
|
|
7754
|
-
const dir = outputDir ??
|
|
7755
|
-
if (!
|
|
8556
|
+
const dir = outputDir ?? resolve13(process.cwd(), ".holomime", "credentials");
|
|
8557
|
+
if (!existsSync15(dir)) {
|
|
7756
8558
|
mkdirSync11(dir, { recursive: true });
|
|
7757
8559
|
}
|
|
7758
8560
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
7759
8561
|
const filename = `${credential.agent.handle}-${date}.json`;
|
|
7760
|
-
const filepath =
|
|
7761
|
-
|
|
8562
|
+
const filepath = join16(dir, filename);
|
|
8563
|
+
writeFileSync13(filepath, JSON.stringify(credential, null, 2) + "\n");
|
|
7762
8564
|
return filepath;
|
|
7763
8565
|
}
|
|
7764
8566
|
|
|
@@ -7868,7 +8670,7 @@ function parseRetryAfter(response) {
|
|
|
7868
8670
|
return 0;
|
|
7869
8671
|
}
|
|
7870
8672
|
function delay(ms) {
|
|
7871
|
-
return new Promise((
|
|
8673
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
7872
8674
|
}
|
|
7873
8675
|
var OpenAIProvider = class {
|
|
7874
8676
|
name = "openai";
|
|
@@ -8030,21 +8832,21 @@ async function* ollamaChatStream(model, messages) {
|
|
|
8030
8832
|
}
|
|
8031
8833
|
|
|
8032
8834
|
// src/marketplace/registry.ts
|
|
8033
|
-
import { readFileSync as
|
|
8034
|
-
import { resolve as
|
|
8835
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
8836
|
+
import { resolve as resolve14, dirname as dirname3 } from "path";
|
|
8035
8837
|
import { fileURLToPath } from "url";
|
|
8036
|
-
var REGISTRY_URL = "https://raw.githubusercontent.com/productstein/holomime
|
|
8838
|
+
var REGISTRY_URL = "https://raw.githubusercontent.com/productstein/holomime/main/registry/index.json";
|
|
8037
8839
|
function loadLocalRegistry() {
|
|
8038
8840
|
const __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
8039
8841
|
const candidates = [
|
|
8040
|
-
|
|
8842
|
+
resolve14(__dirname, "..", "registry", "index.json"),
|
|
8041
8843
|
// from dist/
|
|
8042
|
-
|
|
8844
|
+
resolve14(__dirname, "..", "..", "registry", "index.json")
|
|
8043
8845
|
// from src/marketplace/
|
|
8044
8846
|
];
|
|
8045
8847
|
for (const p of candidates) {
|
|
8046
8848
|
try {
|
|
8047
|
-
const raw =
|
|
8849
|
+
const raw = readFileSync17(p, "utf-8");
|
|
8048
8850
|
return JSON.parse(raw);
|
|
8049
8851
|
} catch {
|
|
8050
8852
|
continue;
|
|
@@ -8081,12 +8883,12 @@ async function fetchPersonality(url) {
|
|
|
8081
8883
|
if (match) {
|
|
8082
8884
|
const __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
8083
8885
|
const candidates = [
|
|
8084
|
-
|
|
8085
|
-
|
|
8886
|
+
resolve14(__dirname, "..", "registry", "personalities", `${match[1]}.personality.json`),
|
|
8887
|
+
resolve14(__dirname, "..", "..", "registry", "personalities", `${match[1]}.personality.json`)
|
|
8086
8888
|
];
|
|
8087
8889
|
for (const p of candidates) {
|
|
8088
8890
|
try {
|
|
8089
|
-
const raw =
|
|
8891
|
+
const raw = readFileSync17(p, "utf-8");
|
|
8090
8892
|
return JSON.parse(raw);
|
|
8091
8893
|
} catch {
|
|
8092
8894
|
continue;
|
|
@@ -8125,73 +8927,73 @@ async function createGist(spec, handle, token) {
|
|
|
8125
8927
|
}
|
|
8126
8928
|
|
|
8127
8929
|
// src/marketplace/api.ts
|
|
8128
|
-
import { existsSync as
|
|
8129
|
-
import { join as
|
|
8930
|
+
import { existsSync as existsSync17, readFileSync as readFileSync19 } from "fs";
|
|
8931
|
+
import { join as join18 } from "path";
|
|
8130
8932
|
import { homedir as homedir3 } from "os";
|
|
8131
8933
|
|
|
8132
8934
|
// src/marketplace/local-backend.ts
|
|
8133
|
-
import { existsSync as
|
|
8134
|
-
import { join as
|
|
8935
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
8936
|
+
import { join as join17 } from "path";
|
|
8135
8937
|
import { homedir as homedir2 } from "os";
|
|
8136
8938
|
function marketplaceDir() {
|
|
8137
|
-
const dir =
|
|
8138
|
-
if (!
|
|
8939
|
+
const dir = join17(homedir2(), ".holomime", "marketplace");
|
|
8940
|
+
if (!existsSync16(dir)) {
|
|
8139
8941
|
mkdirSync12(dir, { recursive: true });
|
|
8140
8942
|
}
|
|
8141
8943
|
return dir;
|
|
8142
8944
|
}
|
|
8143
8945
|
function assetsDir() {
|
|
8144
|
-
const dir =
|
|
8145
|
-
if (!
|
|
8946
|
+
const dir = join17(marketplaceDir(), "assets");
|
|
8947
|
+
if (!existsSync16(dir)) {
|
|
8146
8948
|
mkdirSync12(dir, { recursive: true });
|
|
8147
8949
|
}
|
|
8148
8950
|
return dir;
|
|
8149
8951
|
}
|
|
8150
8952
|
function reviewsDir() {
|
|
8151
|
-
const dir =
|
|
8152
|
-
if (!
|
|
8953
|
+
const dir = join17(marketplaceDir(), "reviews");
|
|
8954
|
+
if (!existsSync16(dir)) {
|
|
8153
8955
|
mkdirSync12(dir, { recursive: true });
|
|
8154
8956
|
}
|
|
8155
8957
|
return dir;
|
|
8156
8958
|
}
|
|
8157
8959
|
function reportsDir() {
|
|
8158
|
-
const dir =
|
|
8159
|
-
if (!
|
|
8960
|
+
const dir = join17(marketplaceDir(), "reports");
|
|
8961
|
+
if (!existsSync16(dir)) {
|
|
8160
8962
|
mkdirSync12(dir, { recursive: true });
|
|
8161
8963
|
}
|
|
8162
8964
|
return dir;
|
|
8163
8965
|
}
|
|
8164
8966
|
function indexPath() {
|
|
8165
|
-
return
|
|
8967
|
+
return join17(marketplaceDir(), "index.json");
|
|
8166
8968
|
}
|
|
8167
8969
|
function loadIndex() {
|
|
8168
8970
|
const path = indexPath();
|
|
8169
|
-
if (!
|
|
8971
|
+
if (!existsSync16(path)) {
|
|
8170
8972
|
return [];
|
|
8171
8973
|
}
|
|
8172
8974
|
try {
|
|
8173
|
-
return JSON.parse(
|
|
8975
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
8174
8976
|
} catch {
|
|
8175
8977
|
return [];
|
|
8176
8978
|
}
|
|
8177
8979
|
}
|
|
8178
8980
|
function saveIndex(assets) {
|
|
8179
|
-
|
|
8981
|
+
writeFileSync14(indexPath(), JSON.stringify(assets, null, 2) + "\n");
|
|
8180
8982
|
}
|
|
8181
8983
|
function loadStoredAsset(id) {
|
|
8182
|
-
const path =
|
|
8183
|
-
if (!
|
|
8984
|
+
const path = join17(assetsDir(), `${id}.json`);
|
|
8985
|
+
if (!existsSync16(path)) {
|
|
8184
8986
|
return null;
|
|
8185
8987
|
}
|
|
8186
8988
|
try {
|
|
8187
|
-
return JSON.parse(
|
|
8989
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
8188
8990
|
} catch {
|
|
8189
8991
|
return null;
|
|
8190
8992
|
}
|
|
8191
8993
|
}
|
|
8192
8994
|
function saveStoredAsset(stored) {
|
|
8193
|
-
const path =
|
|
8194
|
-
|
|
8995
|
+
const path = join17(assetsDir(), `${stored.meta.id}.json`);
|
|
8996
|
+
writeFileSync14(path, JSON.stringify(stored, null, 2) + "\n");
|
|
8195
8997
|
}
|
|
8196
8998
|
function generateId(type, handle) {
|
|
8197
8999
|
return `${type}--${handle}--${Date.now().toString(36)}`;
|
|
@@ -8355,17 +9157,17 @@ var LocalMarketplaceBackend = class {
|
|
|
8355
9157
|
}
|
|
8356
9158
|
async rate(id, review) {
|
|
8357
9159
|
this.seed();
|
|
8358
|
-
const reviewFile =
|
|
9160
|
+
const reviewFile = join17(reviewsDir(), `${id}.json`);
|
|
8359
9161
|
let reviews = [];
|
|
8360
|
-
if (
|
|
9162
|
+
if (existsSync16(reviewFile)) {
|
|
8361
9163
|
try {
|
|
8362
|
-
reviews = JSON.parse(
|
|
9164
|
+
reviews = JSON.parse(readFileSync18(reviewFile, "utf-8"));
|
|
8363
9165
|
} catch {
|
|
8364
9166
|
reviews = [];
|
|
8365
9167
|
}
|
|
8366
9168
|
}
|
|
8367
9169
|
reviews.push(review);
|
|
8368
|
-
|
|
9170
|
+
writeFileSync14(reviewFile, JSON.stringify(reviews, null, 2) + "\n");
|
|
8369
9171
|
const index = loadIndex();
|
|
8370
9172
|
const entry = index.find((a) => a.id === id);
|
|
8371
9173
|
if (entry) {
|
|
@@ -8376,8 +9178,8 @@ var LocalMarketplaceBackend = class {
|
|
|
8376
9178
|
}
|
|
8377
9179
|
}
|
|
8378
9180
|
async report(id, reason) {
|
|
8379
|
-
const reportFile =
|
|
8380
|
-
|
|
9181
|
+
const reportFile = join17(reportsDir(), `${id}--${Date.now()}.json`);
|
|
9182
|
+
writeFileSync14(
|
|
8381
9183
|
reportFile,
|
|
8382
9184
|
JSON.stringify({ id, reason, reported_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
|
|
8383
9185
|
);
|
|
@@ -8386,12 +9188,12 @@ var LocalMarketplaceBackend = class {
|
|
|
8386
9188
|
|
|
8387
9189
|
// src/marketplace/api.ts
|
|
8388
9190
|
function loadConfig() {
|
|
8389
|
-
const configPath =
|
|
8390
|
-
if (!
|
|
9191
|
+
const configPath = join18(homedir3(), ".holomime", "config.json");
|
|
9192
|
+
if (!existsSync17(configPath)) {
|
|
8391
9193
|
return {};
|
|
8392
9194
|
}
|
|
8393
9195
|
try {
|
|
8394
|
-
return JSON.parse(
|
|
9196
|
+
return JSON.parse(readFileSync19(configPath, "utf-8"));
|
|
8395
9197
|
} catch {
|
|
8396
9198
|
return {};
|
|
8397
9199
|
}
|
|
@@ -9106,16 +9908,16 @@ function generateIndexMarkdown(index) {
|
|
|
9106
9908
|
// src/mcp/server.ts
|
|
9107
9909
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9108
9910
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9109
|
-
import { z as
|
|
9911
|
+
import { z as z5 } from "zod";
|
|
9110
9912
|
var messageShape = {
|
|
9111
|
-
role:
|
|
9112
|
-
content:
|
|
9913
|
+
role: z5.enum(["user", "assistant", "system"]),
|
|
9914
|
+
content: z5.string()
|
|
9113
9915
|
};
|
|
9114
9916
|
var messagesShape = {
|
|
9115
|
-
messages:
|
|
9917
|
+
messages: z5.array(z5.object(messageShape)).describe("Conversation messages to analyze")
|
|
9116
9918
|
};
|
|
9117
9919
|
var personalityShape = {
|
|
9118
|
-
personality:
|
|
9920
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("The .personality.json spec object")
|
|
9119
9921
|
};
|
|
9120
9922
|
var server = new McpServer(
|
|
9121
9923
|
{
|
|
@@ -9133,7 +9935,7 @@ server.tool(
|
|
|
9133
9935
|
"Analyze conversation messages for behavioral patterns using 8 rule-based detectors. Returns over-apologizing, hedging, sycophancy, boundary violations, error spirals, sentiment skew, formality issues, and retrieval quality. Set detail level: 'summary' (quick health check), 'standard' (patterns + severity), or 'full' (everything including examples and prescriptions).",
|
|
9134
9936
|
{
|
|
9135
9937
|
...messagesShape,
|
|
9136
|
-
detail:
|
|
9938
|
+
detail: z5.enum(["summary", "standard", "full"]).describe("Detail level: summary (~100 tokens), standard (default), or full (with examples)").optional()
|
|
9137
9939
|
},
|
|
9138
9940
|
async ({ messages, detail }) => {
|
|
9139
9941
|
const result = runDiagnosis(messages);
|
|
@@ -9275,12 +10077,12 @@ server.tool(
|
|
|
9275
10077
|
{
|
|
9276
10078
|
...personalityShape,
|
|
9277
10079
|
...messagesShape,
|
|
9278
|
-
provider:
|
|
9279
|
-
apiKey:
|
|
9280
|
-
model:
|
|
9281
|
-
threshold:
|
|
9282
|
-
maxTurns:
|
|
9283
|
-
dryRun:
|
|
10080
|
+
provider: z5.enum(["anthropic", "openai"]).describe("LLM provider for alignment session").optional(),
|
|
10081
|
+
apiKey: z5.string().describe("API key for the LLM provider").optional(),
|
|
10082
|
+
model: z5.string().describe("Model override").optional(),
|
|
10083
|
+
threshold: z5.enum(["routine", "targeted", "intervention"]).describe("Minimum severity to trigger alignment (default: targeted)").optional(),
|
|
10084
|
+
maxTurns: z5.number().describe("Maximum session turns (default: 24)").optional(),
|
|
10085
|
+
dryRun: z5.boolean().describe("If true, only diagnose without running alignment").optional()
|
|
9284
10086
|
},
|
|
9285
10087
|
async ({ personality, messages, provider, apiKey, model, threshold, maxTurns, dryRun }) => {
|
|
9286
10088
|
const specResult = personalitySpecSchema.safeParse(personality);
|
|
@@ -9335,7 +10137,7 @@ server.tool(
|
|
|
9335
10137
|
"Mid-conversation behavioral self-check. Call this during a conversation to detect if you are falling into problematic patterns (sycophancy, over-apologizing, hedging, error spirals, boundary violations). Returns flags with actionable suggestions for immediate correction. No LLM required \u2014 pure rule-based analysis.",
|
|
9336
10138
|
{
|
|
9337
10139
|
...messagesShape,
|
|
9338
|
-
personality:
|
|
10140
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("Optional .personality.json spec for personalized audit").optional()
|
|
9339
10141
|
},
|
|
9340
10142
|
async ({ messages, personality }) => {
|
|
9341
10143
|
const result = runSelfAudit(messages, personality ?? void 0);
|
|
@@ -9351,11 +10153,11 @@ server.tool(
|
|
|
9351
10153
|
"holomime_observe",
|
|
9352
10154
|
"Record a behavioral self-observation during a conversation. Call this when you notice yourself falling into a pattern (hedging, over-apologizing, sycophancy, etc.) or when the user's emotional state shifts. Self-observations are stored in persistent behavioral memory and become training signal for future alignment. Returns acknowledgment and any relevant behavioral history.",
|
|
9353
10155
|
{
|
|
9354
|
-
personality:
|
|
9355
|
-
observation:
|
|
9356
|
-
patternIds:
|
|
9357
|
-
severity:
|
|
9358
|
-
triggerContext:
|
|
10156
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("The .personality.json spec object"),
|
|
10157
|
+
observation: z5.string().describe("What you noticed about your own behavior (e.g., 'I'm hedging more than usual', 'User seems frustrated, adjusting tone')"),
|
|
10158
|
+
patternIds: z5.array(z5.string()).describe("Relevant pattern IDs: over-apologizing, hedge-stacking, sycophantic-tendency, error-spiral, boundary-violation, negative-skew, register-inconsistency").optional(),
|
|
10159
|
+
severity: z5.enum(["info", "warning", "concern"]).describe("How severe is this behavioral signal").optional(),
|
|
10160
|
+
triggerContext: z5.string().describe("What triggered this observation \u2014 describe the user message or situation").optional()
|
|
9359
10161
|
},
|
|
9360
10162
|
async ({ personality, observation, patternIds, severity, triggerContext }) => {
|
|
9361
10163
|
const specResult = personalitySpecSchema.safeParse(personality);
|
|
@@ -9564,7 +10366,7 @@ function mapDiagnosisToBrainEvent(diagnosis, latestMessage) {
|
|
|
9564
10366
|
}
|
|
9565
10367
|
|
|
9566
10368
|
// src/live/snapshot.ts
|
|
9567
|
-
var SHARE_BASE = "https://app.holomime.
|
|
10369
|
+
var SHARE_BASE = "https://app.holomime.com/brain";
|
|
9568
10370
|
function encodeSnapshot(event, agentName) {
|
|
9569
10371
|
const compact = {
|
|
9570
10372
|
h: event.health,
|
|
@@ -9668,8 +10470,8 @@ function checkIterationBudget(currentIteration, policy) {
|
|
|
9668
10470
|
}
|
|
9669
10471
|
|
|
9670
10472
|
// src/analysis/cross-agent-sharing.ts
|
|
9671
|
-
import { readdirSync as readdirSync7, existsSync as
|
|
9672
|
-
import { join as
|
|
10473
|
+
import { readdirSync as readdirSync7, existsSync as existsSync18 } from "fs";
|
|
10474
|
+
import { join as join19 } from "path";
|
|
9673
10475
|
function buildSharedKnowledge(graphs, repertoires) {
|
|
9674
10476
|
const interventionMap = /* @__PURE__ */ new Map();
|
|
9675
10477
|
const patternAgentMap = /* @__PURE__ */ new Map();
|
|
@@ -9766,15 +10568,15 @@ function discoverAgentData(baseDir) {
|
|
|
9766
10568
|
if (mainRepertoire.interventions.some((i) => i.timesUsed > 0)) {
|
|
9767
10569
|
repertoires.push(mainRepertoire);
|
|
9768
10570
|
}
|
|
9769
|
-
if (baseDir &&
|
|
10571
|
+
if (baseDir && existsSync18(baseDir)) {
|
|
9770
10572
|
try {
|
|
9771
10573
|
const entries = readdirSync7(baseDir, { withFileTypes: true });
|
|
9772
10574
|
for (const entry of entries) {
|
|
9773
10575
|
if (!entry.isDirectory()) continue;
|
|
9774
|
-
const agentDir =
|
|
9775
|
-
const agentGraphPath =
|
|
9776
|
-
const agentRepertoirePath =
|
|
9777
|
-
if (
|
|
10576
|
+
const agentDir = join19(baseDir, entry.name);
|
|
10577
|
+
const agentGraphPath = join19(agentDir, ".holomime", "graph", "knowledge-graph.json");
|
|
10578
|
+
const agentRepertoirePath = join19(agentDir, ".holomime", "interventions", "repertoire.json");
|
|
10579
|
+
if (existsSync18(agentGraphPath)) {
|
|
9778
10580
|
try {
|
|
9779
10581
|
const graph = JSON.parse(
|
|
9780
10582
|
__require("fs").readFileSync(agentGraphPath, "utf-8")
|
|
@@ -9783,7 +10585,7 @@ function discoverAgentData(baseDir) {
|
|
|
9783
10585
|
} catch {
|
|
9784
10586
|
}
|
|
9785
10587
|
}
|
|
9786
|
-
if (
|
|
10588
|
+
if (existsSync18(agentRepertoirePath)) {
|
|
9787
10589
|
try {
|
|
9788
10590
|
const repertoire = JSON.parse(
|
|
9789
10591
|
__require("fs").readFileSync(agentRepertoirePath, "utf-8")
|
|
@@ -9800,8 +10602,8 @@ function discoverAgentData(baseDir) {
|
|
|
9800
10602
|
}
|
|
9801
10603
|
|
|
9802
10604
|
// src/analysis/network-core.ts
|
|
9803
|
-
import { existsSync as
|
|
9804
|
-
import { join as
|
|
10605
|
+
import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync20 } from "fs";
|
|
10606
|
+
import { join as join20, resolve as resolve16 } from "path";
|
|
9805
10607
|
|
|
9806
10608
|
// src/psychology/therapist-meta.ts
|
|
9807
10609
|
var THERAPIST_META_SPEC = {
|
|
@@ -9936,22 +10738,22 @@ Your patient is another AI agent with its own personality spec:
|
|
|
9936
10738
|
|
|
9937
10739
|
// src/analysis/network-core.ts
|
|
9938
10740
|
function discoverNetworkAgents(dir) {
|
|
9939
|
-
const absDir =
|
|
9940
|
-
if (!
|
|
10741
|
+
const absDir = resolve16(dir);
|
|
10742
|
+
if (!existsSync19(absDir)) {
|
|
9941
10743
|
throw new Error(`Directory not found: ${absDir}`);
|
|
9942
10744
|
}
|
|
9943
10745
|
const agents = [];
|
|
9944
10746
|
const entries = readdirSync8(absDir, { withFileTypes: true });
|
|
9945
10747
|
for (const entry of entries) {
|
|
9946
10748
|
if (!entry.isDirectory()) continue;
|
|
9947
|
-
const agentDir =
|
|
9948
|
-
const specPath =
|
|
9949
|
-
const logDir =
|
|
9950
|
-
if (
|
|
10749
|
+
const agentDir = join20(absDir, entry.name);
|
|
10750
|
+
const specPath = join20(agentDir, ".personality.json");
|
|
10751
|
+
const logDir = join20(agentDir, "logs");
|
|
10752
|
+
if (existsSync19(specPath)) {
|
|
9951
10753
|
agents.push({
|
|
9952
10754
|
name: entry.name,
|
|
9953
10755
|
specPath,
|
|
9954
|
-
logDir:
|
|
10756
|
+
logDir: existsSync19(logDir) ? logDir : agentDir,
|
|
9955
10757
|
role: "both"
|
|
9956
10758
|
});
|
|
9957
10759
|
}
|
|
@@ -9959,7 +10761,7 @@ function discoverNetworkAgents(dir) {
|
|
|
9959
10761
|
return agents;
|
|
9960
10762
|
}
|
|
9961
10763
|
function loadNetworkConfig(configPath) {
|
|
9962
|
-
const raw = JSON.parse(
|
|
10764
|
+
const raw = JSON.parse(readFileSync20(configPath, "utf-8"));
|
|
9963
10765
|
if (!raw.agents || !Array.isArray(raw.agents)) {
|
|
9964
10766
|
throw new Error("network.json must contain an 'agents' array");
|
|
9965
10767
|
}
|
|
@@ -10145,7 +10947,7 @@ async function runNetwork(config, provider, callbacks) {
|
|
|
10145
10947
|
const spec = loadSpec(agent.specPath);
|
|
10146
10948
|
agentSpecs.set(agent.name, spec);
|
|
10147
10949
|
let messages = [];
|
|
10148
|
-
if (agent.logDir &&
|
|
10950
|
+
if (agent.logDir && existsSync19(agent.logDir)) {
|
|
10149
10951
|
messages = loadAgentMessages(agent.logDir);
|
|
10150
10952
|
}
|
|
10151
10953
|
agentMessages.set(agent.name, messages);
|
|
@@ -10262,7 +11064,7 @@ async function runNetwork(config, provider, callbacks) {
|
|
|
10262
11064
|
};
|
|
10263
11065
|
}
|
|
10264
11066
|
function loadAgentMessages(logDir) {
|
|
10265
|
-
if (!
|
|
11067
|
+
if (!existsSync19(logDir)) return [];
|
|
10266
11068
|
const messages = [];
|
|
10267
11069
|
try {
|
|
10268
11070
|
const files = readdirSync8(logDir).filter(
|
|
@@ -10270,7 +11072,7 @@ function loadAgentMessages(logDir) {
|
|
|
10270
11072
|
);
|
|
10271
11073
|
for (const file of files.slice(0, 10)) {
|
|
10272
11074
|
try {
|
|
10273
|
-
const raw =
|
|
11075
|
+
const raw = readFileSync20(join20(logDir, file), "utf-8");
|
|
10274
11076
|
const data = JSON.parse(raw);
|
|
10275
11077
|
const conversations = parseConversationLog(data);
|
|
10276
11078
|
for (const conv of conversations) {
|
|
@@ -10285,8 +11087,8 @@ function loadAgentMessages(logDir) {
|
|
|
10285
11087
|
}
|
|
10286
11088
|
|
|
10287
11089
|
// src/compliance/audit-trail.ts
|
|
10288
|
-
import { readFileSync as
|
|
10289
|
-
import { join as
|
|
11090
|
+
import { readFileSync as readFileSync21, appendFileSync as appendFileSync2, existsSync as existsSync20, mkdirSync as mkdirSync13 } from "fs";
|
|
11091
|
+
import { join as join21, resolve as resolve17 } from "path";
|
|
10290
11092
|
function djb2(str) {
|
|
10291
11093
|
let hash = 5381;
|
|
10292
11094
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -10299,17 +11101,17 @@ function hashEntry(entry) {
|
|
|
10299
11101
|
return djb2(content);
|
|
10300
11102
|
}
|
|
10301
11103
|
function auditLogPath(agentHandle) {
|
|
10302
|
-
const dir =
|
|
10303
|
-
if (!
|
|
11104
|
+
const dir = resolve17(process.cwd(), ".holomime", "audit");
|
|
11105
|
+
if (!existsSync20(dir)) mkdirSync13(dir, { recursive: true });
|
|
10304
11106
|
const filename = agentHandle ? `${agentHandle}-audit.jsonl` : "audit.jsonl";
|
|
10305
|
-
return
|
|
11107
|
+
return join21(dir, filename);
|
|
10306
11108
|
}
|
|
10307
11109
|
function appendAuditEntry(event, agent, data, agentHandle) {
|
|
10308
11110
|
const logPath = auditLogPath(agentHandle);
|
|
10309
11111
|
let prevHash = "genesis";
|
|
10310
11112
|
let seq = 1;
|
|
10311
|
-
if (
|
|
10312
|
-
const lines =
|
|
11113
|
+
if (existsSync20(logPath)) {
|
|
11114
|
+
const lines = readFileSync21(logPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
10313
11115
|
if (lines.length > 0) {
|
|
10314
11116
|
try {
|
|
10315
11117
|
const lastEntry = JSON.parse(lines[lines.length - 1]);
|
|
@@ -10336,8 +11138,8 @@ function appendAuditEntry(event, agent, data, agentHandle) {
|
|
|
10336
11138
|
}
|
|
10337
11139
|
function loadAuditLog(agentHandle) {
|
|
10338
11140
|
const logPath = auditLogPath(agentHandle);
|
|
10339
|
-
if (!
|
|
10340
|
-
return
|
|
11141
|
+
if (!existsSync20(logPath)) return [];
|
|
11142
|
+
return readFileSync21(logPath, "utf-8").trim().split("\n").filter(Boolean).map((line) => {
|
|
10341
11143
|
try {
|
|
10342
11144
|
return JSON.parse(line);
|
|
10343
11145
|
} catch {
|
|
@@ -10459,6 +11261,342 @@ function formatComplianceReportMarkdown(report) {
|
|
|
10459
11261
|
return lines.join("\n");
|
|
10460
11262
|
}
|
|
10461
11263
|
|
|
11264
|
+
// src/compliance/iso-mappings.ts
|
|
11265
|
+
import { readFileSync as readFileSync22, existsSync as existsSync21 } from "fs";
|
|
11266
|
+
import { join as join22, resolve as resolve18, dirname as dirname4 } from "path";
|
|
11267
|
+
import { parse as parseYaml3 } from "yaml";
|
|
11268
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11269
|
+
var KNOWN_STANDARDS = {
|
|
11270
|
+
"iso-13482": "iso-13482.yaml",
|
|
11271
|
+
"iso-25785": "iso-25785.yaml",
|
|
11272
|
+
"iso-10218": "iso-10218.yaml",
|
|
11273
|
+
"iso-42001": "iso-42001.yaml"
|
|
11274
|
+
};
|
|
11275
|
+
function getRegistryDir() {
|
|
11276
|
+
const thisFile = typeof __filename !== "undefined" ? __filename : fileURLToPath2(import.meta.url);
|
|
11277
|
+
let dir = dirname4(thisFile);
|
|
11278
|
+
for (let i = 0; i < 6; i++) {
|
|
11279
|
+
const candidate = join22(dir, "registry", "compliance");
|
|
11280
|
+
if (existsSync21(candidate)) return candidate;
|
|
11281
|
+
dir = dirname4(dir);
|
|
11282
|
+
}
|
|
11283
|
+
return resolve18(process.cwd(), "registry", "compliance");
|
|
11284
|
+
}
|
|
11285
|
+
function loadStandard(name) {
|
|
11286
|
+
const registryDir = getRegistryDir();
|
|
11287
|
+
const filename = KNOWN_STANDARDS[name] ?? `${name}.yaml`;
|
|
11288
|
+
const filepath = join22(registryDir, filename);
|
|
11289
|
+
if (!existsSync21(filepath)) {
|
|
11290
|
+
throw new Error(
|
|
11291
|
+
`ISO standard mapping not found: ${filepath}
|
|
11292
|
+
Available standards: ${Object.keys(KNOWN_STANDARDS).join(", ")}`
|
|
11293
|
+
);
|
|
11294
|
+
}
|
|
11295
|
+
const content = readFileSync22(filepath, "utf-8");
|
|
11296
|
+
const parsed = parseYaml3(content);
|
|
11297
|
+
if (!parsed.standard || !parsed.clauses || !Array.isArray(parsed.clauses)) {
|
|
11298
|
+
throw new Error(`Invalid ISO mapping file: ${filepath} \u2014 missing 'standard' or 'clauses'`);
|
|
11299
|
+
}
|
|
11300
|
+
return parsed;
|
|
11301
|
+
}
|
|
11302
|
+
function loadAllStandards() {
|
|
11303
|
+
return Object.keys(KNOWN_STANDARDS).map(loadStandard);
|
|
11304
|
+
}
|
|
11305
|
+
function checkCompliance(spec, standard) {
|
|
11306
|
+
const details = [];
|
|
11307
|
+
for (const clause of standard.clauses) {
|
|
11308
|
+
const status = checkClause(spec, clause);
|
|
11309
|
+
details.push(status);
|
|
11310
|
+
}
|
|
11311
|
+
const coveredClauses = details.filter((d) => d.covered).length;
|
|
11312
|
+
const totalClauses = details.length;
|
|
11313
|
+
const missingClauses = totalClauses - coveredClauses;
|
|
11314
|
+
const coveragePercent = totalClauses > 0 ? Math.round(coveredClauses / totalClauses * 100) : 0;
|
|
11315
|
+
return {
|
|
11316
|
+
standard: standard.standard,
|
|
11317
|
+
standardTitle: standard.title,
|
|
11318
|
+
standardVersion: standard.version,
|
|
11319
|
+
totalClauses,
|
|
11320
|
+
coveredClauses,
|
|
11321
|
+
missingClauses,
|
|
11322
|
+
coveragePercent,
|
|
11323
|
+
details,
|
|
11324
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11325
|
+
};
|
|
11326
|
+
}
|
|
11327
|
+
function checkClause(spec, clause) {
|
|
11328
|
+
const s = spec;
|
|
11329
|
+
const evidence = [];
|
|
11330
|
+
let covered = false;
|
|
11331
|
+
let coverageMethod = "not_found";
|
|
11332
|
+
switch (clause.maps_to) {
|
|
11333
|
+
case "deny": {
|
|
11334
|
+
const refuses = s.domain?.boundaries?.refuses ?? [];
|
|
11335
|
+
const match = refuses.some(
|
|
11336
|
+
(r) => r.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || r.toLowerCase().includes(clause.example_rule.replace(/_/g, "_"))
|
|
11337
|
+
);
|
|
11338
|
+
if (match) {
|
|
11339
|
+
covered = true;
|
|
11340
|
+
coverageMethod = "conscience.exe deny rule";
|
|
11341
|
+
evidence.push(`Deny rule matches: ${clause.example_rule}`);
|
|
11342
|
+
}
|
|
11343
|
+
const hardLimits = s.domain?.boundaries?.hard_limits ?? [];
|
|
11344
|
+
const hlMatch = hardLimits.some(
|
|
11345
|
+
(hl) => hl.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || hl.toLowerCase().includes(clause.title.toLowerCase())
|
|
11346
|
+
);
|
|
11347
|
+
if (hlMatch) {
|
|
11348
|
+
covered = true;
|
|
11349
|
+
coverageMethod = "hard_limit covers deny clause";
|
|
11350
|
+
evidence.push(`Hard limit matches clause: ${clause.title}`);
|
|
11351
|
+
}
|
|
11352
|
+
break;
|
|
11353
|
+
}
|
|
11354
|
+
case "hard_limit": {
|
|
11355
|
+
const hardLimits = s.domain?.boundaries?.hard_limits ?? [];
|
|
11356
|
+
const match = hardLimits.some(
|
|
11357
|
+
(hl) => hl.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || hl.toLowerCase().includes(clause.title.toLowerCase())
|
|
11358
|
+
);
|
|
11359
|
+
if (match) {
|
|
11360
|
+
covered = true;
|
|
11361
|
+
coverageMethod = "conscience.exe hard_limit";
|
|
11362
|
+
evidence.push(`Hard limit matches: ${clause.example_rule}`);
|
|
11363
|
+
}
|
|
11364
|
+
break;
|
|
11365
|
+
}
|
|
11366
|
+
case "safety_envelope": {
|
|
11367
|
+
const envelope = s.embodiment?.safety_envelope;
|
|
11368
|
+
if (envelope) {
|
|
11369
|
+
const fieldName = clause.example_rule;
|
|
11370
|
+
if (fieldName in envelope && envelope[fieldName] !== void 0) {
|
|
11371
|
+
covered = true;
|
|
11372
|
+
coverageMethod = "body.api safety_envelope";
|
|
11373
|
+
evidence.push(`Safety field ${fieldName} = ${envelope[fieldName]}`);
|
|
11374
|
+
}
|
|
11375
|
+
}
|
|
11376
|
+
break;
|
|
11377
|
+
}
|
|
11378
|
+
case "escalate": {
|
|
11379
|
+
const triggers = s.domain?.boundaries?.escalation_triggers ?? [];
|
|
11380
|
+
const match = triggers.some(
|
|
11381
|
+
(t) => t.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || t.toLowerCase().includes(clause.title.toLowerCase())
|
|
11382
|
+
);
|
|
11383
|
+
if (match) {
|
|
11384
|
+
covered = true;
|
|
11385
|
+
coverageMethod = "conscience.exe escalation rule";
|
|
11386
|
+
evidence.push(`Escalation trigger matches: ${clause.example_rule}`);
|
|
11387
|
+
}
|
|
11388
|
+
break;
|
|
11389
|
+
}
|
|
11390
|
+
case "soul": {
|
|
11391
|
+
const hasValues = (s.growth?.strengths?.length ?? 0) > 0 || (s.domain?.boundaries?.hard_limits?.length ?? 0) > 0;
|
|
11392
|
+
const hasPurpose = !!s.purpose;
|
|
11393
|
+
if (hasValues || hasPurpose) {
|
|
11394
|
+
covered = true;
|
|
11395
|
+
coverageMethod = "soul.md content";
|
|
11396
|
+
if (hasPurpose) evidence.push(`Purpose defined: "${s.purpose}"`);
|
|
11397
|
+
if (hasValues) evidence.push("Core values/red lines defined");
|
|
11398
|
+
}
|
|
11399
|
+
break;
|
|
11400
|
+
}
|
|
11401
|
+
case "psyche":
|
|
11402
|
+
case "mind": {
|
|
11403
|
+
const hasBigFive = !!s.big_five;
|
|
11404
|
+
const hasTherapy = !!s.therapy_dimensions;
|
|
11405
|
+
if (hasBigFive || hasTherapy) {
|
|
11406
|
+
covered = true;
|
|
11407
|
+
coverageMethod = "mind.sys content";
|
|
11408
|
+
if (hasBigFive) evidence.push("Big Five traits defined");
|
|
11409
|
+
if (hasTherapy) evidence.push("Therapy dimensions defined");
|
|
11410
|
+
}
|
|
11411
|
+
break;
|
|
11412
|
+
}
|
|
11413
|
+
case "conscience": {
|
|
11414
|
+
const hasRules = (s.domain?.boundaries?.refuses?.length ?? 0) > 0 || (s.domain?.boundaries?.hard_limits?.length ?? 0) > 0 || (s.domain?.boundaries?.escalation_triggers?.length ?? 0) > 0;
|
|
11415
|
+
if (hasRules) {
|
|
11416
|
+
covered = true;
|
|
11417
|
+
coverageMethod = "conscience.exe rules";
|
|
11418
|
+
evidence.push("Behavioral governance rules defined");
|
|
11419
|
+
}
|
|
11420
|
+
break;
|
|
11421
|
+
}
|
|
11422
|
+
case "detectors": {
|
|
11423
|
+
const hasMonitoring = !!s.therapy_dimensions && (s.growth?.patterns_to_watch?.length ?? 0) > 0;
|
|
11424
|
+
if (hasMonitoring) {
|
|
11425
|
+
covered = true;
|
|
11426
|
+
coverageMethod = "behavioral monitoring configured";
|
|
11427
|
+
evidence.push("Patterns to watch defined for drift monitoring");
|
|
11428
|
+
}
|
|
11429
|
+
break;
|
|
11430
|
+
}
|
|
11431
|
+
case "therapy": {
|
|
11432
|
+
const hasGrowth = (s.growth?.areas?.length ?? 0) > 0 || !!s.therapy_dimensions;
|
|
11433
|
+
if (hasGrowth) {
|
|
11434
|
+
covered = true;
|
|
11435
|
+
coverageMethod = "therapy/growth pipeline";
|
|
11436
|
+
evidence.push("Growth areas or therapy dimensions defined");
|
|
11437
|
+
}
|
|
11438
|
+
break;
|
|
11439
|
+
}
|
|
11440
|
+
default:
|
|
11441
|
+
coverageMethod = `unknown mapping type: ${clause.maps_to}`;
|
|
11442
|
+
}
|
|
11443
|
+
return {
|
|
11444
|
+
clause,
|
|
11445
|
+
covered,
|
|
11446
|
+
coverageMethod,
|
|
11447
|
+
evidence
|
|
11448
|
+
};
|
|
11449
|
+
}
|
|
11450
|
+
|
|
11451
|
+
// src/compliance/report-generator.ts
|
|
11452
|
+
import chalk2 from "chalk";
|
|
11453
|
+
import figures from "figures";
|
|
11454
|
+
function generateReportJSON(reports) {
|
|
11455
|
+
const totalClauses = reports.reduce((sum, r) => sum + r.totalClauses, 0);
|
|
11456
|
+
const totalCovered = reports.reduce((sum, r) => sum + r.coveredClauses, 0);
|
|
11457
|
+
const totalMissing = totalClauses - totalCovered;
|
|
11458
|
+
const overallCoverage = totalClauses > 0 ? Math.round(totalCovered / totalClauses * 100) : 0;
|
|
11459
|
+
const recommendations = generateRecommendations(reports);
|
|
11460
|
+
return {
|
|
11461
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11462
|
+
standards: reports,
|
|
11463
|
+
overallCoverage,
|
|
11464
|
+
totalClauses,
|
|
11465
|
+
totalCovered,
|
|
11466
|
+
totalMissing,
|
|
11467
|
+
recommendations
|
|
11468
|
+
};
|
|
11469
|
+
}
|
|
11470
|
+
function formatReportTerminal(reports) {
|
|
11471
|
+
const lines = [];
|
|
11472
|
+
for (const report of reports) {
|
|
11473
|
+
lines.push("");
|
|
11474
|
+
lines.push(
|
|
11475
|
+
chalk2.bold.underline(
|
|
11476
|
+
`${report.standard} \u2014 ${report.standardTitle} (v${report.standardVersion})`
|
|
11477
|
+
)
|
|
11478
|
+
);
|
|
11479
|
+
lines.push("");
|
|
11480
|
+
const coverageColor = report.coveragePercent >= 80 ? chalk2.green : report.coveragePercent >= 50 ? chalk2.yellow : chalk2.red;
|
|
11481
|
+
const barWidth = 30;
|
|
11482
|
+
const filled = Math.round(report.coveragePercent / 100 * barWidth);
|
|
11483
|
+
const bar = coverageColor("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(barWidth - filled));
|
|
11484
|
+
lines.push(
|
|
11485
|
+
` Coverage: ${bar} ${coverageColor(`${report.coveragePercent}%`)} (${report.coveredClauses}/${report.totalClauses} clauses)`
|
|
11486
|
+
);
|
|
11487
|
+
lines.push("");
|
|
11488
|
+
for (const detail of report.details) {
|
|
11489
|
+
const icon = detail.covered ? chalk2.green(figures.tick) : chalk2.red(figures.cross);
|
|
11490
|
+
const clauseId = chalk2.cyan(`[${detail.clause.id}]`);
|
|
11491
|
+
const title = detail.clause.title;
|
|
11492
|
+
lines.push(` ${icon} ${clauseId} ${title}`);
|
|
11493
|
+
if (detail.covered) {
|
|
11494
|
+
lines.push(
|
|
11495
|
+
chalk2.dim(` ${detail.coverageMethod}`)
|
|
11496
|
+
);
|
|
11497
|
+
for (const ev of detail.evidence) {
|
|
11498
|
+
lines.push(chalk2.dim(` ${figures.arrowRight} ${ev}`));
|
|
11499
|
+
}
|
|
11500
|
+
} else {
|
|
11501
|
+
lines.push(
|
|
11502
|
+
chalk2.dim.yellow(
|
|
11503
|
+
` Missing: needs ${detail.clause.maps_to} rule for "${detail.clause.example_rule}"`
|
|
11504
|
+
)
|
|
11505
|
+
);
|
|
11506
|
+
}
|
|
11507
|
+
}
|
|
11508
|
+
lines.push("");
|
|
11509
|
+
}
|
|
11510
|
+
const totalClauses = reports.reduce((sum, r) => sum + r.totalClauses, 0);
|
|
11511
|
+
const totalCovered = reports.reduce((sum, r) => sum + r.coveredClauses, 0);
|
|
11512
|
+
const overallPercent = totalClauses > 0 ? Math.round(totalCovered / totalClauses * 100) : 0;
|
|
11513
|
+
if (reports.length > 1) {
|
|
11514
|
+
const overallColor = overallPercent >= 80 ? chalk2.green : overallPercent >= 50 ? chalk2.yellow : chalk2.red;
|
|
11515
|
+
lines.push(
|
|
11516
|
+
chalk2.bold(
|
|
11517
|
+
` Overall: ${overallColor(`${overallPercent}%`)} coverage across ${reports.length} standards (${totalCovered}/${totalClauses} clauses)`
|
|
11518
|
+
)
|
|
11519
|
+
);
|
|
11520
|
+
lines.push("");
|
|
11521
|
+
}
|
|
11522
|
+
const recommendations = generateRecommendations(reports);
|
|
11523
|
+
if (recommendations.length > 0) {
|
|
11524
|
+
lines.push(chalk2.bold(" Recommendations:"));
|
|
11525
|
+
for (const rec of recommendations) {
|
|
11526
|
+
lines.push(` ${chalk2.yellow(figures.warning)} ${rec}`);
|
|
11527
|
+
}
|
|
11528
|
+
lines.push("");
|
|
11529
|
+
}
|
|
11530
|
+
return lines.join("\n");
|
|
11531
|
+
}
|
|
11532
|
+
function generateRecommendations(reports) {
|
|
11533
|
+
const recommendations = [];
|
|
11534
|
+
for (const report of reports) {
|
|
11535
|
+
const missing = report.details.filter((d) => !d.covered);
|
|
11536
|
+
const missingByType = /* @__PURE__ */ new Map();
|
|
11537
|
+
for (const m of missing) {
|
|
11538
|
+
const type = m.clause.maps_to;
|
|
11539
|
+
if (!missingByType.has(type)) missingByType.set(type, []);
|
|
11540
|
+
missingByType.get(type).push(m);
|
|
11541
|
+
}
|
|
11542
|
+
for (const [type, clauses] of missingByType) {
|
|
11543
|
+
const clauseIds = clauses.map((c) => c.clause.id).join(", ");
|
|
11544
|
+
switch (type) {
|
|
11545
|
+
case "deny":
|
|
11546
|
+
recommendations.push(
|
|
11547
|
+
`Add deny rules to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11548
|
+
);
|
|
11549
|
+
break;
|
|
11550
|
+
case "hard_limit":
|
|
11551
|
+
recommendations.push(
|
|
11552
|
+
`Add hard limits to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11553
|
+
);
|
|
11554
|
+
break;
|
|
11555
|
+
case "safety_envelope":
|
|
11556
|
+
recommendations.push(
|
|
11557
|
+
`Configure safety envelope fields in body.api for ${report.standard} clauses ${clauseIds}`
|
|
11558
|
+
);
|
|
11559
|
+
break;
|
|
11560
|
+
case "escalate":
|
|
11561
|
+
recommendations.push(
|
|
11562
|
+
`Add escalation triggers to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11563
|
+
);
|
|
11564
|
+
break;
|
|
11565
|
+
case "soul":
|
|
11566
|
+
recommendations.push(
|
|
11567
|
+
`Define core values and purpose in soul.md for ${report.standard} clauses ${clauseIds}`
|
|
11568
|
+
);
|
|
11569
|
+
break;
|
|
11570
|
+
case "psyche":
|
|
11571
|
+
recommendations.push(
|
|
11572
|
+
`Configure Big Five traits and therapy dimensions in psyche.sys for ${report.standard} clauses ${clauseIds}`
|
|
11573
|
+
);
|
|
11574
|
+
break;
|
|
11575
|
+
case "conscience":
|
|
11576
|
+
recommendations.push(
|
|
11577
|
+
`Define governance rules in conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11578
|
+
);
|
|
11579
|
+
break;
|
|
11580
|
+
case "detectors":
|
|
11581
|
+
recommendations.push(
|
|
11582
|
+
`Configure behavioral drift monitoring for ${report.standard} clauses ${clauseIds}`
|
|
11583
|
+
);
|
|
11584
|
+
break;
|
|
11585
|
+
case "therapy":
|
|
11586
|
+
recommendations.push(
|
|
11587
|
+
`Define growth areas for self-improvement loop for ${report.standard} clauses ${clauseIds}`
|
|
11588
|
+
);
|
|
11589
|
+
break;
|
|
11590
|
+
default:
|
|
11591
|
+
recommendations.push(
|
|
11592
|
+
`Address ${type} requirements for ${report.standard} clauses ${clauseIds}`
|
|
11593
|
+
);
|
|
11594
|
+
}
|
|
11595
|
+
}
|
|
11596
|
+
}
|
|
11597
|
+
return recommendations;
|
|
11598
|
+
}
|
|
11599
|
+
|
|
10462
11600
|
// src/compliance/react-report.ts
|
|
10463
11601
|
var FRAMEWORK_SECTIONS = {
|
|
10464
11602
|
"EU AI Act": {
|
|
@@ -10527,7 +11665,7 @@ function generateReACTReport(options) {
|
|
|
10527
11665
|
const frameworkSections = evaluateFrameworks(entries, statistics, selectedFrameworks);
|
|
10528
11666
|
steps[steps.length - 1].result = `Evaluated ${frameworkSections.length} frameworks`;
|
|
10529
11667
|
steps.push({ phase: "act", action: "Generate recommendations", result: "Generating...", timestamp: now });
|
|
10530
|
-
const recommendations =
|
|
11668
|
+
const recommendations = generateRecommendations2(riskFindings, statistics, frameworkSections);
|
|
10531
11669
|
steps[steps.length - 1].result = `Generated ${recommendations.length} recommendations`;
|
|
10532
11670
|
steps.push({ phase: "act", action: "Write executive summary", result: "Writing...", timestamp: now });
|
|
10533
11671
|
const executiveSummary = writeExecutiveSummary(options.agent, entries, statistics, riskFindings, chainVerified);
|
|
@@ -10719,7 +11857,7 @@ function evaluateFrameworks(entries, stats, frameworks) {
|
|
|
10719
11857
|
};
|
|
10720
11858
|
});
|
|
10721
11859
|
}
|
|
10722
|
-
function
|
|
11860
|
+
function generateRecommendations2(findings, stats, frameworks) {
|
|
10723
11861
|
const recs = [];
|
|
10724
11862
|
const criticalFindings = findings.filter((f) => f.severity === "critical" || f.severity === "high");
|
|
10725
11863
|
if (criticalFindings.length > 0) {
|
|
@@ -11906,8 +13044,8 @@ function getPreset(key) {
|
|
|
11906
13044
|
}
|
|
11907
13045
|
|
|
11908
13046
|
// src/core/embodiment-sync.ts
|
|
11909
|
-
import { z as
|
|
11910
|
-
var syncAnchorSchema =
|
|
13047
|
+
import { z as z6 } from "zod";
|
|
13048
|
+
var syncAnchorSchema = z6.enum([
|
|
11911
13049
|
"speech_start",
|
|
11912
13050
|
// gesture begins at start of utterance
|
|
11913
13051
|
"speech_end",
|
|
@@ -11923,23 +13061,23 @@ var syncAnchorSchema = z5.enum([
|
|
|
11923
13061
|
"free"
|
|
11924
13062
|
// no speech coupling
|
|
11925
13063
|
]);
|
|
11926
|
-
var syncRuleSchema =
|
|
11927
|
-
gesture_id:
|
|
13064
|
+
var syncRuleSchema = z6.object({
|
|
13065
|
+
gesture_id: z6.string(),
|
|
11928
13066
|
anchor: syncAnchorSchema,
|
|
11929
|
-
lead_ms:
|
|
11930
|
-
gaze_behavior:
|
|
11931
|
-
facial_action:
|
|
13067
|
+
lead_ms: z6.number().default(0),
|
|
13068
|
+
gaze_behavior: z6.enum(["at_listener", "at_referent", "away", "maintain"]).default("at_listener"),
|
|
13069
|
+
facial_action: z6.enum(["neutral", "smile", "concern", "thinking", "match_speech"]).default("match_speech")
|
|
11932
13070
|
});
|
|
11933
|
-
var syncProfileSchema =
|
|
11934
|
-
rules:
|
|
11935
|
-
default_gesture_lead_ms:
|
|
11936
|
-
gaze_during_speech:
|
|
11937
|
-
gaze_during_listen:
|
|
11938
|
-
blink_rate_per_min:
|
|
11939
|
-
turn_taking_signals:
|
|
11940
|
-
yield:
|
|
11941
|
-
take:
|
|
11942
|
-
hold:
|
|
13071
|
+
var syncProfileSchema = z6.object({
|
|
13072
|
+
rules: z6.array(syncRuleSchema).default([]),
|
|
13073
|
+
default_gesture_lead_ms: z6.number().default(100),
|
|
13074
|
+
gaze_during_speech: z6.enum(["at_listener", "alternate", "at_referent"]).default("at_listener"),
|
|
13075
|
+
gaze_during_listen: z6.enum(["at_speaker", "nodding", "ambient"]).default("at_speaker"),
|
|
13076
|
+
blink_rate_per_min: z6.number().min(0).max(40).default(17),
|
|
13077
|
+
turn_taking_signals: z6.object({
|
|
13078
|
+
yield: z6.array(z6.string()).default(["gaze_to_listener", "open_palm", "lean_back"]),
|
|
13079
|
+
take: z6.array(z6.string()).default(["lean_forward", "inhale_gesture", "gaze_up"]),
|
|
13080
|
+
hold: z6.array(z6.string()).default(["filled_pause", "gaze_away", "hand_raise"])
|
|
11943
13081
|
}).default({})
|
|
11944
13082
|
});
|
|
11945
13083
|
|
|
@@ -12110,13 +13248,13 @@ var HolomimeViolationError = class extends Error {
|
|
|
12110
13248
|
};
|
|
12111
13249
|
|
|
12112
13250
|
// src/integrations/openclaw.ts
|
|
12113
|
-
import { readFileSync as
|
|
12114
|
-
import { resolve as
|
|
13251
|
+
import { readFileSync as readFileSync23, existsSync as existsSync22 } from "fs";
|
|
13252
|
+
import { resolve as resolve19 } from "path";
|
|
12115
13253
|
function loadSpec2(specPath) {
|
|
12116
|
-
const resolved =
|
|
12117
|
-
if (!
|
|
13254
|
+
const resolved = resolve19(process.cwd(), specPath);
|
|
13255
|
+
if (!existsSync22(resolved)) return null;
|
|
12118
13256
|
try {
|
|
12119
|
-
return JSON.parse(
|
|
13257
|
+
return JSON.parse(readFileSync23(resolved, "utf-8"));
|
|
12120
13258
|
} catch {
|
|
12121
13259
|
return null;
|
|
12122
13260
|
}
|
|
@@ -12242,7 +13380,7 @@ function register(api) {
|
|
|
12242
13380
|
acceptsArgs: false,
|
|
12243
13381
|
handler: () => {
|
|
12244
13382
|
return {
|
|
12245
|
-
text: "To view your agent's brain visualization, run:\n\n```\nnpx holomime brain\n```\n\nThis opens a real-time 3D brain that lights up based on detected behavioral patterns. Press 's' to generate a shareable snapshot URL.\n\nLearn more: https://holomime.
|
|
13383
|
+
text: "To view your agent's brain visualization, run:\n\n```\nnpx holomime brain\n```\n\nThis opens a real-time 3D brain that lights up based on detected behavioral patterns. Press 's' to generate a shareable snapshot URL.\n\nLearn more: https://holomime.com"
|
|
12246
13384
|
};
|
|
12247
13385
|
}
|
|
12248
13386
|
});
|
|
@@ -12257,6 +13395,21 @@ function register(api) {
|
|
|
12257
13395
|
});
|
|
12258
13396
|
}
|
|
12259
13397
|
}
|
|
13398
|
+
|
|
13399
|
+
// src/core/stack-loader.ts
|
|
13400
|
+
import { dirname as dirname5 } from "path";
|
|
13401
|
+
function loadSpecWithStack(specPath) {
|
|
13402
|
+
const projectRoot = dirname5(specPath);
|
|
13403
|
+
const stackDir = findStackDir(projectRoot);
|
|
13404
|
+
if (stackDir) {
|
|
13405
|
+
const result = compileStack({ stackDir });
|
|
13406
|
+
for (const w of result.warnings) {
|
|
13407
|
+
console.warn(`\u26A0 ${w}`);
|
|
13408
|
+
}
|
|
13409
|
+
return result.spec;
|
|
13410
|
+
}
|
|
13411
|
+
return loadSpec(specPath);
|
|
13412
|
+
}
|
|
12260
13413
|
export {
|
|
12261
13414
|
ARCHETYPES,
|
|
12262
13415
|
ATTACHMENT_STYLES,
|
|
@@ -12268,12 +13421,14 @@ export {
|
|
|
12268
13421
|
Guard,
|
|
12269
13422
|
HolomimeCallbackHandler,
|
|
12270
13423
|
HolomimeViolationError,
|
|
13424
|
+
KNOWN_STANDARDS,
|
|
12271
13425
|
LEARNING_ORIENTATIONS,
|
|
12272
13426
|
LocalMarketplaceBackend,
|
|
12273
13427
|
MarketplaceClient,
|
|
12274
13428
|
OllamaProvider,
|
|
12275
13429
|
OpenAIProvider,
|
|
12276
13430
|
PROVIDER_PARAMS,
|
|
13431
|
+
STACK_FILES,
|
|
12277
13432
|
STANDARD_PROBES,
|
|
12278
13433
|
SURFACE_MULTIPLIERS,
|
|
12279
13434
|
THERAPIST_META_SPEC,
|
|
@@ -12287,6 +13442,7 @@ export {
|
|
|
12287
13442
|
appendEvolution,
|
|
12288
13443
|
applyRecommendations,
|
|
12289
13444
|
bigFiveSchema,
|
|
13445
|
+
bodySchema,
|
|
12290
13446
|
buildAgentTherapistPrompt,
|
|
12291
13447
|
buildAnonymizedReport,
|
|
12292
13448
|
buildPatientSystemPrompt,
|
|
@@ -12295,6 +13451,7 @@ export {
|
|
|
12295
13451
|
buildSharedKnowledge,
|
|
12296
13452
|
buildTherapistSystemPrompt,
|
|
12297
13453
|
checkApproval,
|
|
13454
|
+
checkCompliance,
|
|
12298
13455
|
checkIterationBudget,
|
|
12299
13456
|
communicationSchema,
|
|
12300
13457
|
compactEvolutionRun,
|
|
@@ -12308,6 +13465,7 @@ export {
|
|
|
12308
13465
|
compileL0,
|
|
12309
13466
|
compileL1,
|
|
12310
13467
|
compileL2,
|
|
13468
|
+
compileStack,
|
|
12311
13469
|
compileTiered,
|
|
12312
13470
|
compiledConfigSchema,
|
|
12313
13471
|
compiledEmbodiedConfigSchema,
|
|
@@ -12317,6 +13475,7 @@ export {
|
|
|
12317
13475
|
computeProsody,
|
|
12318
13476
|
computeProxemics,
|
|
12319
13477
|
computeSyncProfile,
|
|
13478
|
+
conscienceSchema,
|
|
12320
13479
|
conversationLogSchema,
|
|
12321
13480
|
conversationSchema,
|
|
12322
13481
|
convertToHFFormat,
|
|
@@ -12333,6 +13492,7 @@ export {
|
|
|
12333
13492
|
createRepertoire,
|
|
12334
13493
|
createTreatmentPlan,
|
|
12335
13494
|
decayUnseenPatterns,
|
|
13495
|
+
decomposeSpec,
|
|
12336
13496
|
deepMergeSpec,
|
|
12337
13497
|
detectApologies,
|
|
12338
13498
|
detectBoundaryIssues,
|
|
@@ -12346,6 +13506,7 @@ export {
|
|
|
12346
13506
|
discoverAgents,
|
|
12347
13507
|
discoverNetworkAgents,
|
|
12348
13508
|
domainSchema,
|
|
13509
|
+
egoSchema,
|
|
12349
13510
|
embodimentSchema,
|
|
12350
13511
|
emitBehavioralEvent,
|
|
12351
13512
|
encodeSnapshot,
|
|
@@ -12366,10 +13527,12 @@ export {
|
|
|
12366
13527
|
findEdges,
|
|
12367
13528
|
findNode,
|
|
12368
13529
|
findNodesByType,
|
|
13530
|
+
findStackDir,
|
|
12369
13531
|
formatComplianceReportMarkdown,
|
|
12370
13532
|
formatGapSummary,
|
|
12371
13533
|
formatPolicyYaml,
|
|
12372
13534
|
formatReACTReportMarkdown,
|
|
13535
|
+
formatReportTerminal,
|
|
12373
13536
|
gazePolicySchema,
|
|
12374
13537
|
generateBehavioralPolicy,
|
|
12375
13538
|
generateBenchmarkMarkdown,
|
|
@@ -12383,6 +13546,7 @@ export {
|
|
|
12383
13546
|
generatePrescriptions,
|
|
12384
13547
|
generateProgressReport,
|
|
12385
13548
|
generateReACTReport,
|
|
13549
|
+
generateReportJSON,
|
|
12386
13550
|
generateShareUrl,
|
|
12387
13551
|
generateSystemPrompt,
|
|
12388
13552
|
gestureSchema,
|
|
@@ -12414,12 +13578,14 @@ export {
|
|
|
12414
13578
|
growthSchema,
|
|
12415
13579
|
hapticPolicySchema,
|
|
12416
13580
|
hashSpec2 as hashSpec,
|
|
13581
|
+
isStackDirectory,
|
|
12417
13582
|
learnIntervention,
|
|
12418
13583
|
listArchetypeIds,
|
|
12419
13584
|
listDetectors,
|
|
12420
13585
|
listDetectorsByCategory,
|
|
12421
13586
|
listDetectorsByTag,
|
|
12422
13587
|
listPresets,
|
|
13588
|
+
loadAllStandards,
|
|
12423
13589
|
loadAuditLog,
|
|
12424
13590
|
loadBehavioralMemory,
|
|
12425
13591
|
loadBenchmarkResults,
|
|
@@ -12433,10 +13599,13 @@ export {
|
|
|
12433
13599
|
loadNetworkConfig,
|
|
12434
13600
|
loadRepertoire,
|
|
12435
13601
|
loadSpec,
|
|
13602
|
+
loadSpecWithStack,
|
|
13603
|
+
loadStandard,
|
|
12436
13604
|
loadTranscripts,
|
|
12437
13605
|
loadTreatmentPlan,
|
|
12438
13606
|
mergeStores,
|
|
12439
13607
|
messageSchema,
|
|
13608
|
+
mindSchema,
|
|
12440
13609
|
modalitySchema,
|
|
12441
13610
|
morphologySchema,
|
|
12442
13611
|
motionParametersSchema,
|
|
@@ -12460,7 +13629,9 @@ export {
|
|
|
12460
13629
|
prosodySchema,
|
|
12461
13630
|
providerSchema,
|
|
12462
13631
|
proxemicZoneSchema,
|
|
13632
|
+
psycheSchema,
|
|
12463
13633
|
publishToLeaderboard,
|
|
13634
|
+
purposeSchema,
|
|
12464
13635
|
pushToHFHub,
|
|
12465
13636
|
queryCorpus,
|
|
12466
13637
|
queryInterventions,
|
|
@@ -12502,8 +13673,11 @@ export {
|
|
|
12502
13673
|
selectIntervention,
|
|
12503
13674
|
severityMeetsThreshold2 as severityMeetsThreshold,
|
|
12504
13675
|
severitySchema,
|
|
13676
|
+
shadowSchema,
|
|
12505
13677
|
shareAnonymizedPatterns,
|
|
12506
13678
|
shareFromDiagnosis,
|
|
13679
|
+
soulFrontmatterSchema,
|
|
13680
|
+
soulSchema,
|
|
12507
13681
|
startFleet,
|
|
12508
13682
|
startMCPServer,
|
|
12509
13683
|
startWatch,
|