@n2world/orchestrator 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/dist/agent-os-rd.d.ts +100 -0
  2. package/dist/agent-os-rd.js +258 -0
  3. package/dist/audit-store.d.ts +14 -0
  4. package/dist/audit-store.js +107 -0
  5. package/dist/beta-runner.d.ts +95 -0
  6. package/dist/beta-runner.js +251 -0
  7. package/dist/beta.d.ts +102 -0
  8. package/dist/beta.js +180 -0
  9. package/dist/browser-agent.d.ts +90 -0
  10. package/dist/browser-agent.js +223 -0
  11. package/dist/channel-gateway.d.ts +74 -0
  12. package/dist/channel-gateway.js +270 -0
  13. package/dist/channels.d.ts +120 -0
  14. package/dist/channels.js +432 -0
  15. package/dist/chat-store.d.ts +29 -0
  16. package/dist/chat-store.js +120 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +607 -0
  19. package/dist/command-screen.d.ts +12 -0
  20. package/dist/command-screen.js +44 -0
  21. package/dist/commit-gate.d.ts +98 -0
  22. package/dist/commit-gate.js +258 -0
  23. package/dist/companion-api.d.ts +37 -0
  24. package/dist/companion-api.js +101 -0
  25. package/dist/conversation-graph.d.ts +39 -0
  26. package/dist/conversation-graph.js +92 -0
  27. package/dist/cost-estimator.d.ts +27 -0
  28. package/dist/cost-estimator.js +42 -0
  29. package/dist/cron-runner.d.ts +31 -0
  30. package/dist/cron-runner.js +46 -0
  31. package/dist/dashboard/chat.html +326 -0
  32. package/dist/dashboard/dental.html +58 -0
  33. package/dist/dashboard/freebie.png +0 -0
  34. package/dist/dashboard/icon-192.png +0 -0
  35. package/dist/dashboard/index.html +892 -0
  36. package/dist/dashboard/manifest.json +15 -0
  37. package/dist/dashboard/service-worker.js +28 -0
  38. package/dist/dashboard-server.d.ts +37 -0
  39. package/dist/dashboard-server.js +457 -0
  40. package/dist/dental-intake-service.d.ts +37 -0
  41. package/dist/dental-intake-service.js +61 -0
  42. package/dist/dental-metrics.d.ts +25 -0
  43. package/dist/dental-metrics.js +37 -0
  44. package/dist/docking.d.ts +36 -0
  45. package/dist/docking.js +73 -0
  46. package/dist/finance-mcts-candidate.d.ts +37 -0
  47. package/dist/finance-mcts-candidate.js +106 -0
  48. package/dist/finance-regulation-kr.d.ts +33 -0
  49. package/dist/finance-regulation-kr.js +104 -0
  50. package/dist/finance-workflow.d.ts +135 -0
  51. package/dist/finance-workflow.js +242 -0
  52. package/dist/gateway.d.ts +18 -0
  53. package/dist/gateway.js +123 -0
  54. package/dist/governance.d.ts +39 -0
  55. package/dist/governance.js +48 -0
  56. package/dist/governed-executor.d.ts +31 -0
  57. package/dist/governed-executor.js +63 -0
  58. package/dist/governed-llm.d.ts +41 -0
  59. package/dist/governed-llm.js +83 -0
  60. package/dist/gpu-bridge.d.ts +16 -0
  61. package/dist/gpu-bridge.js +53 -0
  62. package/dist/health.d.ts +47 -0
  63. package/dist/health.js +66 -0
  64. package/dist/identity-link.d.ts +32 -0
  65. package/dist/identity-link.js +98 -0
  66. package/dist/index.d.ts +184 -0
  67. package/dist/index.js +417 -0
  68. package/dist/integrations/emr-adapter.d.ts +41 -0
  69. package/dist/integrations/emr-adapter.js +63 -0
  70. package/dist/kakao-oauth.d.ts +16 -0
  71. package/dist/kakao-oauth.js +87 -0
  72. package/dist/knowledge-graph.d.ts +53 -0
  73. package/dist/knowledge-graph.js +156 -0
  74. package/dist/llm.d.ts +65 -0
  75. package/dist/llm.js +357 -0
  76. package/dist/mcp-client-guard.d.ts +32 -0
  77. package/dist/mcp-client-guard.js +179 -0
  78. package/dist/mcp-macaroon.d.ts +75 -0
  79. package/dist/mcp-macaroon.js +161 -0
  80. package/dist/mcts-kernel-bridge.d.ts +36 -0
  81. package/dist/mcts-kernel-bridge.js +99 -0
  82. package/dist/mcts-prior.d.ts +79 -0
  83. package/dist/mcts-prior.js +170 -0
  84. package/dist/model-router.d.ts +51 -0
  85. package/dist/model-router.js +75 -0
  86. package/dist/multi-axis-lift.d.ts +43 -0
  87. package/dist/multi-axis-lift.js +141 -0
  88. package/dist/net-guard.d.ts +39 -0
  89. package/dist/net-guard.js +141 -0
  90. package/dist/onboarding.d.ts +38 -0
  91. package/dist/onboarding.js +94 -0
  92. package/dist/oracle-anchored-search.d.ts +25 -0
  93. package/dist/oracle-anchored-search.js +50 -0
  94. package/dist/oracle.d.ts +22 -0
  95. package/dist/oracle.js +116 -0
  96. package/dist/p6-governance.d.ts +150 -0
  97. package/dist/p6-governance.js +252 -0
  98. package/dist/pairing.d.ts +22 -0
  99. package/dist/pairing.js +81 -0
  100. package/dist/personalization.d.ts +35 -0
  101. package/dist/personalization.js +73 -0
  102. package/dist/pglite-hnsw-bridge.d.ts +118 -0
  103. package/dist/pglite-hnsw-bridge.js +311 -0
  104. package/dist/pglite-store.d.ts +59 -0
  105. package/dist/pglite-store.js +180 -0
  106. package/dist/playbook.d.ts +79 -0
  107. package/dist/playbook.js +83 -0
  108. package/dist/playbooks/dental-intake.d.ts +20 -0
  109. package/dist/playbooks/dental-intake.js +112 -0
  110. package/dist/predictive-agent.d.ts +157 -0
  111. package/dist/predictive-agent.js +535 -0
  112. package/dist/prompt-optimizer.d.ts +18 -0
  113. package/dist/prompt-optimizer.js +104 -0
  114. package/dist/rate-limiter.d.ts +25 -0
  115. package/dist/rate-limiter.js +75 -0
  116. package/dist/safety-anneal.d.ts +83 -0
  117. package/dist/safety-anneal.js +153 -0
  118. package/dist/sandbox-controller.d.ts +12 -0
  119. package/dist/sandbox-controller.js +95 -0
  120. package/dist/satisfaction-metrics.d.ts +26 -0
  121. package/dist/satisfaction-metrics.js +61 -0
  122. package/dist/sensor-bridge.d.ts +53 -0
  123. package/dist/sensor-bridge.js +133 -0
  124. package/dist/session-repair.d.ts +27 -0
  125. package/dist/session-repair.js +66 -0
  126. package/dist/slack-finance-intake.d.ts +42 -0
  127. package/dist/slack-finance-intake.js +122 -0
  128. package/dist/symbolic-dynamics.d.ts +113 -0
  129. package/dist/symbolic-dynamics.js +420 -0
  130. package/dist/telemetry.d.ts +19 -0
  131. package/dist/telemetry.js +68 -0
  132. package/dist/text-embedding.d.ts +6 -0
  133. package/dist/text-embedding.js +42 -0
  134. package/dist/tier-classifier.d.ts +20 -0
  135. package/dist/tier-classifier.js +58 -0
  136. package/dist/tier-guard.d.ts +36 -0
  137. package/dist/tier-guard.js +56 -0
  138. package/dist/tui.d.ts +9 -0
  139. package/dist/tui.js +214 -0
  140. package/dist/update-security.d.ts +31 -0
  141. package/dist/update-security.js +112 -0
  142. package/dist/v-calibration.d.ts +16 -0
  143. package/dist/v-calibration.js +42 -0
  144. package/dist/value-calibration.d.ts +41 -0
  145. package/dist/value-calibration.js +133 -0
  146. package/dist/value-head.d.ts +20 -0
  147. package/dist/value-head.js +91 -0
  148. package/dist/wal-buffer.d.ts +23 -0
  149. package/dist/wal-buffer.js +144 -0
  150. package/dist/wiki-synthesizer.d.ts +80 -0
  151. package/dist/wiki-synthesizer.js +0 -0
  152. package/dist/worker-agent.d.ts +10 -0
  153. package/dist/worker-agent.js +19 -0
  154. package/package.json +65 -0
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // v2.5.2 Phase 5 — 센서 브리지 거버넌스 (Tier-0 강제·동의·보존·삭제·소멸감사)
4
+ // ----------------------------------------------------------------------------
5
+ // 계획서 v2.5.2 §3.2/§5/§C: 물리 센서(위치·카메라)·음성 원본은 *민감(Tier-0)* 이다.
6
+ // - 동의 없이는 수집 불가(상황별 재동의)
7
+ // - 전부 Tier-0 → 외부 송신 금지(로컬 전용)
8
+ // - 보존기간 상한 + 삭제(잊혀질 권리) + 소멸 감사(시각/해시)
9
+ //
10
+ // 정직 고지(제1계명): 본 모듈은 *데이터 거버넌스* 계층이며 테스트로 검증된다. 실제
11
+ // 카메라/GPS/마이크 캡처는 네이티브(미검증) — 캡처된 샘플이 이 게이트를 통과해야만
12
+ // 적재되고, 외부로는 결코 나가지 않는다. "소멸"은 감사 로그로 증명한다(연기 금지).
13
+ // ============================================================================
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.SensorBridge = void 0;
49
+ const crypto = __importStar(require("crypto"));
50
+ const tier_classifier_1 = require("./tier-classifier");
51
+ /**
52
+ * 센서 샘플의 적재·보존·삭제를 통제한다. 모든 센서 데이터는 Tier-0(로컬 전용).
53
+ */
54
+ class SensorBridge {
55
+ samples = [];
56
+ consent = new Set(); // `${sessionId}:${kind}`
57
+ audit = [];
58
+ retentionMs;
59
+ constructor(opts = {}) {
60
+ this.retentionMs = opts.retentionMs ?? 10 * 60 * 1000;
61
+ }
62
+ ck(sessionId, kind) { return `${sessionId}:${kind}`; }
63
+ hash(s) { return crypto.createHash('sha256').update(s).digest('hex').slice(0, 16); }
64
+ /** 상황별 동의 부여(센서 종류·세션별). 동의 없이는 적재 거부. */
65
+ grantConsent(sessionId, kind) {
66
+ this.consent.add(this.ck(sessionId, kind));
67
+ this.audit.push({ t: Date.now(), type: 'consent', kind, sessionId });
68
+ }
69
+ revokeConsent(sessionId, kind) {
70
+ this.consent.delete(this.ck(sessionId, kind));
71
+ }
72
+ hasConsent(sessionId, kind) {
73
+ return this.consent.has(this.ck(sessionId, kind));
74
+ }
75
+ /**
76
+ * 센서 샘플 적재 — 동의가 있어야만 통과. 모든 센서 데이터는 Tier-0 로 분류·확인된다.
77
+ * 반환: 적재 성공 여부.
78
+ */
79
+ ingest(sample) {
80
+ if (!this.hasConsent(sample.sessionId, sample.kind)) {
81
+ this.audit.push({ t: Date.now(), type: 'ingest-denied', kind: sample.kind, sessionId: sample.sessionId, detail: '동의 없음' });
82
+ return { ok: false, reason: '동의 없음 — 적재 거부' };
83
+ }
84
+ // 불변식 확인: 센서 데이터는 반드시 Tier-0(외부 금지).
85
+ const tier = (0, tier_classifier_1.classifyTier)({ text: sample.data, kind: sample.kind === 'voice' ? 'voice' : 'sensor' }).tier;
86
+ if (tier !== 0) {
87
+ // 방어적: 센서가 Tier-0 이 아니면 코드 결함 → 적재 거부(외부 유출 위험 차단).
88
+ this.audit.push({ t: Date.now(), type: 'ingest-denied', kind: sample.kind, sessionId: sample.sessionId, detail: `비-Tier0(${tier}) 거부` });
89
+ return { ok: false, reason: '센서는 Tier-0 이어야 함' };
90
+ }
91
+ this.samples.push(sample);
92
+ this.audit.push({ t: Date.now(), type: 'ingest', kind: sample.kind, sessionId: sample.sessionId, hash: this.hash(sample.data) });
93
+ return { ok: true, reason: 'ok' };
94
+ }
95
+ /** 외부 송신 가능 여부 — 센서 데이터는 *항상* 불가. 시도는 감사된다. */
96
+ assertNoEgress(sessionId, kind) {
97
+ this.audit.push({ t: Date.now(), type: 'egress-blocked', kind, sessionId, detail: 'Tier-0 센서 외부 송신 차단' });
98
+ return false; // 절대 외부 송신 불가
99
+ }
100
+ /** 보존기간 초과 샘플 소멸(감사 기록 — 소멸 증명). */
101
+ expire(now = Date.now()) {
102
+ const before = this.samples.length;
103
+ const kept = [];
104
+ for (const s of this.samples) {
105
+ if (now - s.ts > this.retentionMs) {
106
+ this.audit.push({ t: now, type: 'expire', kind: s.kind, sessionId: s.sessionId, hash: this.hash(s.data) });
107
+ }
108
+ else
109
+ kept.push(s);
110
+ }
111
+ this.samples = kept;
112
+ return before - kept.length;
113
+ }
114
+ /** 잊혀질 권리 — 세션(또는 종류)별 즉시 삭제 + 소멸 감사. */
115
+ deleteFor(sessionId, kind) {
116
+ const before = this.samples.length;
117
+ const kept = [];
118
+ for (const s of this.samples) {
119
+ const match = s.sessionId === sessionId && (!kind || s.kind === kind);
120
+ if (match)
121
+ this.audit.push({ t: Date.now(), type: 'delete', kind: s.kind, sessionId, hash: this.hash(s.data) });
122
+ else
123
+ kept.push(s);
124
+ }
125
+ this.samples = kept;
126
+ this.consent.forEach((c) => { if (c.startsWith(`${sessionId}:`) && (!kind || c.endsWith(`:${kind}`)))
127
+ this.consent.delete(c); });
128
+ return before - kept.length;
129
+ }
130
+ count() { return this.samples.length; }
131
+ auditLog() { return [...this.audit]; }
132
+ }
133
+ exports.SensorBridge = SensorBridge;
@@ -0,0 +1,27 @@
1
+ export declare class FencingLock {
2
+ private token;
3
+ private holder;
4
+ /** 락 획득 → 새 펜싱 토큰 발급(이전 보유자는 stale 처리됨). */
5
+ acquire(): number;
6
+ /** 워치독 강제 해제 — 다음 acquire가 더 큰 토큰을 받게 한다. */
7
+ forceRelease(): void;
8
+ /** 쓰기 시도 검증: 보유 토큰이 현재 최신이 아니면 거부(stale writer 차단). */
9
+ validateWrite(myToken: number): {
10
+ ok: boolean;
11
+ reason: string;
12
+ };
13
+ }
14
+ export interface RepairResult<T = any> {
15
+ recovered: T[];
16
+ /** 복원 불가로 *폐기*한 라인 수(날조하지 않음). */
17
+ droppedLines: number;
18
+ /** 폐기 라인 번호(감사용). */
19
+ droppedAt: number[];
20
+ total: number;
21
+ }
22
+ /**
23
+ * 손상 JSONL 텍스트를 정직 복구한다. 파싱 가능한 유효 라인만 복구하고,
24
+ * 파싱 불가/스키마 불일치 라인은 **버리고 카운트**한다(추정 복원 금지).
25
+ * @param isValid 복구 라인의 스키마 검증(선택). 통과 못하면 폐기.
26
+ */
27
+ export declare function repairJsonl<T = any>(raw: string, isValid?: (o: any) => boolean): RepairResult<T>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // v2.5.2 Phase 3 — ResilientSessionRepair (펜싱 토큰 + 정직 JSONL 복구)
4
+ // ----------------------------------------------------------------------------
5
+ // 계획서 v2.5.2 §3.5:
6
+ // (a) Stuck 워치독 강제 락 해제 시 *단조 증가 펜싱 토큰*으로 stale writer 차단
7
+ // → 락 해제가 데이터 손상으로 이어지지 않게 한다.
8
+ // (b) 손상 JSONL은 *복원 가능 라인만* 복구하고, 복원 불가 라인은 **날조 없이 폐기·표기**.
9
+ // "추정 복원" 절대 금지(제1계명).
10
+ // ============================================================================
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FencingLock = void 0;
13
+ exports.repairJsonl = repairJsonl;
14
+ // ── (a) 펜싱 토큰 락 ───────────────────────────────────────────────────────
15
+ class FencingLock {
16
+ token = 0; // 단조 증가 펜싱 토큰
17
+ holder = null;
18
+ /** 락 획득 → 새 펜싱 토큰 발급(이전 보유자는 stale 처리됨). */
19
+ acquire() {
20
+ this.token += 1;
21
+ this.holder = this.token;
22
+ return this.token;
23
+ }
24
+ /** 워치독 강제 해제 — 다음 acquire가 더 큰 토큰을 받게 한다. */
25
+ forceRelease() { this.holder = null; }
26
+ /** 쓰기 시도 검증: 보유 토큰이 현재 최신이 아니면 거부(stale writer 차단). */
27
+ validateWrite(myToken) {
28
+ if (myToken !== this.token) {
29
+ return { ok: false, reason: `stale writer 거부(my=${myToken}, current=${this.token})` };
30
+ }
31
+ if (this.holder !== myToken) {
32
+ return { ok: false, reason: '락 미보유' };
33
+ }
34
+ return { ok: true, reason: 'ok' };
35
+ }
36
+ }
37
+ exports.FencingLock = FencingLock;
38
+ /**
39
+ * 손상 JSONL 텍스트를 정직 복구한다. 파싱 가능한 유효 라인만 복구하고,
40
+ * 파싱 불가/스키마 불일치 라인은 **버리고 카운트**한다(추정 복원 금지).
41
+ * @param isValid 복구 라인의 스키마 검증(선택). 통과 못하면 폐기.
42
+ */
43
+ function repairJsonl(raw, isValid) {
44
+ const lines = raw.split('\n');
45
+ const recovered = [];
46
+ const droppedAt = [];
47
+ let total = 0;
48
+ lines.forEach((line, idx) => {
49
+ const s = line.trim();
50
+ if (!s)
51
+ return; // 빈 줄은 라인 수에 미포함
52
+ total += 1;
53
+ try {
54
+ const o = JSON.parse(s);
55
+ if (isValid && !isValid(o)) {
56
+ droppedAt.push(idx + 1);
57
+ return;
58
+ }
59
+ recovered.push(o);
60
+ }
61
+ catch {
62
+ droppedAt.push(idx + 1); // 파싱 불가 → 폐기(날조 복원 안 함)
63
+ }
64
+ });
65
+ return { recovered, droppedLines: droppedAt.length, droppedAt, total };
66
+ }
@@ -0,0 +1,42 @@
1
+ import { SlackChannel, SendResult } from './channels';
2
+ import { A2AContext } from './agent-os-rd';
3
+ import { FinanceWorkflowEngine, FinanceRequest, WorkflowDecision } from './finance-workflow';
4
+ /** 실 Slack 이벤트에서 금융 인테이크에 필요한 필드(채널·사용자·텍스트)를 추출. */
5
+ export interface SlackFinanceEvent {
6
+ channel: string;
7
+ user: string;
8
+ text: string;
9
+ }
10
+ /**
11
+ * 실제 Slack Events API `event_callback`(message) 페이로드 → SlackFinanceEvent|null.
12
+ * 코어 SlackChannel.parseInbound 와 동일한 수용 조건(메시지·텍스트有·봇아님·subtype無)에
13
+ * 더해 e.user 를 추출한다. challenge/봇/비-메시지는 null.
14
+ */
15
+ export declare function parseSlackFinanceEvent(payload: any): SlackFinanceEvent | null;
16
+ /** Socket Mode 봉투(events_api)에서도 동일 추출. */
17
+ export declare function parseSlackFinanceEnvelope(env: any): SlackFinanceEvent | null;
18
+ export interface ParseResult {
19
+ ok: boolean;
20
+ request?: Omit<FinanceRequest, 'channel' | 'requester'>;
21
+ error?: string;
22
+ }
23
+ export declare function parseFinanceCommand(text: string, today?: Date): ParseResult;
24
+ export interface IntakeOutcome {
25
+ parsed: SlackFinanceEvent | null;
26
+ request: FinanceRequest | null;
27
+ decision: WorkflowDecision | null;
28
+ reply: string;
29
+ /** 실 채널 전송 결과(전송 시도했을 때). 미전송이면 null. */
30
+ send: SendResult | null;
31
+ }
32
+ /** 품의자(Slack user) → 위임 토큰·컨텍스트. 운영에선 역할 원장에서 조회. */
33
+ export type FinanceAuthorizer = (req: FinanceRequest) => {
34
+ token: string;
35
+ ctx: A2AContext;
36
+ };
37
+ /**
38
+ * 실 Slack 페이로드 1건을 받아 금융 워크플로우로 처리하고 답장 텍스트를 만든다.
39
+ * slackChannel 이 설정(토큰)되어 있으면 실제 chat.postMessage 로 전송하고 결과를 채운다.
40
+ * 미설정이면 send=null 로 두고 reply 만 반환한다(가짜 전송 금지).
41
+ */
42
+ export declare function handleSlackFinanceEvent(payload: any, engine: FinanceWorkflowEngine, authorize: FinanceAuthorizer, slackChannel?: SlackChannel): Promise<IntakeOutcome>;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // BM 출원③ — Slack 실 인테이크 어댑터 (700 옴니채널 → 710 금융 워크플로우)
4
+ // ----------------------------------------------------------------------------
5
+ // 실제 Slack Events API / Socket Mode 페이로드(스키마)를 받아 FinanceRequest 로
6
+ // 정규화하고, FinanceWorkflowEngine(720 caveat·730 오라클·750 신뢰)으로 처리한 뒤
7
+ // 답장 텍스트를 만든다. 실 네트워크 전송은 SlackChannel.send(실 chat.postMessage).
8
+ //
9
+ // 정직 고지(제1계명):
10
+ // - 페이로드 파싱은 코어 `SlackChannel.parseInbound` 의 검증조건을 그대로 따르되,
11
+ // 금융 품의에 필요한 **발신 사용자(e.user)** 를 추가 추출한다(코어 미변경).
12
+ // - 실 송수신 성공은 SLACK_BOT_TOKEN/SLACK_APP_TOKEN 이 있어야 검증된다.
13
+ // 토큰이 없으면 send 는 ok:false('미설정') 를 반환한다(mock 성공 연기 금지).
14
+ // ============================================================================
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.parseSlackFinanceEvent = parseSlackFinanceEvent;
17
+ exports.parseSlackFinanceEnvelope = parseSlackFinanceEnvelope;
18
+ exports.parseFinanceCommand = parseFinanceCommand;
19
+ exports.handleSlackFinanceEvent = handleSlackFinanceEvent;
20
+ const channels_1 = require("./channels");
21
+ /**
22
+ * 실제 Slack Events API `event_callback`(message) 페이로드 → SlackFinanceEvent|null.
23
+ * 코어 SlackChannel.parseInbound 와 동일한 수용 조건(메시지·텍스트有·봇아님·subtype無)에
24
+ * 더해 e.user 를 추출한다. challenge/봇/비-메시지는 null.
25
+ */
26
+ function parseSlackFinanceEvent(payload) {
27
+ // 코어 파서로 1차 검증(채널·텍스트·event_callback·봇배제 등 동일 규칙 재사용)
28
+ const base = channels_1.SlackChannel.parseInbound(payload);
29
+ if (!base)
30
+ return null;
31
+ const e = payload.event;
32
+ const user = e?.user ? String(e.user) : '';
33
+ if (!user)
34
+ return null; // 품의자 식별 불가 → 처리 안 함(정직)
35
+ return { channel: base.from, user, text: base.text };
36
+ }
37
+ /** Socket Mode 봉투(events_api)에서도 동일 추출. */
38
+ function parseSlackFinanceEnvelope(env) {
39
+ if (env?.type === 'events_api')
40
+ return parseSlackFinanceEvent(env.payload);
41
+ return null;
42
+ }
43
+ // ---------------------------------------------------------------------------
44
+ // 명령 텍스트 → FinanceRequest 파서 (결정적 문법)
45
+ // 문법: <유형> <금액> <계정과목> <수취처...> [승인자:NAME]
46
+ // 예) "경비 120000 식대 ACME"
47
+ // "송금 2000000 vendor ACME상사 승인자:U_BOB"
48
+ // ---------------------------------------------------------------------------
49
+ const TYPE_ALIAS = {
50
+ 경비: 'expense', expense: 'expense',
51
+ 송금: 'transfer', transfer: 'transfer', 이체: 'transfer',
52
+ };
53
+ const CATEGORY_ALIAS = {
54
+ 출장: 'travel', travel: 'travel',
55
+ 식대: 'meal', meal: 'meal',
56
+ 사무: 'office', office: 'office',
57
+ 거래처: 'vendor', vendor: 'vendor',
58
+ 급여: 'payroll', payroll: 'payroll',
59
+ };
60
+ let _seq = 0;
61
+ function parseFinanceCommand(text, today = new Date()) {
62
+ const tokens = text.trim().split(/\s+/).filter(Boolean);
63
+ if (tokens.length < 4)
64
+ return { ok: false, error: '형식: <유형> <금액> <계정과목> <수취처> [승인자:NAME]' };
65
+ const type = TYPE_ALIAS[tokens[0].toLowerCase()] ?? TYPE_ALIAS[tokens[0]];
66
+ if (!type)
67
+ return { ok: false, error: `알 수 없는 유형: ${tokens[0]} (경비/송금)` };
68
+ const amount = Number(tokens[1].replace(/[,_]/g, ''));
69
+ if (!Number.isFinite(amount) || amount <= 0)
70
+ return { ok: false, error: `금액 파싱 실패: ${tokens[1]}` };
71
+ const category = CATEGORY_ALIAS[tokens[2].toLowerCase()] ?? CATEGORY_ALIAS[tokens[2]] ?? tokens[2];
72
+ // 승인자 토큰 분리
73
+ let approver;
74
+ const rest = [];
75
+ for (const t of tokens.slice(3)) {
76
+ const m = t.match(/^(?:승인자|approver):(.+)$/);
77
+ if (m)
78
+ approver = m[1];
79
+ else
80
+ rest.push(t);
81
+ }
82
+ const payee = rest.join(' ').trim();
83
+ if (!payee)
84
+ return { ok: false, error: '수취처 누락' };
85
+ const date = today.toISOString().slice(0, 10);
86
+ return {
87
+ ok: true,
88
+ request: { id: `slk-${++_seq}-${Date.now().toString(36)}`, type, amount, category, payee, date, approver },
89
+ };
90
+ }
91
+ function formatReply(req, d) {
92
+ const won = req.amount.toLocaleString('ko-KR');
93
+ if (d.approved) {
94
+ return `✅ [승인] ${req.type === 'transfer' ? '송금' : '경비'} 품의 — ${req.payee} ${won}원(${req.category}). 감사 ${d.auditId}.`;
95
+ }
96
+ const map = { trust: '신뢰(인증/평판)', caveat: '규제 경계(caveat)', oracle: '독립 검증(규정)', execute: '실행 단계' };
97
+ const why = d.violations.join('; ') || d.controls.find((c) => !c.passed)?.reason || '사유 미상';
98
+ return `⛔ [차단] ${map[d.decidedBy] ?? d.decidedBy} — ${why}. (가치 v=${d.value.toFixed(2)}, 신뢰 t=${d.trust.toFixed(2)})`;
99
+ }
100
+ /**
101
+ * 실 Slack 페이로드 1건을 받아 금융 워크플로우로 처리하고 답장 텍스트를 만든다.
102
+ * slackChannel 이 설정(토큰)되어 있으면 실제 chat.postMessage 로 전송하고 결과를 채운다.
103
+ * 미설정이면 send=null 로 두고 reply 만 반환한다(가짜 전송 금지).
104
+ */
105
+ async function handleSlackFinanceEvent(payload, engine, authorize, slackChannel) {
106
+ const parsed = parseSlackFinanceEvent(payload);
107
+ if (!parsed)
108
+ return { parsed: null, request: null, decision: null, reply: '', send: null };
109
+ const pr = parseFinanceCommand(parsed.text);
110
+ if (!pr.ok || !pr.request) {
111
+ const reply = `⚠ 인식 실패: ${pr.error}`;
112
+ const send = slackChannel?.isConfigured() ? await slackChannel.send(parsed.channel, reply) : null;
113
+ return { parsed, request: null, decision: null, reply, send };
114
+ }
115
+ const request = { ...pr.request, channel: 'slack', requester: parsed.user };
116
+ const { token, ctx } = authorize(request);
117
+ const decision = engine.process(request, token, ctx);
118
+ const reply = formatReply(request, decision);
119
+ // 실 네트워크 전송(토큰 있을 때만 — 그 전엔 (목표;미측정))
120
+ const send = slackChannel?.isConfigured() ? await slackChannel.send(parsed.channel, reply) : null;
121
+ return { parsed, request, decision, reply, send };
122
+ }
@@ -0,0 +1,113 @@
1
+ import type { Candidate } from './predictive-agent';
2
+ import type { SymbolicMetaTuple } from './index';
3
+ /** AST/진단 오차 1건. */
4
+ export interface AstError {
5
+ line: number;
6
+ code: string;
7
+ msg: string;
8
+ }
9
+ /** m_t — 기호 메타 튜플("정확한 사실"). 코어 SymbolicMetaTuple 의 상위집합. */
10
+ export interface MetaTuple {
11
+ targetFile: string;
12
+ astErrors: AstError[];
13
+ depMap?: Record<string, string[]>;
14
+ buildStatus: 'pass' | 'fail' | 'unknown';
15
+ }
16
+ /** 편집 행동 a_t — 후보의 역학용 표현. */
17
+ export interface EditAction {
18
+ id: string;
19
+ kind: 'edit' | 'command';
20
+ file?: string;
21
+ content?: string;
22
+ command?: string;
23
+ }
24
+ /** s_t — 하이브리드 상태. z 는 G4에서 합류(현재 optional·미사용). */
25
+ export interface HybridState {
26
+ z?: Float32Array;
27
+ m: MetaTuple;
28
+ }
29
+ /** δ: 전이가 규칙으로 결정 가능한가(deny-by-default — G2 실장). */
30
+ export type Decidable = (m: MetaTuple, a: EditAction) => boolean;
31
+ /** Φ: 규칙 전이 — 편집을 VFS 복사본에 적용 후 컴파일러 재평가로 m_{t+1} 산정(G1 실장). */
32
+ export type RuleTransition = (m: MetaTuple, a: EditAction) => Promise<MetaTuple>;
33
+ /** ρ: 규칙 보상(얕은 신호) = αΔ|E| − β|new| + γ·[build pass] (G2 실장). 오라클 앵커 아님. */
34
+ export type RuleReward = (m: MetaTuple, mNext: MetaTuple) => number;
35
+ /** 후보(Candidate) → 편집 행동(EditAction). 핫패스 불변, 역학 인터페이스용 변환. */
36
+ export declare function candidateToEditAction(c: Candidate): EditAction;
37
+ /** 코어 SymbolicMetaTuple(제로카피 슬롯 포맷) → MetaTuple. astErrorCode>0 ⇒ 오차 1건으로 표현. */
38
+ export declare function fromSymbolicMetaTuple(s: SymbolicMetaTuple): MetaTuple;
39
+ /** MetaTuple → 코어 SymbolicMetaTuple(다운캐스트, 손실 가능 — 첫 오차 코드만 보존). */
40
+ export declare function toSymbolicMetaTuple(m: MetaTuple): SymbolicMetaTuple;
41
+ /** MetaTuple 직렬화(JSON). 왕복 보존 검증용. */
42
+ export declare function serializeMeta(m: MetaTuple): string;
43
+ export declare function deserializeMeta(s: string): MetaTuple;
44
+ /** 오차 개수 |E(m)| — ρ·δ 가 참조할 헬퍼. */
45
+ export declare function errorCount(m: MetaTuple): number;
46
+ /** 파일 확장자로 컴파일러 진단 지원 여부. JS=node --check(구문), TS=tsc(구문+타입). */
47
+ export declare function isCompilerDecidableFile(file: string): boolean;
48
+ /**
49
+ * 컴파일러 재평가로 단일 파일의 MetaTuple 산정(결정론적).
50
+ * JS: `node --check`(구문). TS: `tsc --noEmit`(구문+**타입**) — node --check 가 못 잡는 타입 오류 포착.
51
+ */
52
+ export declare function recompileMeta(dir: string, relFile: string): Promise<MetaTuple>;
53
+ /**
54
+ * Φ 팩토리: 워크스페이스 기준 규칙 전이. 편집 a 를 복사본에 적용 → 컴파일러 재평가 →
55
+ * 새 MetaTuple(m_{t+1}). 결정론적·건전(컴파일러 의미론과 일치, 환각 없음 — [논문] 정리 1).
56
+ */
57
+ export declare function makePhi(workspaceDir: string): RuleTransition;
58
+ /** δ — 편집의 컴파일러 결정 가능성. JS 편집만 결정 가능(현재), 그 외(명령·비JS)=0. */
59
+ export declare const isDecidable: Decidable;
60
+ /** ρ 계수(보상 형상). 빌드 통과 보너스 γ 가 지배적이도록. */
61
+ export declare const RHO_ALPHA = 0.1;
62
+ export declare const RHO_BETA = 0.2;
63
+ export declare const RHO_GAMMA = 1;
64
+ /** ρ = αΔ|E| − β|new| + γ·[build pass]. 얕은 사전 정렬 신호([논문] §3.5). */
65
+ export declare const ruleReward: RuleReward;
66
+ import * as _ts from 'typescript';
67
+ export declare class WarmTypeChecker {
68
+ private files;
69
+ private service;
70
+ private options;
71
+ constructor(opts?: _ts.CompilerOptions);
72
+ /** TS 내부는 포워드슬래시 경로를 쓰므로 키를 정규화(Windows 백슬래시 불일치 방지). */
73
+ private static norm;
74
+ /** 파일 내용 설정(버전 증가 → 증분 재검사). */
75
+ setFile(fileName: string, content: string): void;
76
+ /** 한 파일의 구문+의미 진단(증분). */
77
+ private diagnosticsFor;
78
+ /** 단일 파일의 구문+의미 진단(증분, in-process). spawn 없음. */
79
+ check(fileName: string, content: string): AstError[];
80
+ /** 워크스페이스의 .ts/.tsx 를 전부 시드(node_modules·.git 제외). 프로그램이 프로젝트 전체. */
81
+ seedDir(dir: string): Promise<number>;
82
+ /** 디렉토리를 *최초 1회만* 시드(재사용 checker의 워밍업 amortize). 이미 시드된 dir 은 skip. */
83
+ private seededDirs;
84
+ seedDirOnce(dir: string): Promise<number>;
85
+ /** 주어진 파일 집합의 (file:line:code)→AstError 진단 맵. */
86
+ private diagnosticsOver;
87
+ /** 시드된 전 파일 진단(프로젝트 전체) — 폴백·전수 검사용. */
88
+ private allProjectErrors;
89
+ /**
90
+ * G3e 최적화 — 편집 파일이 *영향을 줄 수 있는* 파일 집합: {편집파일} ∪ 그 파일을 (전이적으로)
91
+ * import 하는 의존자. 편집은 다른 파일의 내용을 바꾸지 않으므로 새 오차는 이 집합에만 생긴다(건전).
92
+ * `getFileReferences`(역참조)로 BFS. 미지원/실패 시 전 파일로 폴백(건전성 우선).
93
+ */
94
+ affectedFiles(editedAbsFile: string): string[];
95
+ /**
96
+ * 편집이 *프로젝트에 새로 도입하는* 오차(교차파일 포함). **영향 파일 집합만** 전후 진단 비교
97
+ * (전수 대신 {편집파일}∪의존자) → 후보당 비용 절감. 체커 상태는 호출 후 원복.
98
+ * @param affected 사전 계산된 영향 집합(동일 파일을 여러 후보가 편집할 때 캐시 재사용). 미지정 시 자동.
99
+ */
100
+ addedErrorsForEdit(editedAbsFile: string, content: string, affected?: string[]): AstError[];
101
+ }
102
+ /** 웜 체커로 MetaTuple 산정(콜드 tsc spawn 대신 in-process 증분). */
103
+ export declare function recompileMetaWarm(checker: WarmTypeChecker, fileName: string, content: string): MetaTuple;
104
+ export interface GfastEval {
105
+ decidable: boolean;
106
+ mNext?: MetaTuple;
107
+ rho?: number;
108
+ }
109
+ /**
110
+ * 한 후보에 대한 g_fast 기호 경로 평가: δ → (Φ → ρ). 결정 불가면 {decidable:false}(오라클 위임).
111
+ * 비싼 테스트 오라클 대신 *컴파일러* 만 돌린다.
112
+ */
113
+ export declare function gfastEvaluate(workspaceDir: string, m0: MetaTuple, a: EditAction): Promise<GfastEval>;