diff --git a/adapters/java/pom.xml b/adapters/java/pom.xml
new file mode 100644
index 0000000..db54d10
--- /dev/null
+++ b/adapters/java/pom.xml
@@ -0,0 +1,21 @@
+
+
+ 4.0.0
+ cn.uid9622.longhun
+ lh-standard-adapter
+ 1.0.0
+ LongHun Standard Adapter
+ v∞ DNA traceability + seven-factor behavioral audit for Java/Kotlin
+
+ 8
+ 8
+ UTF-8
+
+
+ com.fasterxml.jackson.corejackson-databind2.15.3
+ org.junit.jupiterjunit-jupiter5.10.0test
+
+ org.apache.maven.pluginsmaven-surefire-plugin3.1.2
+
diff --git a/adapters/java/src/main/java/cn/uid9622/longhun/AuditWrapper.java b/adapters/java/src/main/java/cn/uid9622/longhun/AuditWrapper.java
new file mode 100644
index 0000000..314682c
--- /dev/null
+++ b/adapters/java/src/main/java/cn/uid9622/longhun/AuditWrapper.java
@@ -0,0 +1,85 @@
+package cn.uid9622.longhun;
+
+import java.security.MessageDigest;
+import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
+
+public class AuditWrapper {
+ private static final Map> LABEL_MAP = new LinkedHashMap<>();
+ static {
+ LABEL_MAP.put("P", Map.of("HasPromise","7F-P-有承诺","NoPromise","7F-P-无承诺"));
+ LABEL_MAP.put("F", Map.of("Fulfilled","7F-F-已兑现","Unfulfilled","7F-F-未兑现","Partial","7F-F-部分兑现"));
+ LABEL_MAP.put("E", Map.of("Willing","7F-E-心甘情愿","Perfunctory","7F-E-敷衍","Resentful","7F-E-怨恨","Numb","7F-E-麻木"));
+ LABEL_MAP.put("A", Map.of("Self","7F-A-自己","Partner","7F-A-伴侣","Family","7F-A-家庭","Outsider","7F-A-外人","Public","7F-A-公众"));
+ LABEL_MAP.put("X", Map.of("OverExplain","7F-X-过度解释","Silent","7F-X-沉默","Genuine","7F-X-真诚","Indifferent","7F-X-冷漠"));
+ LABEL_MAP.put("Y", Map.of("Changed","7F-Y-改正","Resisted","7F-Y-抗拒","Indifferent","7F-Y-无视","NoResponse","7F-Y-无响应"));
+ }
+
+ private final String uid;
+ public AuditWrapper(String uid) { this.uid = uid != null ? uid : "9622"; }
+
+ public Map wrap(Object payload, String taskType, String persona) {
+ if (taskType == null || taskType.isEmpty()) taskType = "default";
+ if (persona == null || persona.isEmpty()) persona = "P04";
+
+ Map sig = new LinkedHashMap<>();
+ sig.put("P","HasPromise"); sig.put("F","Fulfilled"); sig.put("T",0.0);
+ sig.put("E","Willing"); sig.put("C",0); sig.put("R",0);
+ sig.put("A","Self"); sig.put("X","Genuine"); sig.put("Y","NoResponse"); sig.put("Z",1.0);
+
+ String pattern = classify(sig);
+ List labels = makeLabels(sig, pattern);
+ String color = determineColor(pattern, (int)sig.get("R"));
+
+ Map result = new LinkedHashMap<>();
+ result.put("audit_version","v1.0");
+ result.put("uid","UID"+uid);
+ result.put("persona",persona);
+ result.put("task_type",taskType);
+ result.put("behavior_signature",sig);
+ result.put("behavior_pattern",pattern);
+ result.put("behavior_labels",labels);
+ result.put("color",color);
+ result.put("timestamp", ZonedDateTime.now(ZoneOffset.UTC).toString());
+
+ try {
+ String pj = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(payload);
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ byte[] h = md.digest(pj.getBytes("UTF-8"));
+ StringBuilder sb = new StringBuilder();
+ for (byte b : h) sb.append(String.format("%02x", b));
+ result.put("payload_hash", sb.toString().substring(0,16));
+ } catch (Exception e) { result.put("payload_hash","0000000000000000"); }
+ return result;
+ }
+
+ static String classify(Map sig) {
+ String f = (String)sig.get("F"), x = (String)sig.get("X");
+ String a = (String)sig.get("A"), y = (String)sig.get("Y");
+ double z = ((Number)sig.getOrDefault("Z",0.0)).doubleValue();
+ if ("Unfulfilled".equals(f) && "OverExplain".equals(x)) return "MODE-DefensiveDefaulter";
+ if ("Fulfilled".equals(f) && "Outsider".equals(a)) return "MODE-ExternalTrustSpender";
+ if ("Unfulfilled".equals(f) && "Indifferent".equals(y)) return "MODE-InternalDestroyer";
+ if (z > 2.0) return "MODE-Fluctuating";
+ return "MODE-StableDisciplined";
+ }
+
+ static List makeLabels(Map sig, String pattern) {
+ List labels = new ArrayList<>();
+ for (String factor : new String[]{"P","F","E","A","X","Y"}) {
+ String val = (String)sig.get(factor);
+ if (val != null && LABEL_MAP.containsKey(factor) && LABEL_MAP.get(factor).containsKey(val))
+ labels.add(LABEL_MAP.get(factor).get(val));
+ }
+ labels.add(pattern);
+ return labels;
+ }
+
+ static String determineColor(String pattern, int repeat) {
+ if ("MODE-InternalDestroyer".equals(pattern)) return "🔴";
+ if ("MODE-Fluctuating".equals(pattern) && repeat > 3) return "🟡";
+ if ("MODE-DefensiveDefaulter".equals(pattern) && repeat > 2) return "🟡";
+ return "🟢";
+ }
+}
diff --git a/adapters/java/src/main/java/cn/uid9622/longhun/DNAGenerator.java b/adapters/java/src/main/java/cn/uid9622/longhun/DNAGenerator.java
new file mode 100644
index 0000000..59f965c
--- /dev/null
+++ b/adapters/java/src/main/java/cn/uid9622/longhun/DNAGenerator.java
@@ -0,0 +1,93 @@
+package cn.uid9622.longhun;
+
+import java.security.MessageDigest;
+import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
+
+public class DNAGenerator {
+ private static final String[] TIAN_GAN = {"Jia","Yi","Bing","Ding","Wu","Ji","Geng","Xin","Ren","Gui"};
+ private static final String[] DI_ZHI = {"Zi","Chou","Yin","Mao","Chen","Si","Wu","Wei","Shen","You","Xu","Hai"};
+ private static final String[] SHI_CHEN = {"ZiShi","ChouShi","YinShi","MaoShi","ChenShi","SiShi","WuShi","WeiShi","ShenShi","YouShi","XuShi","HaiShi"};
+
+ private static final int[] CYCLE_MONTH = {2,4,6,8,10,0,2,4,6,8,10,0};
+ private static final int CYCLE_YEAR = 1984;
+
+ private final String uid, device, locale;
+
+ public DNAGenerator(String uid, String device, String locale) {
+ this.uid = uid != null ? uid : "9622";
+ this.device = device != null ? device : "HM-9622-001";
+ this.locale = locale != null ? locale : "Asia/Shanghai";
+ }
+
+ public String generate(String taskType, String action, String version) {
+ if (taskType == null || taskType.isEmpty()) taskType = "default";
+ if (action == null || action.isEmpty()) action = "WRAP";
+ if (version == null || version.isEmpty()) version = "V1.0";
+
+ ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
+ Map stem = computeStemBranch(now);
+ String[] hex = selectHexagram(taskType);
+ String body = "ADAPTER-" + taskType.toUpperCase() + "-" + action.toUpperCase() + "-" + version;
+
+ String raw = stem.get("year") + stem.get("month") + stem.get("day") + stem.get("shichen")
+ + hex[0] + hex[1] + body + device + now.toString();
+
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ byte[] hash = md.digest(raw.getBytes("UTF-8"));
+ StringBuilder sb = new StringBuilder();
+ for (byte b : hash) sb.append(String.format("%02x", b));
+ String hash8 = sb.toString().substring(0, 8);
+
+ return "#LongHun⚡️" + stem.get("year") + "·" + stem.get("month") + "·" + stem.get("day")
+ + "·" + stem.get("shichen") + "·" + hex[0] + hex[1] + "-" + body + "-" + hash8;
+ } catch (Exception e) { return "#LongHun⚡️ERROR-" + e.getMessage(); }
+ }
+
+ private Map computeStemBranch(ZonedDateTime dt) {
+ int y = dt.getYear(), m = dt.getMonthValue(), doy = dt.getDayOfYear(), h = dt.getHour();
+ int ys = ((y - CYCLE_YEAR) % 10 + 10) % 10;
+ int yb = ((y - CYCLE_YEAR) % 12 + 12) % 12;
+ int mb = CYCLE_MONTH[((y - CYCLE_YEAR) % 10 + 10) % 10];
+ int ms = ((mb + m - 1) % 10 + 10) % 10;
+ int mbr = ((m + 1) % 12 + 12) % 12;
+ int ds = ((y - 1900 + (y - 1900) / 4 + doy) % 10 + 10) % 10;
+ int db = ((y - 1900 + (y - 1900) / 4 + doy) % 12 + 12) % 12;
+ int si = h / 2;
+
+ Map result = new LinkedHashMap<>();
+ result.put("year", TIAN_GAN[ys] + DI_ZHI[yb]);
+ result.put("month", TIAN_GAN[ms] + DI_ZHI[mbr]);
+ result.put("day", TIAN_GAN[ds] + DI_ZHI[db]);
+ result.put("shichen", SHI_CHEN[si]);
+ return result;
+ }
+
+ private String[] selectHexagram(String taskType) {
+ String domain;
+ switch (taskType) {
+ case "code": domain = "engine"; break;
+ case "deploy": domain = "deploy"; break;
+ case "audit": domain = "audit"; break;
+ case "security": domain = "security"; break;
+ case "archive": domain = "archive"; break;
+ case "init": domain = "init"; break;
+ case "learn": domain = "learn"; break;
+ case "legal": domain = "legal"; break;
+ case "privacy": domain = "privacy"; break;
+ case "trust": domain = "trust"; break;
+ case "complete": domain = "complete"; break;
+ case "progress": domain = "progress"; break;
+ default: domain = "governance";
+ }
+ String[][] all = {{"䷀","Qian","governance"},{"䷁","Kun","archive"},{"䷂","Zhun","init"},
+ {"䷃","Meng","learn"},{"䷄","Xu","async"},{"䷅","Song","legal"},
+ {"䷜","Kan","engine"},{"䷝","Li","audit"},{"䷲","Zhen","security"},
+ {"䷳","Gen","privacy"},{"䷸","Xun","deploy"},{"䷹","Dui","trust"},
+ {"䷾","JiJi","complete"},{"䷿","WeiJi","progress"}};
+ for (String[] h : all) if (h[2].equals(domain)) return new String[]{h[0], h[1]};
+ return new String[]{"䷀","Qian"};
+ }
+}
diff --git a/adapters/java/src/main/java/cn/uid9622/longhun/LongHunAdapter.java b/adapters/java/src/main/java/cn/uid9622/longhun/LongHunAdapter.java
new file mode 100644
index 0000000..11e93e8
--- /dev/null
+++ b/adapters/java/src/main/java/cn/uid9622/longhun/LongHunAdapter.java
@@ -0,0 +1,51 @@
+package cn.uid9622.longhun;
+
+import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
+
+public class LongHunAdapter {
+ private final String uid, device, locale;
+ private final DNAGenerator dnaGen;
+ private final AuditWrapper audit;
+ private final Validator validator;
+
+ public LongHunAdapter(String uid, String device, String locale) {
+ this.uid = uid != null ? uid : "9622";
+ this.device = device != null ? device : "HM-9622-001";
+ this.locale = locale != null ? locale : "Asia/Shanghai";
+ this.dnaGen = new DNAGenerator(this.uid, this.device, this.locale);
+ this.audit = new AuditWrapper(this.uid);
+ this.validator = new Validator();
+ }
+
+ public Map wrap(Object data, String taskType, String persona, String action, String version) {
+ if (taskType == null || taskType.isEmpty()) taskType = "default";
+ if (persona == null || persona.isEmpty()) persona = "P04";
+ if (action == null || action.isEmpty()) action = "WRAP";
+ Map result = new LinkedHashMap<>();
+ result.put("dna", dnaGen.generate(taskType, action, version));
+ result.put("audit", audit.wrap(data, taskType, persona));
+ result.put("payload", data);
+ Map meta = new LinkedHashMap<>();
+ meta.put("adapter_version","1.0.0");
+ meta.put("uid",uid);
+ meta.put("device",device);
+ meta.put("task_type",taskType);
+ meta.put("persona",persona);
+ meta.put("generated_at", ZonedDateTime.now(ZoneOffset.UTC).toString());
+ meta.put("format","longhun-v∞");
+ result.put("meta", meta);
+ return result;
+ }
+
+ public ValidationResult validate(Map wrapped) { return validator.validate(wrapped); }
+
+ public Map getSchemas() {
+ Map schemas = new LinkedHashMap<>();
+ schemas.put("dnaSchema", Map.of("type","string","description","v∞ DNA traceability code"));
+ schemas.put("auditSchema", Map.of("type","object","required",
+ List.of("audit_version","uid","behavior_signature","behavior_pattern","behavior_labels","color")));
+ return schemas;
+ }
+}
diff --git a/adapters/java/src/main/java/cn/uid9622/longhun/ValidationResult.java b/adapters/java/src/main/java/cn/uid9622/longhun/ValidationResult.java
new file mode 100644
index 0000000..27bcf6b
--- /dev/null
+++ b/adapters/java/src/main/java/cn/uid9622/longhun/ValidationResult.java
@@ -0,0 +1,17 @@
+package cn.uid9622.longhun;
+
+import java.util.List;
+
+public class ValidationResult {
+ private final boolean valid;
+ private final List errors, warnings;
+ private final String summary;
+
+ public ValidationResult(boolean valid, List errors, List warnings, String summary) {
+ this.valid = valid; this.errors = errors; this.warnings = warnings; this.summary = summary;
+ }
+ public boolean isValid() { return valid; }
+ public List getErrors() { return errors; }
+ public List getWarnings() { return warnings; }
+ public String getSummary() { return summary; }
+}
diff --git a/adapters/java/src/main/java/cn/uid9622/longhun/Validator.java b/adapters/java/src/main/java/cn/uid9622/longhun/Validator.java
new file mode 100644
index 0000000..6a721a1
--- /dev/null
+++ b/adapters/java/src/main/java/cn/uid9622/longhun/Validator.java
@@ -0,0 +1,65 @@
+package cn.uid9622.longhun;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+public class Validator {
+ private static final Pattern DNA_REGEX = Pattern.compile(
+ "^#LongHun⚡️([A-Z][a-zA-Z]+)·([A-Z][a-zA-Z]+)·([A-Z][a-zA-Z]+)·([A-Z][a-zA-Z]+)·([\\u4DC0-\\u4DFF][A-Za-z]+)-(.+)-([a-f0-9]{8})$");
+ private static final Set REQUIRED_TOP = Set.of("dna","audit","payload","meta");
+ private static final Set REQUIRED_AUDIT = Set.of("audit_version","uid","behavior_signature","behavior_pattern","behavior_labels","color");
+ private static final Set REQUIRED_SIG = Set.of("P","F","T","E","C","R","A","X","Y","Z");
+
+ private List errors = new ArrayList<>();
+ private List warnings = new ArrayList<>();
+
+ public ValidationResult validate(Map wrapped) {
+ errors.clear(); warnings.clear();
+ if (wrapped == null || wrapped.isEmpty()) { errors.add("Input null/empty"); return result(); }
+
+ for (String k : REQUIRED_TOP) if (!wrapped.containsKey(k)) errors.add("Missing top key: "+k);
+
+ Object dnaObj = wrapped.get("dna");
+ if (dnaObj == null || "".equals(dnaObj)) errors.add("DNA empty");
+ else if (!DNA_REGEX.matcher((String)dnaObj).matches())
+ errors.add("DNA regex fail: "+((String)dnaObj).substring(0, Math.min(60, ((String)dnaObj).length())));
+
+ Object auditObj = wrapped.get("audit");
+ if (!(auditObj instanceof Map)) errors.add("Audit not object");
+ else validateAudit((Map)auditObj);
+
+ return result();
+ }
+
+ private void validateAudit(Map audit) {
+ for (String k : REQUIRED_AUDIT) if (!audit.containsKey(k)) errors.add("Missing audit key: "+k);
+ Object sigObj = audit.get("behavior_signature");
+ if (!(sigObj instanceof Map)) errors.add("sig not object");
+ else {
+ Map sig = (Map)sigObj;
+ for (String k : REQUIRED_SIG) if (!sig.containsKey(k)) errors.add("Missing sig key: "+k);
+ validateSigValues(sig);
+ }
+ }
+
+ private void validateSigValues(Map sig) {
+ Set vp = Set.of("HasPromise","NoPromise");
+ Set vf = Set.of("Fulfilled","Unfulfilled","Partial");
+ Set ve = Set.of("Willing","Perfunctory","Resentful","Numb");
+ Set va = Set.of("Self","Partner","Family","Outsider","Public");
+ Set vx = Set.of("OverExplain","Silent","Genuine","Indifferent");
+ Set vy = Set.of("Changed","Resisted","Indifferent","NoResponse");
+
+ if (!vp.contains(sig.get("P"))) warnings.add("Invalid P: "+sig.get("P"));
+ if (!vf.contains(sig.get("F"))) warnings.add("Invalid F: "+sig.get("F"));
+ if (!ve.contains(sig.get("E"))) warnings.add("Invalid E: "+sig.get("E"));
+ if (!va.contains(sig.get("A"))) warnings.add("Invalid A: "+sig.get("A"));
+ if (!vx.contains(sig.get("X"))) warnings.add("Invalid X: "+sig.get("X"));
+ if (!vy.contains(sig.get("Y"))) warnings.add("Invalid Y: "+sig.get("Y"));
+ }
+
+ private ValidationResult result() {
+ boolean valid = errors.isEmpty();
+ return new ValidationResult(valid, errors, warnings, valid ? "✅ VALID" : "❌ INVALID");
+ }
+}