Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions adapters/typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```bash
# Install dependencies
cd adapters/typescript
npm install

# Build
npm run build

# Run tests
npm test
```
43 changes: 43 additions & 0 deletions adapters/typescript/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@uid9622/lh-standard-adapter",
"version": "1.0.0",
"description": "LongHun (龍魂) v∞ DNA Traceability Standard — TypeScript Adapter",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
}
},
"files": [
"dist",
"LICENSE",
"README.md"
],
"scripts": {
"build": "tsc",
"test": "vitest run",
"test:watch": "vitest",
"prepublishOnly": "npm run build"
},
"keywords": [
"longhun",
"dna-traceability",
"audit",
"龍魂"
],
"license": "Apache-2.0",
"devDependencies": {
"typescript": "^5.4.0",
"vitest": "^1.6.0",
"@types/node": "^20.0.0"
}
}
160 changes: 160 additions & 0 deletions adapters/typescript/src/AuditWrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* Audit Wrapper — seven-factor behavioral audit metadata generation.
*
* DNA: #LongHun⚡️BingWu·GuiWei·JiaZi·ZiShi·䷝Li-AUDIT-WRAPPER-v1.0.0
*/

import { createHash } from 'node:crypto';
import type {
AuditWrapperResult,
BehaviorPattern,
BehaviorSignature,
} from './types.js';

// ── Seven-Factor Value Sets ──────────────────────────────────────────────────

const P_VALUES = ['HasPromise', 'NoPromise'] as const;
const F_VALUES = ['Fulfilled', 'Unfulfilled', 'Partial'] as const;
const E_VALUES = ['Willing', 'Perfunctory', 'Resentful', 'Numb'] as const;
const A_VALUES = ['Self', 'Partner', 'Family', 'Outsider', 'Public'] as const;
const X_VALUES = ['OverExplain', 'Silent', 'Genuine', 'Indifferent'] as const;
const Y_VALUES = ['Changed', 'Resisted', 'Indifferent', 'NoResponse'] as const;

// ── Behavior Pattern Classification ──────────────────────────────────────────

const PATTERNS: Record<BehaviorPattern, string> = {
'MODE-DefensiveDefaulter': 'Promises fail + over-explains to deflect',
'MODE-ExternalTrustSpender': 'Keeps promises to outsiders at inner-circle expense',
'MODE-InternalDestroyer': 'Breaks promises with indifference, no correction',
'MODE-Fluctuating': 'High volatility in commitment-to-fulfillment ratio',
'MODE-StableDisciplined': 'Consistent, reliable execution',
};

// ── Factor → Label Mapping ───────────────────────────────────────────────────

const LABEL_MAP: Record<string, Record<string, string>> = {
P: { HasPromise: '7F-P-有承诺', NoPromise: '7F-P-无承诺' },
F: { Fulfilled: '7F-F-已兑现', Unfulfilled: '7F-F-未兑现', Partial: '7F-F-部分兑现' },
E: { Willing: '7F-E-心甘情愿', Perfunctory: '7F-E-敷衍', Resentful: '7F-E-怨恨', Numb: '7F-E-麻木' },
A: { Self: '7F-A-自己', Partner: '7F-A-伴侣', Family: '7F-A-家庭', Outsider: '7F-A-外人', Public: '7F-A-公众' },
X: { OverExplain: '7F-X-过度解释', Silent: '7F-X-沉默', Genuine: '7F-X-真诚', Indifferent: '7F-X-冷漠' },
Y: { Changed: '7F-Y-改正', Resisted: '7F-Y-抗拒', Indifferent: '7F-Y-无视', NoResponse: '7F-Y-无响应' },
};

// ── Wrapper ──────────────────────────────────────────────────────────────────

export class AuditWrapper {
private readonly uid: string;

constructor(uid = '9622') {
this.uid = uid;
}

/**
* Generate audit wrapper with seven-factor signature.
*
* @param payload - Raw data to wrap
* @param taskType - Task category
* @param persona - Persona identifier
* @returns Audit metadata
*/
wrap(payload: unknown, taskType = 'default', persona = 'P04'): AuditWrapperResult {
const now = new Date();

// Default signature (StableDisciplined baseline)
const signature: BehaviorSignature = {
P: 'HasPromise',
F: 'Fulfilled',
T: 0.0,
E: 'Willing',
C: 0,
R: 0,
A: 'Self',
X: 'Genuine',
Y: 'NoResponse',
Z: 1.0,
};

const pattern = this.classify(signature);
const labels = this.makeLabels(signature, pattern);
const color = this.determineColor(pattern, signature.R);

// Payload hash (not for crypto, for integrity check)
const payloadJson = JSON.stringify(payload, Object.keys(payload as object).sort());
const payloadHash = createHash('sha256').update(payloadJson, 'utf-8').digest('hex').slice(0, 16);

return {
audit_version: 'v1.0',
uid: `UID${this.uid}`,
persona,
task_type: taskType,
behavior_signature: signature,
behavior_pattern: pattern,
behavior_labels: labels,
color,
timestamp: now.toISOString(),
payload_hash: payloadHash,
};
}

/**
* Classify seven-factor signature into behavior pattern.
*/
private classify(sig: BehaviorSignature): BehaviorPattern {
const fVal = sig.F;
const xVal = sig.X;
const aVal = sig.A;
const yVal = sig.Y;
const zVal = sig.Z;

if (fVal === 'Unfulfilled' && xVal === 'OverExplain') {
return 'MODE-DefensiveDefaulter';
}
if (fVal === 'Fulfilled' && aVal === 'Outsider') {
return 'MODE-ExternalTrustSpender';
}
if (fVal === 'Unfulfilled' && yVal === 'Indifferent') {
return 'MODE-InternalDestroyer';
}
if (zVal > 2.0) {
return 'MODE-Fluctuating';
}
return 'MODE-StableDisciplined';
}

/**
* Generate bilingual behavior labels from signature.
*/
private makeLabels(sig: BehaviorSignature, pattern: BehaviorPattern): string[] {
const labels: string[] = [];
for (const factor of ['P', 'F', 'E', 'A', 'X', 'Y'] as const) {
const val = sig[factor] as string;
if (LABEL_MAP[factor]?.[val]) {
labels.push(LABEL_MAP[factor][val]);
}
}
labels.push(pattern);
return labels;
}

/**
* Determine three-color audit tag.
*/
private determineColor(pattern: BehaviorPattern, repeat: number): '🟢' | '🟡' | '🔴' {
if (pattern === 'MODE-InternalDestroyer') return '🔴';
if (pattern === 'MODE-Fluctuating' && repeat > 3) return '🟡';
if (pattern === 'MODE-DefensiveDefaulter' && repeat > 2) return '🟡';
return '🟢';
}
}

// ── Convenience singleton ────────────────────────────────────────────────────

const defaultWrapper = new AuditWrapper();

/**
* Quick one-shot audit wrapper.
*/
export function auditWrap(payload: unknown, taskType = 'default', persona = 'P04'): AuditWrapperResult {
return defaultWrapper.wrap(payload, taskType, persona);
}
174 changes: 174 additions & 0 deletions adapters/typescript/src/DNAGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* DNA Generator — v∞ format traceability code generation.
*
* DNA: #LongHun⚡️BingWu·GuiWei·JiaZi·ZiShi·䷾JiJi-DNA-GENERATOR-v1.0.0
*/

import { createHash } from 'node:crypto';
import type { Hexagram, StemBranch } from './types.js';

// ── Heavenly Stems and Earthly Branches ──────────────────────────────────────

const TIAN_GAN = ['Jia', 'Yi', 'Bing', 'Ding', 'Wu', 'Ji', 'Geng', 'Xin', 'Ren', 'Gui'];
const DI_ZHI = ['Zi', 'Chou', 'Yin', 'Mao', 'Chen', 'Si', 'Wu', 'Wei', 'Shen', 'You', 'Xu', 'Hai'];
const SHI_CHEN = ['ZiShi', 'ChouShi', 'YinShi', 'MaoShi', 'ChenShi', 'SiShi', 'WuShi', 'WeiShi', 'ShenShi', 'YouShi', 'XuShi', 'HaiShi'];

// ── I Ching Hexagrams ────────────────────────────────────────────────────────

const HEXAGRAMS: Hexagram[] = [
{ symbol: '䷀', enName: 'Qian', cnName: '乾', domain: 'governance' },
{ symbol: '䷁', enName: 'Kun', cnName: '坤', domain: 'archive' },
{ symbol: '䷂', enName: 'Zhun', cnName: '屯', domain: 'init' },
{ symbol: '䷃', enName: 'Meng', cnName: '蒙', domain: 'learn' },
{ symbol: '䷄', enName: 'Xu', cnName: '需', domain: 'async' },
{ symbol: '䷅', enName: 'Song', cnName: '讼', domain: 'legal' },
{ symbol: '䷜', enName: 'Kan', cnName: '坎', domain: 'engine' },
{ symbol: '䷝', enName: 'Li', cnName: '离', domain: 'audit' },
{ symbol: '䷲', enName: 'Zhen', cnName: '震', domain: 'security' },
{ symbol: '䷳', enName: 'Gen', cnName: '艮', domain: 'privacy' },
{ symbol: '䷸', enName: 'Xun', cnName: '巽', domain: 'deploy' },
{ symbol: '䷹', enName: 'Dui', cnName: '兑', domain: 'trust' },
{ symbol: '䷾', enName: 'JiJi', cnName: '既济', domain: 'complete' },
{ symbol: '䷿', enName: 'WeiJi', cnName: '未济', domain: 'progress' },
];

// ── Task-to-hexagram domain mapping ──────────────────────────────────────────

const TASK_HEXAGRAM_MAP: Record<string, string> = {
default: 'governance',
code: 'engine',
deploy: 'deploy',
audit: 'audit',
security: 'security',
archive: 'archive',
init: 'init',
learn: 'learn',
legal: 'legal',
privacy: 'privacy',
trust: 'trust',
complete: 'complete',
progress: 'progress',
};

// ── Month stem offsets ───────────────────────────────────────────────────────

const CYCLE_YEAR = 1984; // JiaZi year reference
const CYCLE_MONTH = [2, 4, 6, 8, 10, 0, 2, 4, 6, 8, 10, 0];

// ── Generator ────────────────────────────────────────────────────────────────

export class DNAGenerator {
private readonly uid: string;
private readonly device: string;

constructor(uid = '9622', device = 'HM-9622-001') {
this.uid = uid;
this.device = device;
}

/**
* Generate a full DNA traceability string.
*
* Format: #LongHun⚡️{StemBranch}·{Hexagram}-{ModulePath}-{Hash8}
*
* @param taskType - Task category (default, code, audit, etc.)
* @param action - Action type (WRAP, VALIDATE, etc.)
* @param version - Optional version string (default: V1.0)
* @returns DNA traceability code string
*/
generate(taskType = 'default', action = 'WRAP', version?: string): string {
const now = new Date();
const stem = this.computeStemBranch(now);
const hexagram = this.selectHexagram(taskType);
const ver = version ?? 'V1.0';
const body = `ADAPTER-${taskType.toUpperCase()}-${action.toUpperCase()}-${ver}`;

const raw = `${stem.year}${stem.month}${stem.day}${stem.shichen}` +
`${hexagram.symbol}${hexagram.enName}${body}${this.device}${now.toISOString()}`;

const hash8 = createHash('sha256').update(raw, 'utf-8').digest('hex').slice(0, 8);

return `#LongHun⚡️${stem.year}·${stem.month}·${stem.day}·${stem.shichen}` +
`·${hexagram.symbol}${hexagram.enName}-${body}-${hash8}`;
}

/**
* Compute Heavenly Stem + Earthly Branch for a given datetime.
*/
private computeStemBranch(dt: Date): StemBranch {
const year = dt.getFullYear();
const month = dt.getMonth() + 1; // 1-indexed
const day = dt.getDate();
const hour = dt.getHours();

// Year pillar
const yearStemIdx = (year - CYCLE_YEAR) % 10;
const yearBranchIdx = (year - CYCLE_YEAR) % 12;

// Month pillar
const cycleIdx = (year - CYCLE_YEAR) % 10;
const monthStemBase = CYCLE_MONTH[cycleIdx];
const monthStemIdx = (monthStemBase + (month - 1)) % 10;
const monthBranchIdx = (month + 1) % 12;

// Day pillar (approximate — use a proper astronomical library for precision)
const dayOff = this.dayOffset(year, month, day);
const dayStemIdx = dayOff % 10;
const dayBranchIdx = dayOff % 12;

// Shichen (2-hour period)
const shichenIdx = Math.floor(hour / 2);

return {
year: TIAN_GAN[this.posMod(yearStemIdx, 10)] + DI_ZHI[this.posMod(yearBranchIdx, 12)],
month: TIAN_GAN[this.posMod(monthStemIdx, 10)] + DI_ZHI[this.posMod(monthBranchIdx, 12)],
day: TIAN_GAN[this.posMod(dayStemIdx, 10)] + DI_ZHI[this.posMod(dayBranchIdx, 12)],
shichen: SHI_CHEN[shichenIdx],
};
}

/**
* Approximate day offset from a reference date for stem-branch calculation.
*/
private dayOffset(year: number, month: number, day: number): number {
// Reference: 1900-01-01 is JiaZi day (day 0)
let total = 0;
for (let y = 1900; y < year; y++) {
total += this.isLeapYear(y) ? 366 : 365;
}
const daysInMonth = [31, this.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
for (let m = 0; m < month - 1; m++) {
total += daysInMonth[m];
}
total += day - 1;
return total;
}

private isLeapYear(y: number): boolean {
return (y % 4 === 0 && y % 100 !== 0) || (y % 400 === 0);
}

private posMod(n: number, m: number): number {
return ((n % m) + m) % m;
}

/**
* Select I Ching hexagram based on task type.
*/
private selectHexagram(taskType: string): Hexagram {
const domain = TASK_HEXAGRAM_MAP[taskType] ?? 'governance';
const candidates = HEXAGRAMS.filter(h => h.domain === domain);
return candidates.length > 0 ? candidates[0] : HEXAGRAMS[0]; // Default: Qian
}
}

// ── Convenience singleton ────────────────────────────────────────────────────

const defaultGenerator = new DNAGenerator();

/**
* Quick one-shot DNA generation.
*/
export function generateDNA(taskType = 'default', action = 'WRAP', version?: string): string {
return defaultGenerator.generate(taskType, action, version);
}
Loading