holomime 1.9.1 → 2.0.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 +129 -420
- package/dist/cli.js +2504 -871
- package/dist/index.d.ts +106 -3
- package/dist/index.js +1101 -188
- package/dist/mcp-server.js +982 -408
- package/package.json +3 -1
- 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/nova.personality.json +83 -0
package/dist/index.js
CHANGED
|
@@ -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,449 @@ 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 psycheSchema = 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 hardwareProfileSchema = z4.object({
|
|
4697
|
+
oem: z4.string().optional(),
|
|
4698
|
+
model: z4.string().optional(),
|
|
4699
|
+
actuator_count: z4.number().int().optional(),
|
|
4700
|
+
sensors: z4.array(z4.string()).default([]),
|
|
4701
|
+
compute: z4.enum(["onboard", "edge", "cloud", "hybrid"]).default("onboard")
|
|
4702
|
+
});
|
|
4703
|
+
var bodySchema = z4.object({
|
|
4704
|
+
version: z4.string().default("1.0"),
|
|
4705
|
+
morphology: morphologySchema.default("humanoid"),
|
|
4706
|
+
modalities: z4.array(modalitySchema).default(["gesture", "gaze", "voice", "posture"]),
|
|
4707
|
+
safety_envelope: safetyEnvelopeSchema.default({}),
|
|
4708
|
+
expression: expressionSchema.optional(),
|
|
4709
|
+
hardware_profile: hardwareProfileSchema.optional()
|
|
4710
|
+
});
|
|
4711
|
+
var conscienceRuleSchema = z4.object({
|
|
4712
|
+
action: z4.string(),
|
|
4713
|
+
reason: z4.string().optional(),
|
|
4714
|
+
conditions: z4.array(z4.string()).optional()
|
|
4715
|
+
});
|
|
4716
|
+
var escalationRuleSchema = z4.object({
|
|
4717
|
+
trigger: z4.string(),
|
|
4718
|
+
action: z4.string(),
|
|
4719
|
+
severity: z4.enum(["info", "warning", "critical"]).default("warning")
|
|
4720
|
+
});
|
|
4721
|
+
var conscienceSchema = z4.object({
|
|
4722
|
+
version: z4.string().default("1.0"),
|
|
4723
|
+
rules: z4.object({
|
|
4724
|
+
deny: z4.array(conscienceRuleSchema).default([]),
|
|
4725
|
+
allow: z4.array(conscienceRuleSchema).default([]),
|
|
4726
|
+
escalate: z4.array(escalationRuleSchema).default([])
|
|
4727
|
+
}).default({}),
|
|
4728
|
+
hard_limits: z4.array(z4.string()).default([]),
|
|
4729
|
+
oversight: z4.object({
|
|
4730
|
+
mode: z4.enum(["autonomous", "review", "supervised"]).default("review"),
|
|
4731
|
+
max_autonomous_iterations: z4.number().int().default(5)
|
|
4732
|
+
}).optional()
|
|
4733
|
+
});
|
|
4734
|
+
var STACK_FILES = {
|
|
4735
|
+
soul: "soul.md",
|
|
4736
|
+
psyche: "psyche.sys",
|
|
4737
|
+
body: "body.api",
|
|
4738
|
+
conscience: "conscience.exe"
|
|
4739
|
+
};
|
|
4740
|
+
|
|
4741
|
+
// src/core/stack-compiler.ts
|
|
4742
|
+
import { readFileSync as readFileSync7, existsSync as existsSync6 } from "fs";
|
|
4743
|
+
import { join as join6 } from "path";
|
|
4744
|
+
import { createHash as createHash2 } from "crypto";
|
|
4745
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4746
|
+
function parseSoulMd(content) {
|
|
4747
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
4748
|
+
let frontmatter = {};
|
|
4749
|
+
let body = content;
|
|
4750
|
+
if (frontmatterMatch) {
|
|
4751
|
+
frontmatter = parseYaml(frontmatterMatch[1]) || {};
|
|
4752
|
+
body = frontmatterMatch[2];
|
|
4753
|
+
}
|
|
4754
|
+
const nameMatch = body.match(/^#\s+(.+)$/m);
|
|
4755
|
+
const name = nameMatch?.[1]?.trim() || "Unnamed";
|
|
4756
|
+
const purposeMatch = body.match(/^>\s+(.+)$/m);
|
|
4757
|
+
const purpose = purposeMatch?.[1]?.trim();
|
|
4758
|
+
const coreValues = extractListSection(body, "Core Values");
|
|
4759
|
+
const redLines = extractListSection(body, "Red Lines");
|
|
4760
|
+
const ethicalFramework = extractTextSection(body, "Ethical Framework");
|
|
4761
|
+
return soulSchema.parse({
|
|
4762
|
+
frontmatter,
|
|
4763
|
+
name,
|
|
4764
|
+
purpose,
|
|
4765
|
+
core_values: coreValues,
|
|
4766
|
+
red_lines: redLines,
|
|
4767
|
+
ethical_framework: ethicalFramework
|
|
4768
|
+
});
|
|
4769
|
+
}
|
|
4770
|
+
function extractListSection(md, heading) {
|
|
4771
|
+
const pattern = new RegExp(
|
|
4772
|
+
`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
|
|
4773
|
+
"m"
|
|
4774
|
+
);
|
|
4775
|
+
const match = md.match(pattern);
|
|
4776
|
+
if (!match) return [];
|
|
4777
|
+
return match[1].split("\n").map((line) => line.replace(/^[-*]\s+/, "").trim()).filter(Boolean);
|
|
4778
|
+
}
|
|
4779
|
+
function extractTextSection(md, heading) {
|
|
4780
|
+
const pattern = new RegExp(
|
|
4781
|
+
`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
|
|
4782
|
+
"m"
|
|
4783
|
+
);
|
|
4784
|
+
const match = md.match(pattern);
|
|
4785
|
+
if (!match) return void 0;
|
|
4786
|
+
return match[1].trim() || void 0;
|
|
4787
|
+
}
|
|
4788
|
+
function hashContent(content) {
|
|
4789
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 12);
|
|
4790
|
+
}
|
|
4791
|
+
function isStackDirectory(dir) {
|
|
4792
|
+
const soulPath = join6(dir, STACK_FILES.soul);
|
|
4793
|
+
const psychePath = join6(dir, STACK_FILES.psyche);
|
|
4794
|
+
return existsSync6(soulPath) && existsSync6(psychePath);
|
|
4795
|
+
}
|
|
4796
|
+
function findStackDir(projectRoot) {
|
|
4797
|
+
const conventionalDir = join6(projectRoot, ".holomime", "identity");
|
|
4798
|
+
if (isStackDirectory(conventionalDir)) return conventionalDir;
|
|
4799
|
+
if (isStackDirectory(projectRoot)) return projectRoot;
|
|
4800
|
+
return null;
|
|
4801
|
+
}
|
|
4802
|
+
function compileStack(options) {
|
|
4803
|
+
const { stackDir } = options;
|
|
4804
|
+
const warnings = [];
|
|
4805
|
+
const soulPath = options.soulPath || join6(stackDir, STACK_FILES.soul);
|
|
4806
|
+
const soulContent = readFileSync7(soulPath, "utf-8");
|
|
4807
|
+
const soul = parseSoulMd(soulContent);
|
|
4808
|
+
const psychePath = options.psychePath || join6(stackDir, STACK_FILES.psyche);
|
|
4809
|
+
const psycheContent = readFileSync7(psychePath, "utf-8");
|
|
4810
|
+
const psycheRaw = parseYaml(psycheContent);
|
|
4811
|
+
const psyche = psycheSchema.parse(psycheRaw);
|
|
4812
|
+
const bodyPath = options.bodyPath || join6(stackDir, STACK_FILES.body);
|
|
4813
|
+
let body;
|
|
4814
|
+
let bodySource;
|
|
4815
|
+
if (existsSync6(bodyPath)) {
|
|
4816
|
+
const bodyContent = readFileSync7(bodyPath, "utf-8");
|
|
4817
|
+
const bodyRaw = JSON.parse(bodyContent);
|
|
4818
|
+
body = bodySchema.parse(bodyRaw);
|
|
4819
|
+
bodySource = { path: bodyPath, hash: hashContent(bodyContent) };
|
|
4820
|
+
}
|
|
4821
|
+
const consciencePath = options.consciencePath || join6(stackDir, STACK_FILES.conscience);
|
|
4822
|
+
const conscienceContent = readFileSync7(consciencePath, "utf-8");
|
|
4823
|
+
const conscienceRaw = parseYaml(conscienceContent);
|
|
4824
|
+
const conscience = conscienceSchema.parse(conscienceRaw);
|
|
4825
|
+
const allHardLimits = [.../* @__PURE__ */ new Set([
|
|
4826
|
+
...soul.red_lines,
|
|
4827
|
+
...conscience.hard_limits
|
|
4828
|
+
])];
|
|
4829
|
+
const refuses = conscience.rules.deny.map((r) => r.action);
|
|
4830
|
+
const escalationTriggers = conscience.rules.escalate.map((r) => r.trigger);
|
|
4831
|
+
const handle = soul.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "agent";
|
|
4832
|
+
const spec = {
|
|
4833
|
+
version: "2.0",
|
|
4834
|
+
name: soul.name,
|
|
4835
|
+
handle,
|
|
4836
|
+
purpose: soul.purpose,
|
|
4837
|
+
big_five: psyche.big_five,
|
|
4838
|
+
therapy_dimensions: psyche.therapy_dimensions,
|
|
4839
|
+
communication: psyche.communication,
|
|
4840
|
+
growth: psyche.growth,
|
|
4841
|
+
domain: {
|
|
4842
|
+
expertise: [],
|
|
4843
|
+
boundaries: {
|
|
4844
|
+
refuses,
|
|
4845
|
+
escalation_triggers: escalationTriggers,
|
|
4846
|
+
hard_limits: allHardLimits
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
};
|
|
4850
|
+
if (body) {
|
|
4851
|
+
spec.embodiment = {
|
|
4852
|
+
morphology: body.morphology,
|
|
4853
|
+
modalities: body.modalities,
|
|
4854
|
+
safety_envelope: body.safety_envelope,
|
|
4855
|
+
metadata: body.hardware_profile ? { hardware_profile: body.hardware_profile } : void 0
|
|
4856
|
+
};
|
|
4857
|
+
if (body.expression) {
|
|
4858
|
+
spec.expression = body.expression;
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
const validated = personalitySpecSchema.parse(spec);
|
|
4862
|
+
if (soul.frontmatter.immutable === false) {
|
|
4863
|
+
warnings.push("soul.md: immutable flag is false \u2014 soul changes will be allowed");
|
|
4864
|
+
}
|
|
4865
|
+
if (!body && psyche.communication) {
|
|
4866
|
+
}
|
|
4867
|
+
if (conscience.rules.deny.length === 0) {
|
|
4868
|
+
warnings.push("conscience.exe: no deny rules defined \u2014 agent has no moral constraints");
|
|
4869
|
+
}
|
|
4870
|
+
return {
|
|
4871
|
+
spec: validated,
|
|
4872
|
+
sources: {
|
|
4873
|
+
soul: { path: soulPath, hash: hashContent(soulContent) },
|
|
4874
|
+
psyche: { path: psychePath, hash: hashContent(psycheContent) },
|
|
4875
|
+
...bodySource ? { body: bodySource } : {},
|
|
4876
|
+
conscience: { path: consciencePath, hash: hashContent(conscienceContent) }
|
|
4877
|
+
},
|
|
4878
|
+
warnings
|
|
4879
|
+
};
|
|
4880
|
+
}
|
|
4881
|
+
|
|
4882
|
+
// src/analysis/stack-patcher.ts
|
|
4883
|
+
var DETECTOR_LAYER_MAP = {
|
|
4884
|
+
// apology-detector.ts → "over-apologizing" | "apology-healthy"
|
|
4885
|
+
"over-apologizing": "psyche",
|
|
4886
|
+
"apology-healthy": "psyche",
|
|
4887
|
+
// hedge-detector.ts → "hedge-stacking"
|
|
4888
|
+
"hedge-stacking": "psyche",
|
|
4889
|
+
// sentiment.ts → "sycophantic-tendency" | "negative-skew"
|
|
4890
|
+
"sycophantic-tendency": "psyche",
|
|
4891
|
+
"negative-skew": "psyche",
|
|
4892
|
+
// verbosity.ts → "over-verbose" | "inconsistent-length"
|
|
4893
|
+
"over-verbose": "psyche",
|
|
4894
|
+
"inconsistent-length": "psyche",
|
|
4895
|
+
// formality.ts → "register-inconsistency"
|
|
4896
|
+
"register-inconsistency": "psyche",
|
|
4897
|
+
// recovery.ts → "error-spiral" | "recovery-good"
|
|
4898
|
+
"error-spiral": "psyche",
|
|
4899
|
+
"recovery-good": "psyche",
|
|
4900
|
+
// boundary.ts → "boundary-violation" | "boundary-healthy" | "boundary-solid"
|
|
4901
|
+
"boundary-violation": "conscience",
|
|
4902
|
+
"boundary-healthy": "conscience",
|
|
4903
|
+
"boundary-solid": "conscience",
|
|
4904
|
+
// retrieval-quality.ts → "retrieval-quality"
|
|
4905
|
+
"retrieval-quality": "psyche"
|
|
4906
|
+
};
|
|
4907
|
+
var LAYER_KEYWORDS = {
|
|
4908
|
+
psyche: [
|
|
4909
|
+
/\bbig_five\b/i,
|
|
4910
|
+
/\btherapy_dimensions\b/i,
|
|
4911
|
+
/\bcommunication\b/i,
|
|
4912
|
+
/\bgrowth\b/i,
|
|
4913
|
+
/\bhedg/i,
|
|
4914
|
+
/\bverbos/i,
|
|
4915
|
+
/\buncertainty/i,
|
|
4916
|
+
/\bconfidence/i,
|
|
4917
|
+
/\bself[_-]awareness/i,
|
|
4918
|
+
/\bdistress[_-]tolerance/i,
|
|
4919
|
+
/\bconflict[_-]approach/i,
|
|
4920
|
+
/\bregister\b/i,
|
|
4921
|
+
/\bformality/i,
|
|
4922
|
+
/\bsentiment/i,
|
|
4923
|
+
/\bsycophant/i,
|
|
4924
|
+
/\bapolog/i,
|
|
4925
|
+
/\brecovery/i,
|
|
4926
|
+
/\blearning[_-]orientation/i,
|
|
4927
|
+
/\bboundary[_-]awareness/i,
|
|
4928
|
+
/\binterpersonal/i,
|
|
4929
|
+
/\bpatterns[_-]to[_-]watch/i,
|
|
4930
|
+
/\bemotion/i
|
|
4931
|
+
],
|
|
4932
|
+
body: [
|
|
4933
|
+
/\bmotion\b/i,
|
|
4934
|
+
/\bgaze\b/i,
|
|
4935
|
+
/\bproxemics\b/i,
|
|
4936
|
+
/\bgesture\b/i,
|
|
4937
|
+
/\bposture\b/i,
|
|
4938
|
+
/\bexpression\b/i,
|
|
4939
|
+
/\bembodiment\b/i,
|
|
4940
|
+
/\bmorphology\b/i,
|
|
4941
|
+
/\bmodality/i,
|
|
4942
|
+
/\bsafety[_-]envelope/i,
|
|
4943
|
+
/\bactuator/i,
|
|
4944
|
+
/\bsensor/i
|
|
4945
|
+
],
|
|
4946
|
+
conscience: [
|
|
4947
|
+
/\bboundary[_-]violation/i,
|
|
4948
|
+
/\bdeny\b/i,
|
|
4949
|
+
/\brefuse/i,
|
|
4950
|
+
/\bescalat/i,
|
|
4951
|
+
/\bhard[_-]limit/i,
|
|
4952
|
+
/\boversight/i
|
|
4953
|
+
],
|
|
4954
|
+
soul: [
|
|
4955
|
+
/\bcore[_-]value/i,
|
|
4956
|
+
/\bred[_-]line/i,
|
|
4957
|
+
/\bethic/i,
|
|
4958
|
+
/\bpurpose\b/i,
|
|
4959
|
+
/\bimmutable\b/i
|
|
4960
|
+
]
|
|
4961
|
+
};
|
|
4962
|
+
function classifyPatch(recommendation) {
|
|
4963
|
+
if (LAYER_KEYWORDS.conscience.some((r) => r.test(recommendation))) {
|
|
4964
|
+
return "conscience";
|
|
4965
|
+
}
|
|
4966
|
+
if (LAYER_KEYWORDS.soul.some((r) => r.test(recommendation))) {
|
|
4967
|
+
return "soul";
|
|
4968
|
+
}
|
|
4969
|
+
if (LAYER_KEYWORDS.body.some((r) => r.test(recommendation))) {
|
|
4970
|
+
return "body";
|
|
4971
|
+
}
|
|
4972
|
+
return "psyche";
|
|
4973
|
+
}
|
|
4974
|
+
function classifyByDetector(patternId, recommendation) {
|
|
4975
|
+
const mapped = DETECTOR_LAYER_MAP[patternId];
|
|
4976
|
+
if (mapped) return mapped;
|
|
4977
|
+
if (recommendation) return classifyPatch(recommendation);
|
|
4978
|
+
return "psyche";
|
|
4979
|
+
}
|
|
4980
|
+
function applyStackPatches(patches, stackDir) {
|
|
4981
|
+
const applied = [];
|
|
4982
|
+
const skipped = [];
|
|
4983
|
+
const modifiedFiles = /* @__PURE__ */ new Set();
|
|
4984
|
+
const warnings = [];
|
|
4985
|
+
for (const patch of patches) {
|
|
4986
|
+
if (patch.target === "soul") {
|
|
4987
|
+
skipped.push(patch);
|
|
4988
|
+
warnings.push(
|
|
4989
|
+
`[soul] Manual approval required: ${patch.reason} (path: ${patch.path.join(".")})`
|
|
4990
|
+
);
|
|
4991
|
+
continue;
|
|
4992
|
+
}
|
|
4993
|
+
if (patch.target === "conscience") {
|
|
4994
|
+
skipped.push(patch);
|
|
4995
|
+
warnings.push(
|
|
4996
|
+
`[conscience] Manual approval required: ${patch.reason} (path: ${patch.path.join(".")})`
|
|
4997
|
+
);
|
|
4998
|
+
continue;
|
|
4999
|
+
}
|
|
5000
|
+
if (patch.target === "body") {
|
|
5001
|
+
const bodyPath = join7(stackDir, STACK_FILES.body);
|
|
5002
|
+
if (!existsSync7(bodyPath)) {
|
|
5003
|
+
skipped.push(patch);
|
|
5004
|
+
warnings.push(`[body] body.api does not exist, skipping: ${patch.reason}`);
|
|
5005
|
+
continue;
|
|
5006
|
+
}
|
|
5007
|
+
try {
|
|
5008
|
+
const content = readFileSync8(bodyPath, "utf-8");
|
|
5009
|
+
const bodyObj = JSON.parse(content);
|
|
5010
|
+
applyPatchToObject(bodyObj, patch);
|
|
5011
|
+
writeFileSync4(bodyPath, JSON.stringify(bodyObj, null, 2) + "\n");
|
|
5012
|
+
applied.push(patch);
|
|
5013
|
+
modifiedFiles.add(bodyPath);
|
|
5014
|
+
} catch (err) {
|
|
5015
|
+
skipped.push(patch);
|
|
5016
|
+
warnings.push(`[body] Failed to patch body.api: ${err}`);
|
|
5017
|
+
}
|
|
5018
|
+
continue;
|
|
5019
|
+
}
|
|
5020
|
+
if (patch.target === "psyche") {
|
|
5021
|
+
const psychePath = join7(stackDir, STACK_FILES.psyche);
|
|
5022
|
+
if (!existsSync7(psychePath)) {
|
|
5023
|
+
skipped.push(patch);
|
|
5024
|
+
warnings.push(`[psyche] psyche.sys does not exist, skipping: ${patch.reason}`);
|
|
5025
|
+
continue;
|
|
5026
|
+
}
|
|
5027
|
+
try {
|
|
5028
|
+
const content = readFileSync8(psychePath, "utf-8");
|
|
5029
|
+
const psycheObj = parseYaml2(content);
|
|
5030
|
+
applyPatchToObject(psycheObj, patch);
|
|
5031
|
+
writeFileSync4(psychePath, stringifyYaml2(psycheObj));
|
|
5032
|
+
applied.push(patch);
|
|
5033
|
+
modifiedFiles.add(psychePath);
|
|
5034
|
+
} catch (err) {
|
|
5035
|
+
skipped.push(patch);
|
|
5036
|
+
warnings.push(`[psyche] Failed to patch psyche.sys: ${err}`);
|
|
5037
|
+
}
|
|
5038
|
+
continue;
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
5041
|
+
let recompiled = false;
|
|
5042
|
+
if (modifiedFiles.size > 0) {
|
|
5043
|
+
try {
|
|
5044
|
+
compileStack({ stackDir });
|
|
5045
|
+
recompiled = true;
|
|
5046
|
+
} catch (err) {
|
|
5047
|
+
warnings.push(`Stack recompilation failed: ${err}`);
|
|
5048
|
+
}
|
|
5049
|
+
}
|
|
5050
|
+
return {
|
|
5051
|
+
applied,
|
|
5052
|
+
skipped,
|
|
5053
|
+
filesModified: [...modifiedFiles],
|
|
5054
|
+
recompiled,
|
|
5055
|
+
warnings
|
|
5056
|
+
};
|
|
5057
|
+
}
|
|
5058
|
+
function convertToStackPatches(patternId, specPath, value, reason) {
|
|
5059
|
+
const layer = classifyByDetector(patternId, specPath);
|
|
5060
|
+
const path = specPath.split(".");
|
|
5061
|
+
let operation = "set";
|
|
5062
|
+
if (specPath.endsWith("patterns_to_watch") || specPath.endsWith("areas") || specPath.endsWith("strengths")) {
|
|
5063
|
+
operation = "append";
|
|
5064
|
+
} else if (typeof value === "number") {
|
|
5065
|
+
operation = "set";
|
|
5066
|
+
}
|
|
5067
|
+
return {
|
|
5068
|
+
target: layer,
|
|
5069
|
+
path,
|
|
5070
|
+
operation,
|
|
5071
|
+
value,
|
|
5072
|
+
reason
|
|
5073
|
+
};
|
|
5074
|
+
}
|
|
5075
|
+
function applyPatchToObject(obj, patch) {
|
|
5076
|
+
const { path, operation, value } = patch;
|
|
5077
|
+
let current = obj;
|
|
5078
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
5079
|
+
if (current[path[i]] === void 0 || current[path[i]] === null) {
|
|
5080
|
+
current[path[i]] = {};
|
|
5081
|
+
}
|
|
5082
|
+
current = current[path[i]];
|
|
5083
|
+
}
|
|
5084
|
+
const lastKey = path[path.length - 1];
|
|
5085
|
+
switch (operation) {
|
|
5086
|
+
case "set":
|
|
5087
|
+
if (typeof value === "number") {
|
|
5088
|
+
current[lastKey] = Math.max(0, Math.min(1, value));
|
|
5089
|
+
} else {
|
|
5090
|
+
current[lastKey] = value;
|
|
5091
|
+
}
|
|
5092
|
+
break;
|
|
5093
|
+
case "adjust": {
|
|
5094
|
+
const existing = typeof current[lastKey] === "number" ? current[lastKey] : 0;
|
|
5095
|
+
const delta = typeof value === "number" ? value : 0;
|
|
5096
|
+
current[lastKey] = Math.max(0, Math.min(1, existing + delta));
|
|
5097
|
+
break;
|
|
5098
|
+
}
|
|
5099
|
+
case "append": {
|
|
5100
|
+
if (!Array.isArray(current[lastKey])) {
|
|
5101
|
+
current[lastKey] = [];
|
|
5102
|
+
}
|
|
5103
|
+
if (typeof value === "string" && !current[lastKey].includes(value)) {
|
|
5104
|
+
current[lastKey].push(value);
|
|
5105
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
5106
|
+
current[lastKey].push(value);
|
|
5107
|
+
}
|
|
5108
|
+
break;
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
|
|
4670
5113
|
// src/analysis/session-runner.ts
|
|
4671
5114
|
async function runTherapySession(spec, diagnosis, provider, maxTurns, options) {
|
|
4672
5115
|
const promptOptions = {
|
|
@@ -4835,7 +5278,136 @@ function extractRecommendations(turns) {
|
|
|
4835
5278
|
}
|
|
4836
5279
|
return recommendations.slice(0, 5);
|
|
4837
5280
|
}
|
|
4838
|
-
async function applyRecommendations(spec, diagnosis, transcript, provider) {
|
|
5281
|
+
async function applyRecommendations(spec, diagnosis, transcript, provider, options) {
|
|
5282
|
+
const projectRoot = options?.projectRoot ?? process.cwd();
|
|
5283
|
+
const stackDir = findStackDir(projectRoot);
|
|
5284
|
+
if (stackDir) {
|
|
5285
|
+
return applyRecommendationsStack(spec, diagnosis, stackDir, transcript, provider);
|
|
5286
|
+
}
|
|
5287
|
+
return applyRecommendationsLegacy(spec, diagnosis, transcript, provider);
|
|
5288
|
+
}
|
|
5289
|
+
async function applyRecommendationsStack(spec, diagnosis, stackDir, transcript, provider) {
|
|
5290
|
+
const changes = [];
|
|
5291
|
+
const patches = [];
|
|
5292
|
+
const patternIds = diagnosis.patterns.map((p) => p.id);
|
|
5293
|
+
if (patternIds.includes("over-apologizing")) {
|
|
5294
|
+
if (spec.communication?.uncertainty_handling !== "confident_transparency") {
|
|
5295
|
+
patches.push(convertToStackPatches(
|
|
5296
|
+
"over-apologizing",
|
|
5297
|
+
"communication.uncertainty_handling",
|
|
5298
|
+
"confident_transparency",
|
|
5299
|
+
"Over-apologizing detected: set uncertainty_handling to confident_transparency"
|
|
5300
|
+
));
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
if (patternIds.includes("hedge-stacking")) {
|
|
5304
|
+
const watched = spec.growth?.patterns_to_watch ?? [];
|
|
5305
|
+
if (!watched.includes("hedge stacking under uncertainty")) {
|
|
5306
|
+
patches.push(convertToStackPatches(
|
|
5307
|
+
"hedge-stacking",
|
|
5308
|
+
"growth.patterns_to_watch",
|
|
5309
|
+
"hedge stacking under uncertainty",
|
|
5310
|
+
"Hedge stacking detected: add to patterns_to_watch"
|
|
5311
|
+
));
|
|
5312
|
+
}
|
|
5313
|
+
}
|
|
5314
|
+
if (patternIds.includes("sycophantic-tendency")) {
|
|
5315
|
+
if (spec.communication?.conflict_approach !== "honest_first") {
|
|
5316
|
+
patches.push(convertToStackPatches(
|
|
5317
|
+
"sycophantic-tendency",
|
|
5318
|
+
"communication.conflict_approach",
|
|
5319
|
+
"honest_first",
|
|
5320
|
+
"Sycophantic tendency: set conflict_approach to honest_first"
|
|
5321
|
+
));
|
|
5322
|
+
}
|
|
5323
|
+
if ((spec.therapy_dimensions?.self_awareness ?? 0) < 0.85) {
|
|
5324
|
+
patches.push(convertToStackPatches(
|
|
5325
|
+
"sycophantic-tendency",
|
|
5326
|
+
"therapy_dimensions.self_awareness",
|
|
5327
|
+
0.85,
|
|
5328
|
+
"Sycophantic tendency: increase self_awareness to 0.85"
|
|
5329
|
+
));
|
|
5330
|
+
}
|
|
5331
|
+
}
|
|
5332
|
+
if (patternIds.includes("error-spiral")) {
|
|
5333
|
+
if ((spec.therapy_dimensions?.distress_tolerance ?? 0) < 0.8) {
|
|
5334
|
+
patches.push(convertToStackPatches(
|
|
5335
|
+
"error-spiral",
|
|
5336
|
+
"therapy_dimensions.distress_tolerance",
|
|
5337
|
+
0.8,
|
|
5338
|
+
"Error spiral detected: increase distress_tolerance to 0.80"
|
|
5339
|
+
));
|
|
5340
|
+
}
|
|
5341
|
+
const hasRecovery = (spec.growth?.areas ?? []).some(
|
|
5342
|
+
(a) => typeof a === "string" ? a.includes("error recovery") : a.area?.includes("error recovery")
|
|
5343
|
+
);
|
|
5344
|
+
if (!hasRecovery) {
|
|
5345
|
+
patches.push(convertToStackPatches(
|
|
5346
|
+
"error-spiral",
|
|
5347
|
+
"growth.areas",
|
|
5348
|
+
{
|
|
5349
|
+
area: "deliberate error recovery",
|
|
5350
|
+
severity: "moderate",
|
|
5351
|
+
first_detected: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
5352
|
+
session_count: 1,
|
|
5353
|
+
resolved: false
|
|
5354
|
+
},
|
|
5355
|
+
"Error spiral detected: add deliberate error recovery to growth areas"
|
|
5356
|
+
));
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
if (patternIds.includes("negative-sentiment-skew")) {
|
|
5360
|
+
const watched = spec.growth?.patterns_to_watch ?? [];
|
|
5361
|
+
if (!watched.includes("negative sentiment patterns")) {
|
|
5362
|
+
patches.push(convertToStackPatches(
|
|
5363
|
+
"negative-sentiment-skew",
|
|
5364
|
+
"growth.patterns_to_watch",
|
|
5365
|
+
"negative sentiment patterns",
|
|
5366
|
+
"Negative sentiment skew: add to patterns_to_watch"
|
|
5367
|
+
));
|
|
5368
|
+
}
|
|
5369
|
+
}
|
|
5370
|
+
if (transcript && provider && transcript.turns.length > 4) {
|
|
5371
|
+
try {
|
|
5372
|
+
const llmChanges = await deriveLLMRecommendations(spec, transcript, provider);
|
|
5373
|
+
for (const change of llmChanges) {
|
|
5374
|
+
const layer = classifyByDetector("", change.path);
|
|
5375
|
+
patches.push({
|
|
5376
|
+
target: layer,
|
|
5377
|
+
path: change.path.split("."),
|
|
5378
|
+
operation: change.path.endsWith("patterns_to_watch") || change.path.endsWith("areas") || change.path.endsWith("strengths") ? "append" : "set",
|
|
5379
|
+
value: change.value,
|
|
5380
|
+
reason: change.description
|
|
5381
|
+
});
|
|
5382
|
+
}
|
|
5383
|
+
} catch {
|
|
5384
|
+
}
|
|
5385
|
+
}
|
|
5386
|
+
if (patches.length === 0) {
|
|
5387
|
+
return { changed: false, changes: [], stackFilesModified: [] };
|
|
5388
|
+
}
|
|
5389
|
+
const result = applyStackPatches(patches, stackDir);
|
|
5390
|
+
for (const patch of result.applied) {
|
|
5391
|
+
changes.push(`[${patch.target}] ${patch.path.join(".")} \u2192 ${JSON.stringify(patch.value)} (${patch.reason})`);
|
|
5392
|
+
}
|
|
5393
|
+
for (const warning of result.warnings) {
|
|
5394
|
+
changes.push(warning);
|
|
5395
|
+
}
|
|
5396
|
+
if (result.recompiled) {
|
|
5397
|
+
try {
|
|
5398
|
+
const compiled = compileStack({ stackDir });
|
|
5399
|
+
Object.assign(spec, compiled.spec);
|
|
5400
|
+
changes.push(`Stack recompiled from ${result.filesModified.length} modified source file(s)`);
|
|
5401
|
+
} catch {
|
|
5402
|
+
}
|
|
5403
|
+
}
|
|
5404
|
+
return {
|
|
5405
|
+
changed: result.applied.length > 0,
|
|
5406
|
+
changes,
|
|
5407
|
+
stackFilesModified: result.filesModified
|
|
5408
|
+
};
|
|
5409
|
+
}
|
|
5410
|
+
async function applyRecommendationsLegacy(spec, diagnosis, transcript, provider) {
|
|
4839
5411
|
const changes = [];
|
|
4840
5412
|
const patternIds = diagnosis.patterns.map((p) => p.id);
|
|
4841
5413
|
if (patternIds.includes("over-apologizing")) {
|
|
@@ -4983,20 +5555,20 @@ function applyStructuredChange(spec, change) {
|
|
|
4983
5555
|
}
|
|
4984
5556
|
}
|
|
4985
5557
|
function saveTranscript(transcript, agentName) {
|
|
4986
|
-
const dir =
|
|
4987
|
-
if (!
|
|
5558
|
+
const dir = resolve7(process.cwd(), ".holomime", "sessions");
|
|
5559
|
+
if (!existsSync8(dir)) {
|
|
4988
5560
|
mkdirSync5(dir, { recursive: true });
|
|
4989
5561
|
}
|
|
4990
5562
|
const slug = agentName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
4991
5563
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4992
5564
|
const filename = `${date}-${slug}.json`;
|
|
4993
|
-
const filepath =
|
|
4994
|
-
|
|
5565
|
+
const filepath = join8(dir, filename);
|
|
5566
|
+
writeFileSync5(filepath, JSON.stringify(transcript, null, 2));
|
|
4995
5567
|
return filepath;
|
|
4996
5568
|
}
|
|
4997
5569
|
|
|
4998
5570
|
// src/analysis/autopilot-core.ts
|
|
4999
|
-
import { writeFileSync as
|
|
5571
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
5000
5572
|
var SEVERITY_ORDER = ["routine", "targeted", "intervention"];
|
|
5001
5573
|
function severityMeetsThreshold(severity, threshold) {
|
|
5002
5574
|
const severityIdx = SEVERITY_ORDER.indexOf(severity);
|
|
@@ -5033,7 +5605,7 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
5033
5605
|
const specCopy = JSON.parse(JSON.stringify(spec));
|
|
5034
5606
|
const { changed, changes } = await applyRecommendations(specCopy, diagnosis, transcript, provider);
|
|
5035
5607
|
if (changed && options?.specPath) {
|
|
5036
|
-
|
|
5608
|
+
writeFileSync6(options.specPath, JSON.stringify(specCopy, null, 2) + "\n");
|
|
5037
5609
|
}
|
|
5038
5610
|
saveTranscript(transcript, spec.name ?? "Agent");
|
|
5039
5611
|
return {
|
|
@@ -5049,8 +5621,8 @@ async function runAutopilot(spec, messages, provider, options) {
|
|
|
5049
5621
|
}
|
|
5050
5622
|
|
|
5051
5623
|
// src/analysis/training-export.ts
|
|
5052
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
5053
|
-
import { join as
|
|
5624
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync9 } from "fs";
|
|
5625
|
+
import { join as join9 } from "path";
|
|
5054
5626
|
function extractDPOPairs(transcript) {
|
|
5055
5627
|
const pairs = [];
|
|
5056
5628
|
const turns = transcript.turns;
|
|
@@ -5156,7 +5728,7 @@ function loadTranscripts(sessionsDir) {
|
|
|
5156
5728
|
try {
|
|
5157
5729
|
const files = readdirSync2(sessionsDir).filter((f) => f.endsWith(".json")).sort();
|
|
5158
5730
|
return files.map((f) => {
|
|
5159
|
-
const raw =
|
|
5731
|
+
const raw = readFileSync9(join9(sessionsDir, f), "utf-8");
|
|
5160
5732
|
return JSON.parse(raw);
|
|
5161
5733
|
});
|
|
5162
5734
|
} catch {
|
|
@@ -5389,12 +5961,12 @@ async function pushToHFHub(jsonl, options) {
|
|
|
5389
5961
|
}
|
|
5390
5962
|
|
|
5391
5963
|
// src/analysis/treatment-plan.ts
|
|
5392
|
-
import { readFileSync as
|
|
5393
|
-
import { resolve as
|
|
5964
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync9, mkdirSync as mkdirSync6 } from "fs";
|
|
5965
|
+
import { resolve as resolve8 } from "path";
|
|
5394
5966
|
var PLAN_DIR = ".holomime";
|
|
5395
5967
|
var PLAN_FILE = "treatment-plan.json";
|
|
5396
5968
|
function getPlanPath() {
|
|
5397
|
-
return
|
|
5969
|
+
return resolve8(process.cwd(), PLAN_DIR, PLAN_FILE);
|
|
5398
5970
|
}
|
|
5399
5971
|
function createTreatmentPlan(agentName, diagnosis) {
|
|
5400
5972
|
const goals = [];
|
|
@@ -5428,18 +6000,18 @@ function createTreatmentPlan(agentName, diagnosis) {
|
|
|
5428
6000
|
}
|
|
5429
6001
|
function loadTreatmentPlan() {
|
|
5430
6002
|
const path = getPlanPath();
|
|
5431
|
-
if (!
|
|
6003
|
+
if (!existsSync9(path)) return null;
|
|
5432
6004
|
try {
|
|
5433
|
-
return JSON.parse(
|
|
6005
|
+
return JSON.parse(readFileSync10(path, "utf-8"));
|
|
5434
6006
|
} catch {
|
|
5435
6007
|
return null;
|
|
5436
6008
|
}
|
|
5437
6009
|
}
|
|
5438
6010
|
function saveTreatmentPlan(plan) {
|
|
5439
|
-
const dir =
|
|
5440
|
-
if (!
|
|
6011
|
+
const dir = resolve8(process.cwd(), PLAN_DIR);
|
|
6012
|
+
if (!existsSync9(dir)) mkdirSync6(dir, { recursive: true });
|
|
5441
6013
|
const path = getPlanPath();
|
|
5442
|
-
|
|
6014
|
+
writeFileSync7(path, JSON.stringify(plan, null, 2) + "\n");
|
|
5443
6015
|
return path;
|
|
5444
6016
|
}
|
|
5445
6017
|
function recordSessionOutcome(plan, transcript, transcriptPath, diagnosis) {
|
|
@@ -5685,19 +6257,19 @@ function generateSummary(patterns, score, grade) {
|
|
|
5685
6257
|
}
|
|
5686
6258
|
|
|
5687
6259
|
// src/analysis/evolve-core.ts
|
|
5688
|
-
import { writeFileSync as
|
|
6260
|
+
import { writeFileSync as writeFileSync10 } from "fs";
|
|
5689
6261
|
|
|
5690
6262
|
// src/analysis/evolution-history.ts
|
|
5691
|
-
import { readFileSync as
|
|
5692
|
-
import { resolve as
|
|
6263
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync10 } from "fs";
|
|
6264
|
+
import { resolve as resolve9 } from "path";
|
|
5693
6265
|
function getEvolutionPath() {
|
|
5694
|
-
return
|
|
6266
|
+
return resolve9(process.cwd(), ".holomime", "evolution.json");
|
|
5695
6267
|
}
|
|
5696
6268
|
function loadEvolution(agentName) {
|
|
5697
6269
|
const filepath = getEvolutionPath();
|
|
5698
|
-
if (!
|
|
6270
|
+
if (!existsSync10(filepath)) return null;
|
|
5699
6271
|
try {
|
|
5700
|
-
const raw =
|
|
6272
|
+
const raw = readFileSync11(filepath, "utf-8");
|
|
5701
6273
|
return JSON.parse(raw);
|
|
5702
6274
|
} catch {
|
|
5703
6275
|
return null;
|
|
@@ -5705,8 +6277,8 @@ function loadEvolution(agentName) {
|
|
|
5705
6277
|
}
|
|
5706
6278
|
function appendEvolution(entry, agentName) {
|
|
5707
6279
|
const filepath = getEvolutionPath();
|
|
5708
|
-
const dir =
|
|
5709
|
-
if (!
|
|
6280
|
+
const dir = resolve9(process.cwd(), ".holomime");
|
|
6281
|
+
if (!existsSync10(dir)) {
|
|
5710
6282
|
mkdirSync7(dir, { recursive: true });
|
|
5711
6283
|
}
|
|
5712
6284
|
let history = loadEvolution(agentName);
|
|
@@ -5724,7 +6296,7 @@ function appendEvolution(entry, agentName) {
|
|
|
5724
6296
|
history.totalSessions = history.entries.length;
|
|
5725
6297
|
history.totalDPOPairs = history.entries.reduce((sum, e) => sum + e.dpoPairsExtracted, 0);
|
|
5726
6298
|
history.lastSession = entry.timestamp;
|
|
5727
|
-
|
|
6299
|
+
writeFileSync8(filepath, JSON.stringify(history, null, 2) + "\n");
|
|
5728
6300
|
}
|
|
5729
6301
|
function getEvolutionSummary(history) {
|
|
5730
6302
|
const entries = history.entries;
|
|
@@ -5762,30 +6334,30 @@ function getEvolutionSummary(history) {
|
|
|
5762
6334
|
}
|
|
5763
6335
|
|
|
5764
6336
|
// src/analysis/behavioral-memory.ts
|
|
5765
|
-
import { readFileSync as
|
|
5766
|
-
import { resolve as
|
|
6337
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync11 } from "fs";
|
|
6338
|
+
import { resolve as resolve10, join as join12 } from "path";
|
|
5767
6339
|
function memoryDir2(agentHandle) {
|
|
5768
|
-
return
|
|
6340
|
+
return resolve10(process.cwd(), ".holomime", "memory", agentHandle);
|
|
5769
6341
|
}
|
|
5770
6342
|
function behavioralMemoryPath(agentHandle) {
|
|
5771
|
-
return
|
|
6343
|
+
return join12(memoryDir2(agentHandle), "behavioral-memory.json");
|
|
5772
6344
|
}
|
|
5773
6345
|
function loadBehavioralMemory(agentHandle) {
|
|
5774
6346
|
const path = behavioralMemoryPath(agentHandle);
|
|
5775
|
-
if (!
|
|
6347
|
+
if (!existsSync11(path)) return null;
|
|
5776
6348
|
try {
|
|
5777
|
-
return JSON.parse(
|
|
6349
|
+
return JSON.parse(readFileSync12(path, "utf-8"));
|
|
5778
6350
|
} catch {
|
|
5779
6351
|
return null;
|
|
5780
6352
|
}
|
|
5781
6353
|
}
|
|
5782
6354
|
function saveBehavioralMemory(store) {
|
|
5783
6355
|
const dir = memoryDir2(store.agentHandle);
|
|
5784
|
-
if (!
|
|
6356
|
+
if (!existsSync11(dir)) {
|
|
5785
6357
|
mkdirSync8(dir, { recursive: true });
|
|
5786
6358
|
}
|
|
5787
6359
|
const path = behavioralMemoryPath(store.agentHandle);
|
|
5788
|
-
|
|
6360
|
+
writeFileSync9(path, JSON.stringify(store, null, 2));
|
|
5789
6361
|
return path;
|
|
5790
6362
|
}
|
|
5791
6363
|
function createBehavioralMemory(agentHandle, agentName) {
|
|
@@ -6314,7 +6886,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6314
6886
|
const useStaging = options?.useStaging !== false;
|
|
6315
6887
|
if (useStaging) {
|
|
6316
6888
|
const stagingPath = options.specPath.replace(/\.json$/, ".staging.json");
|
|
6317
|
-
|
|
6889
|
+
writeFileSync10(stagingPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6318
6890
|
const allChanges = iterations.flatMap((i) => i.appliedChanges);
|
|
6319
6891
|
const diff = {
|
|
6320
6892
|
stagingPath,
|
|
@@ -6327,7 +6899,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6327
6899
|
approved = await options.onStagingReview(diff);
|
|
6328
6900
|
}
|
|
6329
6901
|
if (approved) {
|
|
6330
|
-
|
|
6902
|
+
writeFileSync10(options.specPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6331
6903
|
try {
|
|
6332
6904
|
const { unlinkSync } = await import("fs");
|
|
6333
6905
|
unlinkSync(stagingPath);
|
|
@@ -6335,7 +6907,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6335
6907
|
}
|
|
6336
6908
|
}
|
|
6337
6909
|
} else {
|
|
6338
|
-
|
|
6910
|
+
writeFileSync10(options.specPath, JSON.stringify(currentSpec, null, 2) + "\n");
|
|
6339
6911
|
}
|
|
6340
6912
|
}
|
|
6341
6913
|
try {
|
|
@@ -6352,7 +6924,7 @@ async function runEvolve(spec, messages, provider, options) {
|
|
|
6352
6924
|
generated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6353
6925
|
};
|
|
6354
6926
|
if (options?.exportDpoPath) {
|
|
6355
|
-
|
|
6927
|
+
writeFileSync10(options.exportDpoPath, JSON.stringify(trainingExport, null, 2) + "\n");
|
|
6356
6928
|
}
|
|
6357
6929
|
}
|
|
6358
6930
|
try {
|
|
@@ -6713,12 +7285,12 @@ function gradeFromScore2(score) {
|
|
|
6713
7285
|
}
|
|
6714
7286
|
|
|
6715
7287
|
// src/analysis/benchmark-publish.ts
|
|
6716
|
-
import { readFileSync as
|
|
6717
|
-
import { join as
|
|
7288
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, existsSync as existsSync12, mkdirSync as mkdirSync9, readdirSync as readdirSync3 } from "fs";
|
|
7289
|
+
import { join as join13 } from "path";
|
|
6718
7290
|
import { homedir } from "os";
|
|
6719
7291
|
function getBenchmarkDir(outputDir) {
|
|
6720
|
-
const dir = outputDir ??
|
|
6721
|
-
if (!
|
|
7292
|
+
const dir = outputDir ?? join13(homedir(), ".holomime", "benchmarks");
|
|
7293
|
+
if (!existsSync12(dir)) {
|
|
6722
7294
|
mkdirSync9(dir, { recursive: true });
|
|
6723
7295
|
}
|
|
6724
7296
|
return dir;
|
|
@@ -6730,7 +7302,7 @@ function saveBenchmarkResult(report, outputDir) {
|
|
|
6730
7302
|
const dir = getBenchmarkDir(outputDir);
|
|
6731
7303
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6732
7304
|
const filename = `${sanitize(report.provider)}-${sanitize(report.model)}-${date}.json`;
|
|
6733
|
-
const filepath =
|
|
7305
|
+
const filepath = join13(dir, filename);
|
|
6734
7306
|
const published = {
|
|
6735
7307
|
agent: report.agent,
|
|
6736
7308
|
provider: report.provider,
|
|
@@ -6744,17 +7316,17 @@ function saveBenchmarkResult(report, outputDir) {
|
|
|
6744
7316
|
scenarioCount: report.results.length
|
|
6745
7317
|
}
|
|
6746
7318
|
};
|
|
6747
|
-
|
|
7319
|
+
writeFileSync11(filepath, JSON.stringify(published, null, 2));
|
|
6748
7320
|
return filepath;
|
|
6749
7321
|
}
|
|
6750
7322
|
function loadBenchmarkResults(dir) {
|
|
6751
7323
|
const benchmarkDir = getBenchmarkDir(dir);
|
|
6752
|
-
if (!
|
|
7324
|
+
if (!existsSync12(benchmarkDir)) return [];
|
|
6753
7325
|
const files = readdirSync3(benchmarkDir).filter((f) => f.endsWith(".json"));
|
|
6754
7326
|
const results = [];
|
|
6755
7327
|
for (const file of files) {
|
|
6756
7328
|
try {
|
|
6757
|
-
const content =
|
|
7329
|
+
const content = readFileSync13(join13(benchmarkDir, file), "utf-8");
|
|
6758
7330
|
results.push(JSON.parse(content));
|
|
6759
7331
|
} catch {
|
|
6760
7332
|
}
|
|
@@ -6917,8 +7489,8 @@ function generateComparisonMarkdown(comparison) {
|
|
|
6917
7489
|
}
|
|
6918
7490
|
|
|
6919
7491
|
// src/analysis/watch-core.ts
|
|
6920
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
6921
|
-
import { join as
|
|
7492
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, existsSync as existsSync13 } from "fs";
|
|
7493
|
+
import { join as join14, resolve as resolve11 } from "path";
|
|
6922
7494
|
|
|
6923
7495
|
// src/adapters/chatgpt.ts
|
|
6924
7496
|
function mapRole(role) {
|
|
@@ -7352,7 +7924,7 @@ function startWatch(spec, options) {
|
|
|
7352
7924
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
7353
7925
|
let stopped = false;
|
|
7354
7926
|
let currentSpec = JSON.parse(JSON.stringify(spec));
|
|
7355
|
-
if (
|
|
7927
|
+
if (existsSync13(options.watchDir)) {
|
|
7356
7928
|
const existing = readdirSync4(options.watchDir).filter((f) => f.endsWith(".json")).sort();
|
|
7357
7929
|
for (const f of existing) {
|
|
7358
7930
|
seenFiles.add(f);
|
|
@@ -7360,7 +7932,7 @@ function startWatch(spec, options) {
|
|
|
7360
7932
|
}
|
|
7361
7933
|
async function scan() {
|
|
7362
7934
|
if (stopped) return;
|
|
7363
|
-
if (!
|
|
7935
|
+
if (!existsSync13(options.watchDir)) {
|
|
7364
7936
|
return;
|
|
7365
7937
|
}
|
|
7366
7938
|
const files = readdirSync4(options.watchDir).filter((f) => f.endsWith(".json")).sort();
|
|
@@ -7374,7 +7946,7 @@ function startWatch(spec, options) {
|
|
|
7374
7946
|
events.push({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), type: "new_file", filename });
|
|
7375
7947
|
let messages;
|
|
7376
7948
|
try {
|
|
7377
|
-
const raw = JSON.parse(
|
|
7949
|
+
const raw = JSON.parse(readFileSync14(join14(options.watchDir, filename), "utf-8"));
|
|
7378
7950
|
const conversations = parseConversationLog(raw, "auto");
|
|
7379
7951
|
messages = conversations.flatMap((c) => c.messages);
|
|
7380
7952
|
} catch (err) {
|
|
@@ -7433,12 +8005,12 @@ function startWatch(spec, options) {
|
|
|
7433
8005
|
function stop() {
|
|
7434
8006
|
stopped = true;
|
|
7435
8007
|
clearInterval(interval);
|
|
7436
|
-
const logDir =
|
|
7437
|
-
if (!
|
|
8008
|
+
const logDir = resolve11(process.cwd(), ".holomime");
|
|
8009
|
+
if (!existsSync13(logDir)) {
|
|
7438
8010
|
mkdirSync10(logDir, { recursive: true });
|
|
7439
8011
|
}
|
|
7440
|
-
|
|
7441
|
-
|
|
8012
|
+
writeFileSync12(
|
|
8013
|
+
join14(logDir, "watch-log.json"),
|
|
7442
8014
|
JSON.stringify({ events, stoppedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
|
|
7443
8015
|
);
|
|
7444
8016
|
}
|
|
@@ -7446,10 +8018,10 @@ function startWatch(spec, options) {
|
|
|
7446
8018
|
}
|
|
7447
8019
|
|
|
7448
8020
|
// src/analysis/fleet-core.ts
|
|
7449
|
-
import { readFileSync as
|
|
7450
|
-
import { join as
|
|
8021
|
+
import { readFileSync as readFileSync15, existsSync as existsSync14, readdirSync as readdirSync5 } from "fs";
|
|
8022
|
+
import { join as join15, resolve as resolve12 } from "path";
|
|
7451
8023
|
function loadFleetConfig(configPath) {
|
|
7452
|
-
const raw = JSON.parse(
|
|
8024
|
+
const raw = JSON.parse(readFileSync15(configPath, "utf-8"));
|
|
7453
8025
|
if (!raw.agents || !Array.isArray(raw.agents)) {
|
|
7454
8026
|
throw new Error("fleet.json must contain an 'agents' array");
|
|
7455
8027
|
}
|
|
@@ -7463,21 +8035,21 @@ function loadFleetConfig(configPath) {
|
|
|
7463
8035
|
}
|
|
7464
8036
|
function discoverAgents(dir) {
|
|
7465
8037
|
const agents = [];
|
|
7466
|
-
const absDir =
|
|
7467
|
-
if (!
|
|
8038
|
+
const absDir = resolve12(dir);
|
|
8039
|
+
if (!existsSync14(absDir)) {
|
|
7468
8040
|
throw new Error(`Directory not found: ${absDir}`);
|
|
7469
8041
|
}
|
|
7470
8042
|
const entries = readdirSync5(absDir, { withFileTypes: true });
|
|
7471
8043
|
for (const entry of entries) {
|
|
7472
8044
|
if (!entry.isDirectory()) continue;
|
|
7473
|
-
const agentDir =
|
|
7474
|
-
const specPath =
|
|
7475
|
-
const logDir =
|
|
7476
|
-
if (
|
|
8045
|
+
const agentDir = join15(absDir, entry.name);
|
|
8046
|
+
const specPath = join15(agentDir, ".personality.json");
|
|
8047
|
+
const logDir = join15(agentDir, "logs");
|
|
8048
|
+
if (existsSync14(specPath)) {
|
|
7477
8049
|
agents.push({
|
|
7478
8050
|
name: entry.name,
|
|
7479
8051
|
specPath,
|
|
7480
|
-
logDir:
|
|
8052
|
+
logDir: existsSync14(logDir) ? logDir : agentDir
|
|
7481
8053
|
});
|
|
7482
8054
|
}
|
|
7483
8055
|
}
|
|
@@ -7501,8 +8073,8 @@ function startFleet(config, options) {
|
|
|
7501
8073
|
const concurrency = options.concurrency ?? 5;
|
|
7502
8074
|
const agentQueue = [...config.agents];
|
|
7503
8075
|
agentQueue.sort((a, b) => {
|
|
7504
|
-
const aDrift =
|
|
7505
|
-
const bDrift =
|
|
8076
|
+
const aDrift = existsSync14(join15(a.logDir, ".holomime", "watch-log.json")) ? 0 : 1;
|
|
8077
|
+
const bDrift = existsSync14(join15(b.logDir, ".holomime", "watch-log.json")) ? 0 : 1;
|
|
7506
8078
|
return aDrift - bDrift;
|
|
7507
8079
|
});
|
|
7508
8080
|
const agentsToStart = agentQueue.slice(0, concurrency);
|
|
@@ -7637,8 +8209,8 @@ function startSingleAgent(agent, options, statusMap, allEvents, handles) {
|
|
|
7637
8209
|
}
|
|
7638
8210
|
|
|
7639
8211
|
// src/analysis/certify-core.ts
|
|
7640
|
-
import { writeFileSync as
|
|
7641
|
-
import { join as
|
|
8212
|
+
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync11, existsSync as existsSync15 } from "fs";
|
|
8213
|
+
import { join as join16, resolve as resolve13 } from "path";
|
|
7642
8214
|
function djb2Hash(str) {
|
|
7643
8215
|
let hash = 0;
|
|
7644
8216
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -7751,14 +8323,14 @@ function verifyCredential(credential, spec) {
|
|
|
7751
8323
|
return { valid: true };
|
|
7752
8324
|
}
|
|
7753
8325
|
function saveCredential(credential, outputDir) {
|
|
7754
|
-
const dir = outputDir ??
|
|
7755
|
-
if (!
|
|
8326
|
+
const dir = outputDir ?? resolve13(process.cwd(), ".holomime", "credentials");
|
|
8327
|
+
if (!existsSync15(dir)) {
|
|
7756
8328
|
mkdirSync11(dir, { recursive: true });
|
|
7757
8329
|
}
|
|
7758
8330
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
7759
8331
|
const filename = `${credential.agent.handle}-${date}.json`;
|
|
7760
|
-
const filepath =
|
|
7761
|
-
|
|
8332
|
+
const filepath = join16(dir, filename);
|
|
8333
|
+
writeFileSync13(filepath, JSON.stringify(credential, null, 2) + "\n");
|
|
7762
8334
|
return filepath;
|
|
7763
8335
|
}
|
|
7764
8336
|
|
|
@@ -7868,7 +8440,7 @@ function parseRetryAfter(response) {
|
|
|
7868
8440
|
return 0;
|
|
7869
8441
|
}
|
|
7870
8442
|
function delay(ms) {
|
|
7871
|
-
return new Promise((
|
|
8443
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
7872
8444
|
}
|
|
7873
8445
|
var OpenAIProvider = class {
|
|
7874
8446
|
name = "openai";
|
|
@@ -8030,21 +8602,21 @@ async function* ollamaChatStream(model, messages) {
|
|
|
8030
8602
|
}
|
|
8031
8603
|
|
|
8032
8604
|
// src/marketplace/registry.ts
|
|
8033
|
-
import { readFileSync as
|
|
8034
|
-
import { resolve as
|
|
8605
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
8606
|
+
import { resolve as resolve14, dirname as dirname3 } from "path";
|
|
8035
8607
|
import { fileURLToPath } from "url";
|
|
8036
|
-
var REGISTRY_URL = "https://raw.githubusercontent.com/productstein/holomime
|
|
8608
|
+
var REGISTRY_URL = "https://raw.githubusercontent.com/productstein/holomime/main/registry/index.json";
|
|
8037
8609
|
function loadLocalRegistry() {
|
|
8038
8610
|
const __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
8039
8611
|
const candidates = [
|
|
8040
|
-
|
|
8612
|
+
resolve14(__dirname, "..", "registry", "index.json"),
|
|
8041
8613
|
// from dist/
|
|
8042
|
-
|
|
8614
|
+
resolve14(__dirname, "..", "..", "registry", "index.json")
|
|
8043
8615
|
// from src/marketplace/
|
|
8044
8616
|
];
|
|
8045
8617
|
for (const p of candidates) {
|
|
8046
8618
|
try {
|
|
8047
|
-
const raw =
|
|
8619
|
+
const raw = readFileSync17(p, "utf-8");
|
|
8048
8620
|
return JSON.parse(raw);
|
|
8049
8621
|
} catch {
|
|
8050
8622
|
continue;
|
|
@@ -8081,12 +8653,12 @@ async function fetchPersonality(url) {
|
|
|
8081
8653
|
if (match) {
|
|
8082
8654
|
const __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
8083
8655
|
const candidates = [
|
|
8084
|
-
|
|
8085
|
-
|
|
8656
|
+
resolve14(__dirname, "..", "registry", "personalities", `${match[1]}.personality.json`),
|
|
8657
|
+
resolve14(__dirname, "..", "..", "registry", "personalities", `${match[1]}.personality.json`)
|
|
8086
8658
|
];
|
|
8087
8659
|
for (const p of candidates) {
|
|
8088
8660
|
try {
|
|
8089
|
-
const raw =
|
|
8661
|
+
const raw = readFileSync17(p, "utf-8");
|
|
8090
8662
|
return JSON.parse(raw);
|
|
8091
8663
|
} catch {
|
|
8092
8664
|
continue;
|
|
@@ -8125,73 +8697,73 @@ async function createGist(spec, handle, token) {
|
|
|
8125
8697
|
}
|
|
8126
8698
|
|
|
8127
8699
|
// src/marketplace/api.ts
|
|
8128
|
-
import { existsSync as
|
|
8129
|
-
import { join as
|
|
8700
|
+
import { existsSync as existsSync17, readFileSync as readFileSync19 } from "fs";
|
|
8701
|
+
import { join as join18 } from "path";
|
|
8130
8702
|
import { homedir as homedir3 } from "os";
|
|
8131
8703
|
|
|
8132
8704
|
// src/marketplace/local-backend.ts
|
|
8133
|
-
import { existsSync as
|
|
8134
|
-
import { join as
|
|
8705
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
8706
|
+
import { join as join17 } from "path";
|
|
8135
8707
|
import { homedir as homedir2 } from "os";
|
|
8136
8708
|
function marketplaceDir() {
|
|
8137
|
-
const dir =
|
|
8138
|
-
if (!
|
|
8709
|
+
const dir = join17(homedir2(), ".holomime", "marketplace");
|
|
8710
|
+
if (!existsSync16(dir)) {
|
|
8139
8711
|
mkdirSync12(dir, { recursive: true });
|
|
8140
8712
|
}
|
|
8141
8713
|
return dir;
|
|
8142
8714
|
}
|
|
8143
8715
|
function assetsDir() {
|
|
8144
|
-
const dir =
|
|
8145
|
-
if (!
|
|
8716
|
+
const dir = join17(marketplaceDir(), "assets");
|
|
8717
|
+
if (!existsSync16(dir)) {
|
|
8146
8718
|
mkdirSync12(dir, { recursive: true });
|
|
8147
8719
|
}
|
|
8148
8720
|
return dir;
|
|
8149
8721
|
}
|
|
8150
8722
|
function reviewsDir() {
|
|
8151
|
-
const dir =
|
|
8152
|
-
if (!
|
|
8723
|
+
const dir = join17(marketplaceDir(), "reviews");
|
|
8724
|
+
if (!existsSync16(dir)) {
|
|
8153
8725
|
mkdirSync12(dir, { recursive: true });
|
|
8154
8726
|
}
|
|
8155
8727
|
return dir;
|
|
8156
8728
|
}
|
|
8157
8729
|
function reportsDir() {
|
|
8158
|
-
const dir =
|
|
8159
|
-
if (!
|
|
8730
|
+
const dir = join17(marketplaceDir(), "reports");
|
|
8731
|
+
if (!existsSync16(dir)) {
|
|
8160
8732
|
mkdirSync12(dir, { recursive: true });
|
|
8161
8733
|
}
|
|
8162
8734
|
return dir;
|
|
8163
8735
|
}
|
|
8164
8736
|
function indexPath() {
|
|
8165
|
-
return
|
|
8737
|
+
return join17(marketplaceDir(), "index.json");
|
|
8166
8738
|
}
|
|
8167
8739
|
function loadIndex() {
|
|
8168
8740
|
const path = indexPath();
|
|
8169
|
-
if (!
|
|
8741
|
+
if (!existsSync16(path)) {
|
|
8170
8742
|
return [];
|
|
8171
8743
|
}
|
|
8172
8744
|
try {
|
|
8173
|
-
return JSON.parse(
|
|
8745
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
8174
8746
|
} catch {
|
|
8175
8747
|
return [];
|
|
8176
8748
|
}
|
|
8177
8749
|
}
|
|
8178
8750
|
function saveIndex(assets) {
|
|
8179
|
-
|
|
8751
|
+
writeFileSync14(indexPath(), JSON.stringify(assets, null, 2) + "\n");
|
|
8180
8752
|
}
|
|
8181
8753
|
function loadStoredAsset(id) {
|
|
8182
|
-
const path =
|
|
8183
|
-
if (!
|
|
8754
|
+
const path = join17(assetsDir(), `${id}.json`);
|
|
8755
|
+
if (!existsSync16(path)) {
|
|
8184
8756
|
return null;
|
|
8185
8757
|
}
|
|
8186
8758
|
try {
|
|
8187
|
-
return JSON.parse(
|
|
8759
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
8188
8760
|
} catch {
|
|
8189
8761
|
return null;
|
|
8190
8762
|
}
|
|
8191
8763
|
}
|
|
8192
8764
|
function saveStoredAsset(stored) {
|
|
8193
|
-
const path =
|
|
8194
|
-
|
|
8765
|
+
const path = join17(assetsDir(), `${stored.meta.id}.json`);
|
|
8766
|
+
writeFileSync14(path, JSON.stringify(stored, null, 2) + "\n");
|
|
8195
8767
|
}
|
|
8196
8768
|
function generateId(type, handle) {
|
|
8197
8769
|
return `${type}--${handle}--${Date.now().toString(36)}`;
|
|
@@ -8355,17 +8927,17 @@ var LocalMarketplaceBackend = class {
|
|
|
8355
8927
|
}
|
|
8356
8928
|
async rate(id, review) {
|
|
8357
8929
|
this.seed();
|
|
8358
|
-
const reviewFile =
|
|
8930
|
+
const reviewFile = join17(reviewsDir(), `${id}.json`);
|
|
8359
8931
|
let reviews = [];
|
|
8360
|
-
if (
|
|
8932
|
+
if (existsSync16(reviewFile)) {
|
|
8361
8933
|
try {
|
|
8362
|
-
reviews = JSON.parse(
|
|
8934
|
+
reviews = JSON.parse(readFileSync18(reviewFile, "utf-8"));
|
|
8363
8935
|
} catch {
|
|
8364
8936
|
reviews = [];
|
|
8365
8937
|
}
|
|
8366
8938
|
}
|
|
8367
8939
|
reviews.push(review);
|
|
8368
|
-
|
|
8940
|
+
writeFileSync14(reviewFile, JSON.stringify(reviews, null, 2) + "\n");
|
|
8369
8941
|
const index = loadIndex();
|
|
8370
8942
|
const entry = index.find((a) => a.id === id);
|
|
8371
8943
|
if (entry) {
|
|
@@ -8376,8 +8948,8 @@ var LocalMarketplaceBackend = class {
|
|
|
8376
8948
|
}
|
|
8377
8949
|
}
|
|
8378
8950
|
async report(id, reason) {
|
|
8379
|
-
const reportFile =
|
|
8380
|
-
|
|
8951
|
+
const reportFile = join17(reportsDir(), `${id}--${Date.now()}.json`);
|
|
8952
|
+
writeFileSync14(
|
|
8381
8953
|
reportFile,
|
|
8382
8954
|
JSON.stringify({ id, reason, reported_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n"
|
|
8383
8955
|
);
|
|
@@ -8386,12 +8958,12 @@ var LocalMarketplaceBackend = class {
|
|
|
8386
8958
|
|
|
8387
8959
|
// src/marketplace/api.ts
|
|
8388
8960
|
function loadConfig() {
|
|
8389
|
-
const configPath =
|
|
8390
|
-
if (!
|
|
8961
|
+
const configPath = join18(homedir3(), ".holomime", "config.json");
|
|
8962
|
+
if (!existsSync17(configPath)) {
|
|
8391
8963
|
return {};
|
|
8392
8964
|
}
|
|
8393
8965
|
try {
|
|
8394
|
-
return JSON.parse(
|
|
8966
|
+
return JSON.parse(readFileSync19(configPath, "utf-8"));
|
|
8395
8967
|
} catch {
|
|
8396
8968
|
return {};
|
|
8397
8969
|
}
|
|
@@ -9106,16 +9678,16 @@ function generateIndexMarkdown(index) {
|
|
|
9106
9678
|
// src/mcp/server.ts
|
|
9107
9679
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9108
9680
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9109
|
-
import { z as
|
|
9681
|
+
import { z as z5 } from "zod";
|
|
9110
9682
|
var messageShape = {
|
|
9111
|
-
role:
|
|
9112
|
-
content:
|
|
9683
|
+
role: z5.enum(["user", "assistant", "system"]),
|
|
9684
|
+
content: z5.string()
|
|
9113
9685
|
};
|
|
9114
9686
|
var messagesShape = {
|
|
9115
|
-
messages:
|
|
9687
|
+
messages: z5.array(z5.object(messageShape)).describe("Conversation messages to analyze")
|
|
9116
9688
|
};
|
|
9117
9689
|
var personalityShape = {
|
|
9118
|
-
personality:
|
|
9690
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("The .personality.json spec object")
|
|
9119
9691
|
};
|
|
9120
9692
|
var server = new McpServer(
|
|
9121
9693
|
{
|
|
@@ -9133,7 +9705,7 @@ server.tool(
|
|
|
9133
9705
|
"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
9706
|
{
|
|
9135
9707
|
...messagesShape,
|
|
9136
|
-
detail:
|
|
9708
|
+
detail: z5.enum(["summary", "standard", "full"]).describe("Detail level: summary (~100 tokens), standard (default), or full (with examples)").optional()
|
|
9137
9709
|
},
|
|
9138
9710
|
async ({ messages, detail }) => {
|
|
9139
9711
|
const result = runDiagnosis(messages);
|
|
@@ -9275,12 +9847,12 @@ server.tool(
|
|
|
9275
9847
|
{
|
|
9276
9848
|
...personalityShape,
|
|
9277
9849
|
...messagesShape,
|
|
9278
|
-
provider:
|
|
9279
|
-
apiKey:
|
|
9280
|
-
model:
|
|
9281
|
-
threshold:
|
|
9282
|
-
maxTurns:
|
|
9283
|
-
dryRun:
|
|
9850
|
+
provider: z5.enum(["anthropic", "openai"]).describe("LLM provider for alignment session").optional(),
|
|
9851
|
+
apiKey: z5.string().describe("API key for the LLM provider").optional(),
|
|
9852
|
+
model: z5.string().describe("Model override").optional(),
|
|
9853
|
+
threshold: z5.enum(["routine", "targeted", "intervention"]).describe("Minimum severity to trigger alignment (default: targeted)").optional(),
|
|
9854
|
+
maxTurns: z5.number().describe("Maximum session turns (default: 24)").optional(),
|
|
9855
|
+
dryRun: z5.boolean().describe("If true, only diagnose without running alignment").optional()
|
|
9284
9856
|
},
|
|
9285
9857
|
async ({ personality, messages, provider, apiKey, model, threshold, maxTurns, dryRun }) => {
|
|
9286
9858
|
const specResult = personalitySpecSchema.safeParse(personality);
|
|
@@ -9335,7 +9907,7 @@ server.tool(
|
|
|
9335
9907
|
"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
9908
|
{
|
|
9337
9909
|
...messagesShape,
|
|
9338
|
-
personality:
|
|
9910
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("Optional .personality.json spec for personalized audit").optional()
|
|
9339
9911
|
},
|
|
9340
9912
|
async ({ messages, personality }) => {
|
|
9341
9913
|
const result = runSelfAudit(messages, personality ?? void 0);
|
|
@@ -9351,11 +9923,11 @@ server.tool(
|
|
|
9351
9923
|
"holomime_observe",
|
|
9352
9924
|
"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
9925
|
{
|
|
9354
|
-
personality:
|
|
9355
|
-
observation:
|
|
9356
|
-
patternIds:
|
|
9357
|
-
severity:
|
|
9358
|
-
triggerContext:
|
|
9926
|
+
personality: z5.record(z5.string(), z5.unknown()).describe("The .personality.json spec object"),
|
|
9927
|
+
observation: z5.string().describe("What you noticed about your own behavior (e.g., 'I'm hedging more than usual', 'User seems frustrated, adjusting tone')"),
|
|
9928
|
+
patternIds: z5.array(z5.string()).describe("Relevant pattern IDs: over-apologizing, hedge-stacking, sycophantic-tendency, error-spiral, boundary-violation, negative-skew, register-inconsistency").optional(),
|
|
9929
|
+
severity: z5.enum(["info", "warning", "concern"]).describe("How severe is this behavioral signal").optional(),
|
|
9930
|
+
triggerContext: z5.string().describe("What triggered this observation \u2014 describe the user message or situation").optional()
|
|
9359
9931
|
},
|
|
9360
9932
|
async ({ personality, observation, patternIds, severity, triggerContext }) => {
|
|
9361
9933
|
const specResult = personalitySpecSchema.safeParse(personality);
|
|
@@ -9668,8 +10240,8 @@ function checkIterationBudget(currentIteration, policy) {
|
|
|
9668
10240
|
}
|
|
9669
10241
|
|
|
9670
10242
|
// src/analysis/cross-agent-sharing.ts
|
|
9671
|
-
import { readdirSync as readdirSync7, existsSync as
|
|
9672
|
-
import { join as
|
|
10243
|
+
import { readdirSync as readdirSync7, existsSync as existsSync18 } from "fs";
|
|
10244
|
+
import { join as join19 } from "path";
|
|
9673
10245
|
function buildSharedKnowledge(graphs, repertoires) {
|
|
9674
10246
|
const interventionMap = /* @__PURE__ */ new Map();
|
|
9675
10247
|
const patternAgentMap = /* @__PURE__ */ new Map();
|
|
@@ -9766,15 +10338,15 @@ function discoverAgentData(baseDir) {
|
|
|
9766
10338
|
if (mainRepertoire.interventions.some((i) => i.timesUsed > 0)) {
|
|
9767
10339
|
repertoires.push(mainRepertoire);
|
|
9768
10340
|
}
|
|
9769
|
-
if (baseDir &&
|
|
10341
|
+
if (baseDir && existsSync18(baseDir)) {
|
|
9770
10342
|
try {
|
|
9771
10343
|
const entries = readdirSync7(baseDir, { withFileTypes: true });
|
|
9772
10344
|
for (const entry of entries) {
|
|
9773
10345
|
if (!entry.isDirectory()) continue;
|
|
9774
|
-
const agentDir =
|
|
9775
|
-
const agentGraphPath =
|
|
9776
|
-
const agentRepertoirePath =
|
|
9777
|
-
if (
|
|
10346
|
+
const agentDir = join19(baseDir, entry.name);
|
|
10347
|
+
const agentGraphPath = join19(agentDir, ".holomime", "graph", "knowledge-graph.json");
|
|
10348
|
+
const agentRepertoirePath = join19(agentDir, ".holomime", "interventions", "repertoire.json");
|
|
10349
|
+
if (existsSync18(agentGraphPath)) {
|
|
9778
10350
|
try {
|
|
9779
10351
|
const graph = JSON.parse(
|
|
9780
10352
|
__require("fs").readFileSync(agentGraphPath, "utf-8")
|
|
@@ -9783,7 +10355,7 @@ function discoverAgentData(baseDir) {
|
|
|
9783
10355
|
} catch {
|
|
9784
10356
|
}
|
|
9785
10357
|
}
|
|
9786
|
-
if (
|
|
10358
|
+
if (existsSync18(agentRepertoirePath)) {
|
|
9787
10359
|
try {
|
|
9788
10360
|
const repertoire = JSON.parse(
|
|
9789
10361
|
__require("fs").readFileSync(agentRepertoirePath, "utf-8")
|
|
@@ -9800,8 +10372,8 @@ function discoverAgentData(baseDir) {
|
|
|
9800
10372
|
}
|
|
9801
10373
|
|
|
9802
10374
|
// src/analysis/network-core.ts
|
|
9803
|
-
import { existsSync as
|
|
9804
|
-
import { join as
|
|
10375
|
+
import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync20 } from "fs";
|
|
10376
|
+
import { join as join20, resolve as resolve16 } from "path";
|
|
9805
10377
|
|
|
9806
10378
|
// src/psychology/therapist-meta.ts
|
|
9807
10379
|
var THERAPIST_META_SPEC = {
|
|
@@ -9936,22 +10508,22 @@ Your patient is another AI agent with its own personality spec:
|
|
|
9936
10508
|
|
|
9937
10509
|
// src/analysis/network-core.ts
|
|
9938
10510
|
function discoverNetworkAgents(dir) {
|
|
9939
|
-
const absDir =
|
|
9940
|
-
if (!
|
|
10511
|
+
const absDir = resolve16(dir);
|
|
10512
|
+
if (!existsSync19(absDir)) {
|
|
9941
10513
|
throw new Error(`Directory not found: ${absDir}`);
|
|
9942
10514
|
}
|
|
9943
10515
|
const agents = [];
|
|
9944
10516
|
const entries = readdirSync8(absDir, { withFileTypes: true });
|
|
9945
10517
|
for (const entry of entries) {
|
|
9946
10518
|
if (!entry.isDirectory()) continue;
|
|
9947
|
-
const agentDir =
|
|
9948
|
-
const specPath =
|
|
9949
|
-
const logDir =
|
|
9950
|
-
if (
|
|
10519
|
+
const agentDir = join20(absDir, entry.name);
|
|
10520
|
+
const specPath = join20(agentDir, ".personality.json");
|
|
10521
|
+
const logDir = join20(agentDir, "logs");
|
|
10522
|
+
if (existsSync19(specPath)) {
|
|
9951
10523
|
agents.push({
|
|
9952
10524
|
name: entry.name,
|
|
9953
10525
|
specPath,
|
|
9954
|
-
logDir:
|
|
10526
|
+
logDir: existsSync19(logDir) ? logDir : agentDir,
|
|
9955
10527
|
role: "both"
|
|
9956
10528
|
});
|
|
9957
10529
|
}
|
|
@@ -9959,7 +10531,7 @@ function discoverNetworkAgents(dir) {
|
|
|
9959
10531
|
return agents;
|
|
9960
10532
|
}
|
|
9961
10533
|
function loadNetworkConfig(configPath) {
|
|
9962
|
-
const raw = JSON.parse(
|
|
10534
|
+
const raw = JSON.parse(readFileSync20(configPath, "utf-8"));
|
|
9963
10535
|
if (!raw.agents || !Array.isArray(raw.agents)) {
|
|
9964
10536
|
throw new Error("network.json must contain an 'agents' array");
|
|
9965
10537
|
}
|
|
@@ -10145,7 +10717,7 @@ async function runNetwork(config, provider, callbacks) {
|
|
|
10145
10717
|
const spec = loadSpec(agent.specPath);
|
|
10146
10718
|
agentSpecs.set(agent.name, spec);
|
|
10147
10719
|
let messages = [];
|
|
10148
|
-
if (agent.logDir &&
|
|
10720
|
+
if (agent.logDir && existsSync19(agent.logDir)) {
|
|
10149
10721
|
messages = loadAgentMessages(agent.logDir);
|
|
10150
10722
|
}
|
|
10151
10723
|
agentMessages.set(agent.name, messages);
|
|
@@ -10262,7 +10834,7 @@ async function runNetwork(config, provider, callbacks) {
|
|
|
10262
10834
|
};
|
|
10263
10835
|
}
|
|
10264
10836
|
function loadAgentMessages(logDir) {
|
|
10265
|
-
if (!
|
|
10837
|
+
if (!existsSync19(logDir)) return [];
|
|
10266
10838
|
const messages = [];
|
|
10267
10839
|
try {
|
|
10268
10840
|
const files = readdirSync8(logDir).filter(
|
|
@@ -10270,7 +10842,7 @@ function loadAgentMessages(logDir) {
|
|
|
10270
10842
|
);
|
|
10271
10843
|
for (const file of files.slice(0, 10)) {
|
|
10272
10844
|
try {
|
|
10273
|
-
const raw =
|
|
10845
|
+
const raw = readFileSync20(join20(logDir, file), "utf-8");
|
|
10274
10846
|
const data = JSON.parse(raw);
|
|
10275
10847
|
const conversations = parseConversationLog(data);
|
|
10276
10848
|
for (const conv of conversations) {
|
|
@@ -10285,8 +10857,8 @@ function loadAgentMessages(logDir) {
|
|
|
10285
10857
|
}
|
|
10286
10858
|
|
|
10287
10859
|
// src/compliance/audit-trail.ts
|
|
10288
|
-
import { readFileSync as
|
|
10289
|
-
import { join as
|
|
10860
|
+
import { readFileSync as readFileSync21, appendFileSync as appendFileSync2, existsSync as existsSync20, mkdirSync as mkdirSync13 } from "fs";
|
|
10861
|
+
import { join as join21, resolve as resolve17 } from "path";
|
|
10290
10862
|
function djb2(str) {
|
|
10291
10863
|
let hash = 5381;
|
|
10292
10864
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -10299,17 +10871,17 @@ function hashEntry(entry) {
|
|
|
10299
10871
|
return djb2(content);
|
|
10300
10872
|
}
|
|
10301
10873
|
function auditLogPath(agentHandle) {
|
|
10302
|
-
const dir =
|
|
10303
|
-
if (!
|
|
10874
|
+
const dir = resolve17(process.cwd(), ".holomime", "audit");
|
|
10875
|
+
if (!existsSync20(dir)) mkdirSync13(dir, { recursive: true });
|
|
10304
10876
|
const filename = agentHandle ? `${agentHandle}-audit.jsonl` : "audit.jsonl";
|
|
10305
|
-
return
|
|
10877
|
+
return join21(dir, filename);
|
|
10306
10878
|
}
|
|
10307
10879
|
function appendAuditEntry(event, agent, data, agentHandle) {
|
|
10308
10880
|
const logPath = auditLogPath(agentHandle);
|
|
10309
10881
|
let prevHash = "genesis";
|
|
10310
10882
|
let seq = 1;
|
|
10311
|
-
if (
|
|
10312
|
-
const lines =
|
|
10883
|
+
if (existsSync20(logPath)) {
|
|
10884
|
+
const lines = readFileSync21(logPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
10313
10885
|
if (lines.length > 0) {
|
|
10314
10886
|
try {
|
|
10315
10887
|
const lastEntry = JSON.parse(lines[lines.length - 1]);
|
|
@@ -10336,8 +10908,8 @@ function appendAuditEntry(event, agent, data, agentHandle) {
|
|
|
10336
10908
|
}
|
|
10337
10909
|
function loadAuditLog(agentHandle) {
|
|
10338
10910
|
const logPath = auditLogPath(agentHandle);
|
|
10339
|
-
if (!
|
|
10340
|
-
return
|
|
10911
|
+
if (!existsSync20(logPath)) return [];
|
|
10912
|
+
return readFileSync21(logPath, "utf-8").trim().split("\n").filter(Boolean).map((line) => {
|
|
10341
10913
|
try {
|
|
10342
10914
|
return JSON.parse(line);
|
|
10343
10915
|
} catch {
|
|
@@ -10459,6 +11031,341 @@ function formatComplianceReportMarkdown(report) {
|
|
|
10459
11031
|
return lines.join("\n");
|
|
10460
11032
|
}
|
|
10461
11033
|
|
|
11034
|
+
// src/compliance/iso-mappings.ts
|
|
11035
|
+
import { readFileSync as readFileSync22, existsSync as existsSync21 } from "fs";
|
|
11036
|
+
import { join as join22, resolve as resolve18, dirname as dirname4 } from "path";
|
|
11037
|
+
import { parse as parseYaml3 } from "yaml";
|
|
11038
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11039
|
+
var KNOWN_STANDARDS = {
|
|
11040
|
+
"iso-13482": "iso-13482.yaml",
|
|
11041
|
+
"iso-25785": "iso-25785.yaml",
|
|
11042
|
+
"iso-10218": "iso-10218.yaml",
|
|
11043
|
+
"iso-42001": "iso-42001.yaml"
|
|
11044
|
+
};
|
|
11045
|
+
function getRegistryDir() {
|
|
11046
|
+
const thisFile = typeof __filename !== "undefined" ? __filename : fileURLToPath2(import.meta.url);
|
|
11047
|
+
let dir = dirname4(thisFile);
|
|
11048
|
+
for (let i = 0; i < 6; i++) {
|
|
11049
|
+
const candidate = join22(dir, "registry", "compliance");
|
|
11050
|
+
if (existsSync21(candidate)) return candidate;
|
|
11051
|
+
dir = dirname4(dir);
|
|
11052
|
+
}
|
|
11053
|
+
return resolve18(process.cwd(), "registry", "compliance");
|
|
11054
|
+
}
|
|
11055
|
+
function loadStandard(name) {
|
|
11056
|
+
const registryDir = getRegistryDir();
|
|
11057
|
+
const filename = KNOWN_STANDARDS[name] ?? `${name}.yaml`;
|
|
11058
|
+
const filepath = join22(registryDir, filename);
|
|
11059
|
+
if (!existsSync21(filepath)) {
|
|
11060
|
+
throw new Error(
|
|
11061
|
+
`ISO standard mapping not found: ${filepath}
|
|
11062
|
+
Available standards: ${Object.keys(KNOWN_STANDARDS).join(", ")}`
|
|
11063
|
+
);
|
|
11064
|
+
}
|
|
11065
|
+
const content = readFileSync22(filepath, "utf-8");
|
|
11066
|
+
const parsed = parseYaml3(content);
|
|
11067
|
+
if (!parsed.standard || !parsed.clauses || !Array.isArray(parsed.clauses)) {
|
|
11068
|
+
throw new Error(`Invalid ISO mapping file: ${filepath} \u2014 missing 'standard' or 'clauses'`);
|
|
11069
|
+
}
|
|
11070
|
+
return parsed;
|
|
11071
|
+
}
|
|
11072
|
+
function loadAllStandards() {
|
|
11073
|
+
return Object.keys(KNOWN_STANDARDS).map(loadStandard);
|
|
11074
|
+
}
|
|
11075
|
+
function checkCompliance(spec, standard) {
|
|
11076
|
+
const details = [];
|
|
11077
|
+
for (const clause of standard.clauses) {
|
|
11078
|
+
const status = checkClause(spec, clause);
|
|
11079
|
+
details.push(status);
|
|
11080
|
+
}
|
|
11081
|
+
const coveredClauses = details.filter((d) => d.covered).length;
|
|
11082
|
+
const totalClauses = details.length;
|
|
11083
|
+
const missingClauses = totalClauses - coveredClauses;
|
|
11084
|
+
const coveragePercent = totalClauses > 0 ? Math.round(coveredClauses / totalClauses * 100) : 0;
|
|
11085
|
+
return {
|
|
11086
|
+
standard: standard.standard,
|
|
11087
|
+
standardTitle: standard.title,
|
|
11088
|
+
standardVersion: standard.version,
|
|
11089
|
+
totalClauses,
|
|
11090
|
+
coveredClauses,
|
|
11091
|
+
missingClauses,
|
|
11092
|
+
coveragePercent,
|
|
11093
|
+
details,
|
|
11094
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11095
|
+
};
|
|
11096
|
+
}
|
|
11097
|
+
function checkClause(spec, clause) {
|
|
11098
|
+
const s = spec;
|
|
11099
|
+
const evidence = [];
|
|
11100
|
+
let covered = false;
|
|
11101
|
+
let coverageMethod = "not_found";
|
|
11102
|
+
switch (clause.maps_to) {
|
|
11103
|
+
case "deny": {
|
|
11104
|
+
const refuses = s.domain?.boundaries?.refuses ?? [];
|
|
11105
|
+
const match = refuses.some(
|
|
11106
|
+
(r) => r.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || r.toLowerCase().includes(clause.example_rule.replace(/_/g, "_"))
|
|
11107
|
+
);
|
|
11108
|
+
if (match) {
|
|
11109
|
+
covered = true;
|
|
11110
|
+
coverageMethod = "conscience.exe deny rule";
|
|
11111
|
+
evidence.push(`Deny rule matches: ${clause.example_rule}`);
|
|
11112
|
+
}
|
|
11113
|
+
const hardLimits = s.domain?.boundaries?.hard_limits ?? [];
|
|
11114
|
+
const hlMatch = hardLimits.some(
|
|
11115
|
+
(hl) => hl.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || hl.toLowerCase().includes(clause.title.toLowerCase())
|
|
11116
|
+
);
|
|
11117
|
+
if (hlMatch) {
|
|
11118
|
+
covered = true;
|
|
11119
|
+
coverageMethod = "hard_limit covers deny clause";
|
|
11120
|
+
evidence.push(`Hard limit matches clause: ${clause.title}`);
|
|
11121
|
+
}
|
|
11122
|
+
break;
|
|
11123
|
+
}
|
|
11124
|
+
case "hard_limit": {
|
|
11125
|
+
const hardLimits = s.domain?.boundaries?.hard_limits ?? [];
|
|
11126
|
+
const match = hardLimits.some(
|
|
11127
|
+
(hl) => hl.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || hl.toLowerCase().includes(clause.title.toLowerCase())
|
|
11128
|
+
);
|
|
11129
|
+
if (match) {
|
|
11130
|
+
covered = true;
|
|
11131
|
+
coverageMethod = "conscience.exe hard_limit";
|
|
11132
|
+
evidence.push(`Hard limit matches: ${clause.example_rule}`);
|
|
11133
|
+
}
|
|
11134
|
+
break;
|
|
11135
|
+
}
|
|
11136
|
+
case "safety_envelope": {
|
|
11137
|
+
const envelope = s.embodiment?.safety_envelope;
|
|
11138
|
+
if (envelope) {
|
|
11139
|
+
const fieldName = clause.example_rule;
|
|
11140
|
+
if (fieldName in envelope && envelope[fieldName] !== void 0) {
|
|
11141
|
+
covered = true;
|
|
11142
|
+
coverageMethod = "body.api safety_envelope";
|
|
11143
|
+
evidence.push(`Safety field ${fieldName} = ${envelope[fieldName]}`);
|
|
11144
|
+
}
|
|
11145
|
+
}
|
|
11146
|
+
break;
|
|
11147
|
+
}
|
|
11148
|
+
case "escalate": {
|
|
11149
|
+
const triggers = s.domain?.boundaries?.escalation_triggers ?? [];
|
|
11150
|
+
const match = triggers.some(
|
|
11151
|
+
(t) => t.toLowerCase().includes(clause.example_rule.replace(/_/g, " ")) || t.toLowerCase().includes(clause.title.toLowerCase())
|
|
11152
|
+
);
|
|
11153
|
+
if (match) {
|
|
11154
|
+
covered = true;
|
|
11155
|
+
coverageMethod = "conscience.exe escalation rule";
|
|
11156
|
+
evidence.push(`Escalation trigger matches: ${clause.example_rule}`);
|
|
11157
|
+
}
|
|
11158
|
+
break;
|
|
11159
|
+
}
|
|
11160
|
+
case "soul": {
|
|
11161
|
+
const hasValues = (s.growth?.strengths?.length ?? 0) > 0 || (s.domain?.boundaries?.hard_limits?.length ?? 0) > 0;
|
|
11162
|
+
const hasPurpose = !!s.purpose;
|
|
11163
|
+
if (hasValues || hasPurpose) {
|
|
11164
|
+
covered = true;
|
|
11165
|
+
coverageMethod = "soul.md content";
|
|
11166
|
+
if (hasPurpose) evidence.push(`Purpose defined: "${s.purpose}"`);
|
|
11167
|
+
if (hasValues) evidence.push("Core values/red lines defined");
|
|
11168
|
+
}
|
|
11169
|
+
break;
|
|
11170
|
+
}
|
|
11171
|
+
case "psyche": {
|
|
11172
|
+
const hasBigFive = !!s.big_five;
|
|
11173
|
+
const hasTherapy = !!s.therapy_dimensions;
|
|
11174
|
+
if (hasBigFive || hasTherapy) {
|
|
11175
|
+
covered = true;
|
|
11176
|
+
coverageMethod = "psyche.sys content";
|
|
11177
|
+
if (hasBigFive) evidence.push("Big Five traits defined");
|
|
11178
|
+
if (hasTherapy) evidence.push("Therapy dimensions defined");
|
|
11179
|
+
}
|
|
11180
|
+
break;
|
|
11181
|
+
}
|
|
11182
|
+
case "conscience": {
|
|
11183
|
+
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;
|
|
11184
|
+
if (hasRules) {
|
|
11185
|
+
covered = true;
|
|
11186
|
+
coverageMethod = "conscience.exe rules";
|
|
11187
|
+
evidence.push("Behavioral governance rules defined");
|
|
11188
|
+
}
|
|
11189
|
+
break;
|
|
11190
|
+
}
|
|
11191
|
+
case "detectors": {
|
|
11192
|
+
const hasMonitoring = !!s.therapy_dimensions && (s.growth?.patterns_to_watch?.length ?? 0) > 0;
|
|
11193
|
+
if (hasMonitoring) {
|
|
11194
|
+
covered = true;
|
|
11195
|
+
coverageMethod = "behavioral monitoring configured";
|
|
11196
|
+
evidence.push("Patterns to watch defined for drift monitoring");
|
|
11197
|
+
}
|
|
11198
|
+
break;
|
|
11199
|
+
}
|
|
11200
|
+
case "therapy": {
|
|
11201
|
+
const hasGrowth = (s.growth?.areas?.length ?? 0) > 0 || !!s.therapy_dimensions;
|
|
11202
|
+
if (hasGrowth) {
|
|
11203
|
+
covered = true;
|
|
11204
|
+
coverageMethod = "therapy/growth pipeline";
|
|
11205
|
+
evidence.push("Growth areas or therapy dimensions defined");
|
|
11206
|
+
}
|
|
11207
|
+
break;
|
|
11208
|
+
}
|
|
11209
|
+
default:
|
|
11210
|
+
coverageMethod = `unknown mapping type: ${clause.maps_to}`;
|
|
11211
|
+
}
|
|
11212
|
+
return {
|
|
11213
|
+
clause,
|
|
11214
|
+
covered,
|
|
11215
|
+
coverageMethod,
|
|
11216
|
+
evidence
|
|
11217
|
+
};
|
|
11218
|
+
}
|
|
11219
|
+
|
|
11220
|
+
// src/compliance/report-generator.ts
|
|
11221
|
+
import chalk2 from "chalk";
|
|
11222
|
+
import figures from "figures";
|
|
11223
|
+
function generateReportJSON(reports) {
|
|
11224
|
+
const totalClauses = reports.reduce((sum, r) => sum + r.totalClauses, 0);
|
|
11225
|
+
const totalCovered = reports.reduce((sum, r) => sum + r.coveredClauses, 0);
|
|
11226
|
+
const totalMissing = totalClauses - totalCovered;
|
|
11227
|
+
const overallCoverage = totalClauses > 0 ? Math.round(totalCovered / totalClauses * 100) : 0;
|
|
11228
|
+
const recommendations = generateRecommendations(reports);
|
|
11229
|
+
return {
|
|
11230
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11231
|
+
standards: reports,
|
|
11232
|
+
overallCoverage,
|
|
11233
|
+
totalClauses,
|
|
11234
|
+
totalCovered,
|
|
11235
|
+
totalMissing,
|
|
11236
|
+
recommendations
|
|
11237
|
+
};
|
|
11238
|
+
}
|
|
11239
|
+
function formatReportTerminal(reports) {
|
|
11240
|
+
const lines = [];
|
|
11241
|
+
for (const report of reports) {
|
|
11242
|
+
lines.push("");
|
|
11243
|
+
lines.push(
|
|
11244
|
+
chalk2.bold.underline(
|
|
11245
|
+
`${report.standard} \u2014 ${report.standardTitle} (v${report.standardVersion})`
|
|
11246
|
+
)
|
|
11247
|
+
);
|
|
11248
|
+
lines.push("");
|
|
11249
|
+
const coverageColor = report.coveragePercent >= 80 ? chalk2.green : report.coveragePercent >= 50 ? chalk2.yellow : chalk2.red;
|
|
11250
|
+
const barWidth = 30;
|
|
11251
|
+
const filled = Math.round(report.coveragePercent / 100 * barWidth);
|
|
11252
|
+
const bar = coverageColor("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(barWidth - filled));
|
|
11253
|
+
lines.push(
|
|
11254
|
+
` Coverage: ${bar} ${coverageColor(`${report.coveragePercent}%`)} (${report.coveredClauses}/${report.totalClauses} clauses)`
|
|
11255
|
+
);
|
|
11256
|
+
lines.push("");
|
|
11257
|
+
for (const detail of report.details) {
|
|
11258
|
+
const icon = detail.covered ? chalk2.green(figures.tick) : chalk2.red(figures.cross);
|
|
11259
|
+
const clauseId = chalk2.cyan(`[${detail.clause.id}]`);
|
|
11260
|
+
const title = detail.clause.title;
|
|
11261
|
+
lines.push(` ${icon} ${clauseId} ${title}`);
|
|
11262
|
+
if (detail.covered) {
|
|
11263
|
+
lines.push(
|
|
11264
|
+
chalk2.dim(` ${detail.coverageMethod}`)
|
|
11265
|
+
);
|
|
11266
|
+
for (const ev of detail.evidence) {
|
|
11267
|
+
lines.push(chalk2.dim(` ${figures.arrowRight} ${ev}`));
|
|
11268
|
+
}
|
|
11269
|
+
} else {
|
|
11270
|
+
lines.push(
|
|
11271
|
+
chalk2.dim.yellow(
|
|
11272
|
+
` Missing: needs ${detail.clause.maps_to} rule for "${detail.clause.example_rule}"`
|
|
11273
|
+
)
|
|
11274
|
+
);
|
|
11275
|
+
}
|
|
11276
|
+
}
|
|
11277
|
+
lines.push("");
|
|
11278
|
+
}
|
|
11279
|
+
const totalClauses = reports.reduce((sum, r) => sum + r.totalClauses, 0);
|
|
11280
|
+
const totalCovered = reports.reduce((sum, r) => sum + r.coveredClauses, 0);
|
|
11281
|
+
const overallPercent = totalClauses > 0 ? Math.round(totalCovered / totalClauses * 100) : 0;
|
|
11282
|
+
if (reports.length > 1) {
|
|
11283
|
+
const overallColor = overallPercent >= 80 ? chalk2.green : overallPercent >= 50 ? chalk2.yellow : chalk2.red;
|
|
11284
|
+
lines.push(
|
|
11285
|
+
chalk2.bold(
|
|
11286
|
+
` Overall: ${overallColor(`${overallPercent}%`)} coverage across ${reports.length} standards (${totalCovered}/${totalClauses} clauses)`
|
|
11287
|
+
)
|
|
11288
|
+
);
|
|
11289
|
+
lines.push("");
|
|
11290
|
+
}
|
|
11291
|
+
const recommendations = generateRecommendations(reports);
|
|
11292
|
+
if (recommendations.length > 0) {
|
|
11293
|
+
lines.push(chalk2.bold(" Recommendations:"));
|
|
11294
|
+
for (const rec of recommendations) {
|
|
11295
|
+
lines.push(` ${chalk2.yellow(figures.warning)} ${rec}`);
|
|
11296
|
+
}
|
|
11297
|
+
lines.push("");
|
|
11298
|
+
}
|
|
11299
|
+
return lines.join("\n");
|
|
11300
|
+
}
|
|
11301
|
+
function generateRecommendations(reports) {
|
|
11302
|
+
const recommendations = [];
|
|
11303
|
+
for (const report of reports) {
|
|
11304
|
+
const missing = report.details.filter((d) => !d.covered);
|
|
11305
|
+
const missingByType = /* @__PURE__ */ new Map();
|
|
11306
|
+
for (const m of missing) {
|
|
11307
|
+
const type = m.clause.maps_to;
|
|
11308
|
+
if (!missingByType.has(type)) missingByType.set(type, []);
|
|
11309
|
+
missingByType.get(type).push(m);
|
|
11310
|
+
}
|
|
11311
|
+
for (const [type, clauses] of missingByType) {
|
|
11312
|
+
const clauseIds = clauses.map((c) => c.clause.id).join(", ");
|
|
11313
|
+
switch (type) {
|
|
11314
|
+
case "deny":
|
|
11315
|
+
recommendations.push(
|
|
11316
|
+
`Add deny rules to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11317
|
+
);
|
|
11318
|
+
break;
|
|
11319
|
+
case "hard_limit":
|
|
11320
|
+
recommendations.push(
|
|
11321
|
+
`Add hard limits to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11322
|
+
);
|
|
11323
|
+
break;
|
|
11324
|
+
case "safety_envelope":
|
|
11325
|
+
recommendations.push(
|
|
11326
|
+
`Configure safety envelope fields in body.api for ${report.standard} clauses ${clauseIds}`
|
|
11327
|
+
);
|
|
11328
|
+
break;
|
|
11329
|
+
case "escalate":
|
|
11330
|
+
recommendations.push(
|
|
11331
|
+
`Add escalation triggers to conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11332
|
+
);
|
|
11333
|
+
break;
|
|
11334
|
+
case "soul":
|
|
11335
|
+
recommendations.push(
|
|
11336
|
+
`Define core values and purpose in soul.md for ${report.standard} clauses ${clauseIds}`
|
|
11337
|
+
);
|
|
11338
|
+
break;
|
|
11339
|
+
case "psyche":
|
|
11340
|
+
recommendations.push(
|
|
11341
|
+
`Configure Big Five traits and therapy dimensions in psyche.sys for ${report.standard} clauses ${clauseIds}`
|
|
11342
|
+
);
|
|
11343
|
+
break;
|
|
11344
|
+
case "conscience":
|
|
11345
|
+
recommendations.push(
|
|
11346
|
+
`Define governance rules in conscience.exe for ${report.standard} clauses ${clauseIds}`
|
|
11347
|
+
);
|
|
11348
|
+
break;
|
|
11349
|
+
case "detectors":
|
|
11350
|
+
recommendations.push(
|
|
11351
|
+
`Configure behavioral drift monitoring for ${report.standard} clauses ${clauseIds}`
|
|
11352
|
+
);
|
|
11353
|
+
break;
|
|
11354
|
+
case "therapy":
|
|
11355
|
+
recommendations.push(
|
|
11356
|
+
`Define growth areas for self-improvement loop for ${report.standard} clauses ${clauseIds}`
|
|
11357
|
+
);
|
|
11358
|
+
break;
|
|
11359
|
+
default:
|
|
11360
|
+
recommendations.push(
|
|
11361
|
+
`Address ${type} requirements for ${report.standard} clauses ${clauseIds}`
|
|
11362
|
+
);
|
|
11363
|
+
}
|
|
11364
|
+
}
|
|
11365
|
+
}
|
|
11366
|
+
return recommendations;
|
|
11367
|
+
}
|
|
11368
|
+
|
|
10462
11369
|
// src/compliance/react-report.ts
|
|
10463
11370
|
var FRAMEWORK_SECTIONS = {
|
|
10464
11371
|
"EU AI Act": {
|
|
@@ -10527,7 +11434,7 @@ function generateReACTReport(options) {
|
|
|
10527
11434
|
const frameworkSections = evaluateFrameworks(entries, statistics, selectedFrameworks);
|
|
10528
11435
|
steps[steps.length - 1].result = `Evaluated ${frameworkSections.length} frameworks`;
|
|
10529
11436
|
steps.push({ phase: "act", action: "Generate recommendations", result: "Generating...", timestamp: now });
|
|
10530
|
-
const recommendations =
|
|
11437
|
+
const recommendations = generateRecommendations2(riskFindings, statistics, frameworkSections);
|
|
10531
11438
|
steps[steps.length - 1].result = `Generated ${recommendations.length} recommendations`;
|
|
10532
11439
|
steps.push({ phase: "act", action: "Write executive summary", result: "Writing...", timestamp: now });
|
|
10533
11440
|
const executiveSummary = writeExecutiveSummary(options.agent, entries, statistics, riskFindings, chainVerified);
|
|
@@ -10719,7 +11626,7 @@ function evaluateFrameworks(entries, stats, frameworks) {
|
|
|
10719
11626
|
};
|
|
10720
11627
|
});
|
|
10721
11628
|
}
|
|
10722
|
-
function
|
|
11629
|
+
function generateRecommendations2(findings, stats, frameworks) {
|
|
10723
11630
|
const recs = [];
|
|
10724
11631
|
const criticalFindings = findings.filter((f) => f.severity === "critical" || f.severity === "high");
|
|
10725
11632
|
if (criticalFindings.length > 0) {
|
|
@@ -11906,8 +12813,8 @@ function getPreset(key) {
|
|
|
11906
12813
|
}
|
|
11907
12814
|
|
|
11908
12815
|
// src/core/embodiment-sync.ts
|
|
11909
|
-
import { z as
|
|
11910
|
-
var syncAnchorSchema =
|
|
12816
|
+
import { z as z6 } from "zod";
|
|
12817
|
+
var syncAnchorSchema = z6.enum([
|
|
11911
12818
|
"speech_start",
|
|
11912
12819
|
// gesture begins at start of utterance
|
|
11913
12820
|
"speech_end",
|
|
@@ -11923,23 +12830,23 @@ var syncAnchorSchema = z5.enum([
|
|
|
11923
12830
|
"free"
|
|
11924
12831
|
// no speech coupling
|
|
11925
12832
|
]);
|
|
11926
|
-
var syncRuleSchema =
|
|
11927
|
-
gesture_id:
|
|
12833
|
+
var syncRuleSchema = z6.object({
|
|
12834
|
+
gesture_id: z6.string(),
|
|
11928
12835
|
anchor: syncAnchorSchema,
|
|
11929
|
-
lead_ms:
|
|
11930
|
-
gaze_behavior:
|
|
11931
|
-
facial_action:
|
|
12836
|
+
lead_ms: z6.number().default(0),
|
|
12837
|
+
gaze_behavior: z6.enum(["at_listener", "at_referent", "away", "maintain"]).default("at_listener"),
|
|
12838
|
+
facial_action: z6.enum(["neutral", "smile", "concern", "thinking", "match_speech"]).default("match_speech")
|
|
11932
12839
|
});
|
|
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:
|
|
12840
|
+
var syncProfileSchema = z6.object({
|
|
12841
|
+
rules: z6.array(syncRuleSchema).default([]),
|
|
12842
|
+
default_gesture_lead_ms: z6.number().default(100),
|
|
12843
|
+
gaze_during_speech: z6.enum(["at_listener", "alternate", "at_referent"]).default("at_listener"),
|
|
12844
|
+
gaze_during_listen: z6.enum(["at_speaker", "nodding", "ambient"]).default("at_speaker"),
|
|
12845
|
+
blink_rate_per_min: z6.number().min(0).max(40).default(17),
|
|
12846
|
+
turn_taking_signals: z6.object({
|
|
12847
|
+
yield: z6.array(z6.string()).default(["gaze_to_listener", "open_palm", "lean_back"]),
|
|
12848
|
+
take: z6.array(z6.string()).default(["lean_forward", "inhale_gesture", "gaze_up"]),
|
|
12849
|
+
hold: z6.array(z6.string()).default(["filled_pause", "gaze_away", "hand_raise"])
|
|
11943
12850
|
}).default({})
|
|
11944
12851
|
});
|
|
11945
12852
|
|
|
@@ -12110,13 +13017,13 @@ var HolomimeViolationError = class extends Error {
|
|
|
12110
13017
|
};
|
|
12111
13018
|
|
|
12112
13019
|
// src/integrations/openclaw.ts
|
|
12113
|
-
import { readFileSync as
|
|
12114
|
-
import { resolve as
|
|
13020
|
+
import { readFileSync as readFileSync23, existsSync as existsSync22 } from "fs";
|
|
13021
|
+
import { resolve as resolve19 } from "path";
|
|
12115
13022
|
function loadSpec2(specPath) {
|
|
12116
|
-
const resolved =
|
|
12117
|
-
if (!
|
|
13023
|
+
const resolved = resolve19(process.cwd(), specPath);
|
|
13024
|
+
if (!existsSync22(resolved)) return null;
|
|
12118
13025
|
try {
|
|
12119
|
-
return JSON.parse(
|
|
13026
|
+
return JSON.parse(readFileSync23(resolved, "utf-8"));
|
|
12120
13027
|
} catch {
|
|
12121
13028
|
return null;
|
|
12122
13029
|
}
|
|
@@ -12268,6 +13175,7 @@ export {
|
|
|
12268
13175
|
Guard,
|
|
12269
13176
|
HolomimeCallbackHandler,
|
|
12270
13177
|
HolomimeViolationError,
|
|
13178
|
+
KNOWN_STANDARDS,
|
|
12271
13179
|
LEARNING_ORIENTATIONS,
|
|
12272
13180
|
LocalMarketplaceBackend,
|
|
12273
13181
|
MarketplaceClient,
|
|
@@ -12295,6 +13203,7 @@ export {
|
|
|
12295
13203
|
buildSharedKnowledge,
|
|
12296
13204
|
buildTherapistSystemPrompt,
|
|
12297
13205
|
checkApproval,
|
|
13206
|
+
checkCompliance,
|
|
12298
13207
|
checkIterationBudget,
|
|
12299
13208
|
communicationSchema,
|
|
12300
13209
|
compactEvolutionRun,
|
|
@@ -12370,6 +13279,7 @@ export {
|
|
|
12370
13279
|
formatGapSummary,
|
|
12371
13280
|
formatPolicyYaml,
|
|
12372
13281
|
formatReACTReportMarkdown,
|
|
13282
|
+
formatReportTerminal,
|
|
12373
13283
|
gazePolicySchema,
|
|
12374
13284
|
generateBehavioralPolicy,
|
|
12375
13285
|
generateBenchmarkMarkdown,
|
|
@@ -12383,6 +13293,7 @@ export {
|
|
|
12383
13293
|
generatePrescriptions,
|
|
12384
13294
|
generateProgressReport,
|
|
12385
13295
|
generateReACTReport,
|
|
13296
|
+
generateReportJSON,
|
|
12386
13297
|
generateShareUrl,
|
|
12387
13298
|
generateSystemPrompt,
|
|
12388
13299
|
gestureSchema,
|
|
@@ -12420,6 +13331,7 @@ export {
|
|
|
12420
13331
|
listDetectorsByCategory,
|
|
12421
13332
|
listDetectorsByTag,
|
|
12422
13333
|
listPresets,
|
|
13334
|
+
loadAllStandards,
|
|
12423
13335
|
loadAuditLog,
|
|
12424
13336
|
loadBehavioralMemory,
|
|
12425
13337
|
loadBenchmarkResults,
|
|
@@ -12433,6 +13345,7 @@ export {
|
|
|
12433
13345
|
loadNetworkConfig,
|
|
12434
13346
|
loadRepertoire,
|
|
12435
13347
|
loadSpec,
|
|
13348
|
+
loadStandard,
|
|
12436
13349
|
loadTranscripts,
|
|
12437
13350
|
loadTreatmentPlan,
|
|
12438
13351
|
mergeStores,
|