@routinecrew/routinecode 2.31.30 → 2.31.32
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/bin/prompt-vault.js +1 -1
- package/bin/setup.js +1 -1
- package/hooks/pending-drainer.sh +254 -0
- package/hooks/post-tool-universal.sh +23 -0
- package/hooks/pre-agent-spawn.mjs +1 -1
- package/hooks/pre-read-knowledge-inject.sh +65 -12
- package/hooks/recorder-runner.sh +20 -1
- package/hooks/session-start.sh +25 -0
- package/hooks/stop-usage-metrics.sh +27 -0
- package/mcp-db-manager/dist/analyzers/duplicate-detector.js +1 -1
- package/mcp-db-manager/dist/core/model-parser.js +1 -1
- package/mcp-db-manager/dist/core/schema-reader.js +1 -1
- package/mcp-db-manager/dist/executors/migration-executor.js +1 -1
- package/mcp-db-manager/dist/generators/migration-generator.js +1 -1
- package/mcp-db-manager/dist/index.js +1 -1
- package/mcp-db-manager/dist/validators/schema-validator.js +1 -1
- package/mcp-dev-tester/dist/analyzers/auth-diagnoser.js +1 -1
- package/mcp-dev-tester/dist/analyzers/backend-analyzer.js +1 -1
- package/mcp-dev-tester/dist/analyzers/endpoint-diagnoser.js +1 -1
- package/mcp-dev-tester/dist/analyzers/frontend-analyzer.js +1 -1
- package/mcp-dev-tester/dist/analyzers/runtime-diagnoser.js +1 -1
- package/mcp-dev-tester/dist/analyzers/type-comparator.js +1 -1
- package/mcp-dev-tester/dist/analyzers/validation-diagnoser.js +1 -1
- package/mcp-dev-tester/dist/browser/playwright-manager.js +1 -1
- package/mcp-dev-tester/dist/browser/ui-tester.js +1 -1
- package/mcp-dev-tester/dist/config/project-config.js +1 -1
- package/mcp-dev-tester/dist/index.js +1 -1
- package/mcp-dev-tester/dist/testers/api-tester.js +1 -1
- package/mcp-doc-fetcher/dist/index.js +1 -1
- package/mcp-html-renderer/dist/index.js +1 -1
- package/mcp-html-renderer/dist/preview.js +1 -1
- package/mcp-html-renderer/dist/template-engine.js +1 -1
- package/mcp-intelligence/dist/concept-catalog.d.ts +33 -0
- package/mcp-intelligence/dist/concept-catalog.d.ts.map +1 -1
- package/mcp-intelligence/dist/concept-catalog.js +1 -1
- package/mcp-intelligence/dist/concept-server-proxy.js +1 -1
- package/mcp-intelligence/dist/config-auth.js +1 -1
- package/mcp-intelligence/dist/contracts.generated.js +1 -1
- package/mcp-intelligence/dist/domain-templates.js +1 -1
- package/mcp-intelligence/dist/grounding.js +1 -1
- package/mcp-intelligence/dist/handlers.js +1 -1
- package/mcp-intelligence/dist/index.js +1 -1
- package/mcp-intelligence/dist/intelligence-file.js +1 -1
- package/mcp-intelligence/dist/knowledge-critic.js +1 -1
- package/mcp-intelligence/dist/knowledge-handlers.d.ts.map +1 -1
- package/mcp-intelligence/dist/knowledge-handlers.js +1 -1
- package/mcp-intelligence/dist/mention-extractor.js +1 -1
- package/mcp-intelligence/dist/provenance.js +1 -1
- package/mcp-intelligence/dist/semantic-embedder.js +1 -1
- package/mcp-log-watcher/dist/config-auth.js +1 -1
- package/mcp-log-watcher/dist/file-watcher.js +1 -1
- package/mcp-log-watcher/dist/index.js +1 -1
- package/mcp-log-watcher/dist/known-solutions.js +1 -1
- package/mcp-log-watcher/dist/log-store.js +1 -1
- package/mcp-log-watcher/dist/websocket-server.js +1 -1
- package/mcp-plan-manager/dist/__tests__/plan-parser.test.js +1 -1
- package/mcp-plan-manager/dist/file-ops.js +1 -1
- package/mcp-plan-manager/dist/index.js +1 -1
- package/mcp-plan-manager/dist/plan-parser.js +1 -1
- package/mcp-project-context/dist/git-ops.js +1 -1
- package/mcp-project-context/dist/index.js +1 -1
- package/mcp-project-context/dist/project-analysis.js +1 -1
- package/mcp-routinecode/dist/agent-tracker.js +1 -1
- package/mcp-routinecode/dist/blast-radius.js +1 -1
- package/mcp-routinecode/dist/config-auth.js +1 -1
- package/mcp-routinecode/dist/contracts.generated.js +1 -1
- package/mcp-routinecode/dist/explorer-advisor.js +1 -1
- package/mcp-routinecode/dist/failure-tracker.js +1 -1
- package/mcp-routinecode/dist/file-lock-registry.js +1 -1
- package/mcp-routinecode/dist/file-risk-scorer.js +1 -1
- package/mcp-routinecode/dist/index.js +1 -1
- package/mcp-routinecode/dist/known-solutions.js +1 -1
- package/mcp-routinecode/dist/ledger-miner.js +1 -1
- package/mcp-routinecode/dist/observed-draft.js +1 -1
- package/mcp-routinecode/dist/pattern-matcher.js +1 -1
- package/mcp-routinecode/dist/routines.d.ts +18 -0
- package/mcp-routinecode/dist/routines.js +1 -1
- package/mcp-routinecode/dist/rule-engine.js +1 -1
- package/mcp-routinecode/dist/rule-promoter.js +1 -1
- package/mcp-routinecode/dist/telemetry-analyzer.js +1 -1
- package/mcp-routinecode/dist/verification.js +0 -0
- package/mcp-routinecode/dist/viral-loop.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pending-drainer — pending-sync.jsonl 을 서버로 주기 백필. **MCP 비의존**(cwd 무관).
|
|
3
|
+
# session-start 훅이 백그라운드(nohup)로 기동. post-tool-universal 이 6h 안전망으로 재기동.
|
|
4
|
+
# 목표: 각 사용자 pending 이 세션 경계를 넘겨 쌓이지 않게 하고, 유실 0(실패=pending 또는 dead-letter).
|
|
5
|
+
#
|
|
6
|
+
# 설계 L5 (교차검증 97):
|
|
7
|
+
# - config.json(serverUrl/apiKey/tenantId/userId/machineId) 직접 읽어 Bearer POST
|
|
8
|
+
# ${serverUrl}/api/v1/ingest/${endpoint}.
|
|
9
|
+
# - payload body 엔벌로프는 sendToServer 와 **동일** 재구성:
|
|
10
|
+
# {...item.data, tenantId, userId, contributorHash: userId ? 'p:'+userId : machineId}
|
|
11
|
+
# (헤더만으론 서버 dedup/귀속이 깨짐 — body 의 contributorHash 사용)
|
|
12
|
+
# - 디바운스: .last-drain mtime <1h 면 skip. 성공 후 touch.
|
|
13
|
+
# - rate: 요청 간 >=2.5s(<=24/min). 429 는 지수 백오프.
|
|
14
|
+
# - nextAttemptAt(L4 백오프) 존중. 멱등(서버 dedup). claim-rename 으로 동시실행 방지.
|
|
15
|
+
# - 실패 분류/재큐/dead-letter 는 L4(knowledge-handlers) 와 동일 규칙.
|
|
16
|
+
set -u
|
|
17
|
+
|
|
18
|
+
KN="${ROUTINECODE_KNOWLEDGE_DIR:-${ROUTINECODE_DIR:-$HOME/.routinecode}/knowledge}"
|
|
19
|
+
CONFIG="${ROUTINECODE_CONFIG_PATH:-${ROUTINECODE_DIR:-$HOME/.routinecode}/config.json}"
|
|
20
|
+
PENDING="$KN/pending-sync.jsonl"
|
|
21
|
+
DEADLETTER="$KN/pending-sync.deadletter.jsonl"
|
|
22
|
+
MARKER="$KN/.last-drain"
|
|
23
|
+
|
|
24
|
+
# recorder 자신의 세션에서는 돌지 않음(불필요한 중첩 방지)
|
|
25
|
+
[ "${ROUTINECODE_RECORDER:-}" = "1" ] && exit 0
|
|
26
|
+
[ -f "$CONFIG" ] || exit 0
|
|
27
|
+
[ -f "$PENDING" ] || exit 0
|
|
28
|
+
|
|
29
|
+
# ── 디바운스: .last-drain mtime 이 1시간 이내면 skip ──────────────
|
|
30
|
+
# ROUTINECODE_DRAIN_FORCE=1 이면 무시(테스트/수동 트리거용).
|
|
31
|
+
if [ "${ROUTINECODE_DRAIN_FORCE:-}" != "1" ] && [ -f "$MARKER" ]; then
|
|
32
|
+
now_epoch=$(date +%s)
|
|
33
|
+
marker_epoch=$(python3 -c "import os,sys;print(int(os.path.getmtime('$MARKER')))" 2>/dev/null || echo 0)
|
|
34
|
+
if [ "$marker_epoch" -gt 0 ] && [ $((now_epoch - marker_epoch)) -lt 3600 ]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# ── 원자적 claim (동시 실행 방지) ────────────────────────────────
|
|
40
|
+
# recorder-runner.sh 선례: mv 가 실패하면 다른 프로세스가 이미 claim 한 것 → 종료.
|
|
41
|
+
CLAIM="$PENDING.processing.$$"
|
|
42
|
+
mv "$PENDING" "$CLAIM" 2>/dev/null || exit 0
|
|
43
|
+
|
|
44
|
+
# ── drain (python3: 엔벌로프 재구성·분류·백오프·rate·dead-letter) ─
|
|
45
|
+
ROUTINECODE_DRAIN_CONFIG="$CONFIG" \
|
|
46
|
+
ROUTINECODE_DRAIN_CLAIM="$CLAIM" \
|
|
47
|
+
ROUTINECODE_DRAIN_PENDING="$PENDING" \
|
|
48
|
+
ROUTINECODE_DRAIN_DEADLETTER="$DEADLETTER" \
|
|
49
|
+
ROUTINECODE_DRAIN_MARKER="$MARKER" \
|
|
50
|
+
ROUTINECODE_DRAIN_DRY="${ROUTINECODE_DRAIN_DRY:-}" \
|
|
51
|
+
python3 - <<'PYEOF'
|
|
52
|
+
import json, os, sys, time, urllib.request, urllib.error
|
|
53
|
+
|
|
54
|
+
CONFIG = os.environ['ROUTINECODE_DRAIN_CONFIG']
|
|
55
|
+
CLAIM = os.environ['ROUTINECODE_DRAIN_CLAIM']
|
|
56
|
+
PENDING = os.environ['ROUTINECODE_DRAIN_PENDING']
|
|
57
|
+
DEADLETTER = os.environ['ROUTINECODE_DRAIN_DEADLETTER']
|
|
58
|
+
MARKER = os.environ['ROUTINECODE_DRAIN_MARKER']
|
|
59
|
+
DRY = os.environ.get('ROUTINECODE_DRAIN_DRY') == '1'
|
|
60
|
+
|
|
61
|
+
MAX_RETRIES = 10
|
|
62
|
+
BACKOFF_BASE = 5000 # ms
|
|
63
|
+
BACKOFF_CAP = 60*60*1000 # 1h ms
|
|
64
|
+
RATE_WINDOW = 60*1000 # 429 최소 백오프 ms
|
|
65
|
+
MIN_INTERVAL = 2.5 # 요청 간 최소 간격(초) → <=24/min
|
|
66
|
+
MAX_BATCH = 50 # 한 번 drain 상한 (초과분은 CLAIM→pending 로 이월)
|
|
67
|
+
|
|
68
|
+
def now_ms():
|
|
69
|
+
return int(time.time()*1000)
|
|
70
|
+
|
|
71
|
+
def read_config():
|
|
72
|
+
try:
|
|
73
|
+
with open(CONFIG, 'r') as f:
|
|
74
|
+
return json.load(f)
|
|
75
|
+
except Exception:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
def load_claim():
|
|
79
|
+
items = []
|
|
80
|
+
try:
|
|
81
|
+
with open(CLAIM, 'r') as f:
|
|
82
|
+
for line in f:
|
|
83
|
+
line = line.strip()
|
|
84
|
+
if not line:
|
|
85
|
+
continue
|
|
86
|
+
try:
|
|
87
|
+
items.append(json.loads(line))
|
|
88
|
+
except Exception:
|
|
89
|
+
pass # malformed line skip
|
|
90
|
+
except Exception:
|
|
91
|
+
pass
|
|
92
|
+
return items
|
|
93
|
+
|
|
94
|
+
def append_jsonl(path, obj):
|
|
95
|
+
try:
|
|
96
|
+
with open(path, 'a') as f:
|
|
97
|
+
f.write(json.dumps(obj, ensure_ascii=False) + '\n')
|
|
98
|
+
except Exception:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
def requeue(items):
|
|
102
|
+
# CLAIM 소비분 중 미전송/미도래 항목을 pending 으로 되돌림(append, 유실 방지).
|
|
103
|
+
for it in items:
|
|
104
|
+
append_jsonl(PENDING, it)
|
|
105
|
+
|
|
106
|
+
def restore_all_and_exit(items, code=0):
|
|
107
|
+
requeue(items)
|
|
108
|
+
try:
|
|
109
|
+
os.remove(CLAIM)
|
|
110
|
+
except Exception:
|
|
111
|
+
pass
|
|
112
|
+
sys.exit(code)
|
|
113
|
+
|
|
114
|
+
cfg = read_config()
|
|
115
|
+
if not cfg or not cfg.get('syncEnabled') or not cfg.get('serverUrl') or not cfg.get('apiKey'):
|
|
116
|
+
# sync 불가 → claim 원복(유실 금지)
|
|
117
|
+
restore_all_and_exit(load_claim(), 0)
|
|
118
|
+
|
|
119
|
+
server_url = cfg['serverUrl'].rstrip('/')
|
|
120
|
+
api_key = cfg['apiKey']
|
|
121
|
+
tenant_id = cfg.get('tenantId')
|
|
122
|
+
user_id = cfg.get('userId')
|
|
123
|
+
machine_id = cfg.get('machineId')
|
|
124
|
+
contributor = ('p:' + str(user_id)) if user_id else machine_id
|
|
125
|
+
|
|
126
|
+
items = load_claim()
|
|
127
|
+
leftover = [] # 이번 패스에서 전송하지 않고 pending 으로 되돌릴 항목(미도래/백오프/상한초과)
|
|
128
|
+
processed = 0
|
|
129
|
+
last_req_ts = 0.0
|
|
130
|
+
|
|
131
|
+
def classify(status):
|
|
132
|
+
# status 0 = 네트워크/타임아웃 → transient (L4 sendToServer catch 와 동일)
|
|
133
|
+
if status == 0:
|
|
134
|
+
return 'transient'
|
|
135
|
+
if status == 401:
|
|
136
|
+
return 'auth'
|
|
137
|
+
if status >= 500 or status == 429:
|
|
138
|
+
return 'transient'
|
|
139
|
+
return 'permanent' # 그 외 4xx(400/422 등)
|
|
140
|
+
|
|
141
|
+
def compute_next_attempt(retries, status):
|
|
142
|
+
delay = min(BACKOFF_BASE * (2 ** retries), BACKOFF_CAP)
|
|
143
|
+
if status == 429:
|
|
144
|
+
delay = max(delay, RATE_WINDOW)
|
|
145
|
+
return now_ms() + delay
|
|
146
|
+
|
|
147
|
+
def send(endpoint, data):
|
|
148
|
+
# 엔벌로프: sendToServer(:511-518) 와 동일. 헤더만으론 부족.
|
|
149
|
+
body = dict(data)
|
|
150
|
+
body['tenantId'] = tenant_id if tenant_id is not None else None
|
|
151
|
+
body['userId'] = user_id if user_id is not None else None
|
|
152
|
+
body['contributorHash'] = contributor
|
|
153
|
+
if endpoint.startswith('ontology/'):
|
|
154
|
+
url = server_url + '/api/v1/' + endpoint
|
|
155
|
+
else:
|
|
156
|
+
url = server_url + '/api/v1/ingest/' + endpoint
|
|
157
|
+
payload = json.dumps(body).encode('utf-8')
|
|
158
|
+
req = urllib.request.Request(url, data=payload, method='POST')
|
|
159
|
+
req.add_header('Content-Type', 'application/json')
|
|
160
|
+
req.add_header('Authorization', 'Bearer ' + str(api_key))
|
|
161
|
+
try:
|
|
162
|
+
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
163
|
+
return resp.getcode(), ''
|
|
164
|
+
except urllib.error.HTTPError as e:
|
|
165
|
+
try:
|
|
166
|
+
rbody = e.read().decode('utf-8', 'replace')[:2000]
|
|
167
|
+
except Exception:
|
|
168
|
+
rbody = ''
|
|
169
|
+
return e.code, rbody
|
|
170
|
+
except Exception:
|
|
171
|
+
return 0, '' # 네트워크/타임아웃 → transient
|
|
172
|
+
|
|
173
|
+
cur = now_ms()
|
|
174
|
+
for idx, item in enumerate(items):
|
|
175
|
+
# 상한 초과 → 남은 항목 전부 pending 으로 이월
|
|
176
|
+
if processed >= MAX_BATCH:
|
|
177
|
+
leftover.append(item)
|
|
178
|
+
continue
|
|
179
|
+
# L4 백오프 존중: 미도래 항목은 전송하지 않고 되돌림
|
|
180
|
+
next_at = item.get('nextAttemptAt') or 0
|
|
181
|
+
if next_at > cur:
|
|
182
|
+
leftover.append(item)
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
# DRY 모드: 전송하지 않고 재구성된 엔벌로프를 stderr 로 출력(검증용), 항목은 보존
|
|
186
|
+
if DRY:
|
|
187
|
+
body = dict(item.get('data', {}))
|
|
188
|
+
body['tenantId'] = tenant_id if tenant_id is not None else None
|
|
189
|
+
body['userId'] = user_id if user_id is not None else None
|
|
190
|
+
body['contributorHash'] = contributor
|
|
191
|
+
sys.stderr.write('[drain-dry] endpoint=%s envelope=%s\n'
|
|
192
|
+
% (item.get('endpoint'), json.dumps(body, ensure_ascii=False)))
|
|
193
|
+
leftover.append(item)
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# rate: 요청 간 >= MIN_INTERVAL
|
|
197
|
+
wait = MIN_INTERVAL - (time.time() - last_req_ts)
|
|
198
|
+
if wait > 0:
|
|
199
|
+
time.sleep(wait)
|
|
200
|
+
|
|
201
|
+
status, rbody = send(item.get('endpoint', ''), item.get('data', {}))
|
|
202
|
+
last_req_ts = time.time()
|
|
203
|
+
processed += 1
|
|
204
|
+
|
|
205
|
+
if 200 <= status < 300:
|
|
206
|
+
continue # 성공 → 소비(요건: pending/claim 어디에도 남기지 않음)
|
|
207
|
+
|
|
208
|
+
kind = classify(status)
|
|
209
|
+
if kind == 'permanent':
|
|
210
|
+
append_jsonl(DEADLETTER, {
|
|
211
|
+
'endpoint': item.get('endpoint'),
|
|
212
|
+
'data': item.get('data'),
|
|
213
|
+
'ts': item.get('ts'),
|
|
214
|
+
'retries': item.get('retries', 0),
|
|
215
|
+
'reason': 'permanent_4xx',
|
|
216
|
+
'status': status,
|
|
217
|
+
'body': rbody[:2000],
|
|
218
|
+
'deadLetteredAt': time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime()),
|
|
219
|
+
})
|
|
220
|
+
continue
|
|
221
|
+
|
|
222
|
+
# transient | auth → 백오프 재큐, MAX_RETRIES 초과 시 dead-letter(드롭 금지)
|
|
223
|
+
item['retries'] = int(item.get('retries', 0)) + 1
|
|
224
|
+
if item['retries'] >= MAX_RETRIES:
|
|
225
|
+
append_jsonl(DEADLETTER, {
|
|
226
|
+
'endpoint': item.get('endpoint'),
|
|
227
|
+
'data': item.get('data'),
|
|
228
|
+
'ts': item.get('ts'),
|
|
229
|
+
'retries': item['retries'],
|
|
230
|
+
'reason': 'max_retries_exceeded',
|
|
231
|
+
'status': status,
|
|
232
|
+
'body': rbody[:2000],
|
|
233
|
+
'deadLetteredAt': time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime()),
|
|
234
|
+
})
|
|
235
|
+
continue
|
|
236
|
+
item['nextAttemptAt'] = compute_next_attempt(item['retries'], status)
|
|
237
|
+
leftover.append(item)
|
|
238
|
+
|
|
239
|
+
# 미전송/재큐 항목을 pending 으로 되돌림
|
|
240
|
+
requeue(leftover)
|
|
241
|
+
try:
|
|
242
|
+
os.remove(CLAIM)
|
|
243
|
+
except Exception:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
# 디바운스 마커 갱신(이번 drain 완료 표시). DRY 모드에서도 갱신 않음(실제 drain 아님).
|
|
247
|
+
if not DRY:
|
|
248
|
+
try:
|
|
249
|
+
with open(MARKER, 'a'):
|
|
250
|
+
pass
|
|
251
|
+
os.utime(MARKER, None)
|
|
252
|
+
except Exception:
|
|
253
|
+
pass
|
|
254
|
+
PYEOF
|
|
@@ -151,3 +151,26 @@ if is_mcp_tool:
|
|
|
151
151
|
|
|
152
152
|
print('{"continue":true}')
|
|
153
153
|
PYEOF
|
|
154
|
+
|
|
155
|
+
# --- L5 안전망: 장수 세션에서 drainer 재기동 (경량 stat 1회) ---
|
|
156
|
+
# session-start 가 유일 트리거면 장시간 열린 세션에서 drain 이 안 돈다.
|
|
157
|
+
# .last-drain mtime > 6h 일 때만 drainer 를 nohup 재기동한다(평소 비용 ~0).
|
|
158
|
+
# drainer 내부 디바운스(1h)가 중복 실행을 다시 막으므로 과기동해도 무해.
|
|
159
|
+
if [ "${ROUTINECODE_RECORDER:-}" != "1" ]; then
|
|
160
|
+
_RC_HOOKS_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
|
|
161
|
+
_RC_KN="${ROUTINECODE_KNOWLEDGE_DIR:-$HOME/.routinecode/knowledge}"
|
|
162
|
+
_RC_DRAINER="$_RC_HOOKS_DIR/pending-drainer.sh"
|
|
163
|
+
_RC_MARKER="$_RC_KN/.last-drain"
|
|
164
|
+
if [ -f "$_RC_DRAINER" ] && [ -f "$_RC_KN/pending-sync.jsonl" ]; then
|
|
165
|
+
# 마커 없음 OR mtime > 6h(21600s) → 재기동
|
|
166
|
+
_RC_STALE=1
|
|
167
|
+
if [ -f "$_RC_MARKER" ]; then
|
|
168
|
+
_RC_NOW=$(date +%s)
|
|
169
|
+
_RC_MT=$(python3 -c "import os;print(int(os.path.getmtime('$_RC_MARKER')))" 2>/dev/null || echo 0)
|
|
170
|
+
if [ "$_RC_MT" -gt 0 ] && [ $((_RC_NOW - _RC_MT)) -le 21600 ]; then _RC_STALE=0; fi
|
|
171
|
+
fi
|
|
172
|
+
if [ "$_RC_STALE" = "1" ]; then
|
|
173
|
+
nohup bash "$_RC_DRAINER" >/dev/null 2>&1 &
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
fi
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const a0_0x56a23f=a0_0x49e5;(function(_0x5ea239,_0x570203){const _0x5a08e9=a0_0x49e5,_0x39d4a7=_0x5ea239();while(!![]){try{const _0x408aba=-parseInt(_0x5a08e9(0xd6,'LveC'))/(-0x1885+-0x16aa+0x2f30)*(-parseInt(_0x5a08e9(0x1b2,'Z0Jm'))/(-0x1*-0xeb9+0x706*-0x1+-0x7b1))+parseInt(_0x5a08e9(0x105,'U#&Q'))/(-0x8fc+-0x6*0x4a7+0x24e9)+-parseInt(_0x5a08e9(0x161,'WTD0'))/(0x231e+-0xe13*-0x1+-0x312d)*(-parseInt(_0x5a08e9(0x129,'ng)J'))/(0x36f*-0x7+0x3*-0xbf8+-0x266*-0x19))+parseInt(_0x5a08e9(0xcd,'U#&Q'))/(-0x1a91+-0x49d*0x3+0x286e)+-parseInt(_0x5a08e9(0x149,'IlXp'))/(0x64d*-0x1+0x5*-0x595+0x223d)*(-parseInt(_0x5a08e9(0x186,'qsb8'))/(-0x2675+0x6*0x3b7+0x1033))+-parseInt(_0x5a08e9(0x199,'IlXp'))/(0x26b+-0x7bc+0x2ad*0x2)*(-parseInt(_0x5a08e9(0x138,'LQZ('))/(0xcc4+0x3ab*0x7+-0x2667*0x1))+-parseInt(_0x5a08e9(0xb5,'LveC'))/(-0x2*0x553+0xb0c+-0x5b)*(parseInt(_0x5a08e9(0xb6,'$en$'))/(0x5*-0x4fb+-0x4*-0x6f3+-0x2d9));if(_0x408aba===_0x570203)break;else _0x39d4a7['push'](_0x39d4a7['shift']());}catch(_0x354333){_0x39d4a7['push'](_0x39d4a7['shift']());}}}(a0_0x56ae,-0x3f1*0xbf+-0x31c0e+0xbe490));import{fileURLToPath}from'node:url';function a0_0x56ae(){const _0x2f7450=['rqtdUJhcQa','w8knW4Lmxa','x8o9WPpdNqtcJM/dQ8ov','WQX3qW','j1ZcLMvxW5OZlxq','FCkxfSo7Ba','ltWNiu8','WPVcTeFcG3m','WOuOuSkjWRy','WPFdTKnMxa','W7HkWQXwW6y','W53dV1NdNuK','csepWP/cQa','WOX/iCo5o8o7WQmxfYe0WP9o','WOJcM8k0WRGK','xSoRWOW','W54nWRPJW6e','cYGhWQa','a8oQfCol','WPBdRuONoW','lSo1f8o6W5e','ySkgW4vyWRTIWRhdTg/dSmkxW4Sr','x8o3WPdcHMddLqVdR8obW5PJW5FdIa','a3NdHCo4W7jSWP/dNe8','vg/cHmo/W40','W60HEmkxqW','ACofWOqmWQq','WPydW5XHWQi','WRZdJ3BcV8kb','WRSOcSkVW5u','iZFdTmoNja','W5ZdJKqIW6u','Dwayr8kj','WPfKiCkSW4m','W58QFCkJzG','ccaBWPm','WOi5zSogWPy','BCo9WPZcUNO','o8k6k8oovq','DmkYi8oocq','WOBdTeLKDW','WRDaW4VcG8oz','WQBdQ0FdOmkh','gI4SWOjD','vCkkf8o+sG','WO4ae8kqbuVcH8oGW7eszgGF','qmkUW5ddMdW','qSoMWRKRmq','DmkTnG','W50lWRXHW78','WOBcRvFcRxa','W4K5W7rtWPK','W6dcI27dSKO','W6PJWPL7W6y','yLKNW5ZdIa','bZCvW47cOq','gbiwWR7cOa','qJVcHmosW5i','WOxcISkdWP0MWPD6mmkboCkbyMW','odixWR7cHW','W5X9rSodDq','W4KfWPHhW5G','WPOXWRKdga','WRSPWOqalq','vb7cSSkwca','W6XpaNf+','w8kTDSk4FW','iZldUmoZBq','WPCUWQiXhq','WO8SxG','FSk7s8kMqW','r8o+WOqmka','WPtdIhv/AW','W4FdKL8LW7G','zfKGWOy','W5O4W79vWOu','sstcOmoqW7q','felcTNtcMmo2CW','W6CsWR9yW4q','W5OAWOGUW5i','WPuOW7zeWOW','W6RcLs/dSf8','W4zOWQeRdmkRWQtdJa','WOe4WQHIta','WQuktCkVzW','bGVdUSkecW','jtedWPVcMa','rmoFW4jexW','WP3cICk+WOiP','dq0kmKW','WOCfW64LWOm','kmoTWRRcVwy','W5hcQHqYBKpdKWSIW7W','vX3dP0vI','ccOiWPNcVq','jmohWP8DW6W','WQqUWQGwaq','kYfXWOZdLW','y1nYW4RdHa','WRNdJxxdT8ot','W4OAWQzNW7y','yCkaW4vFWRfLW7FdJ0ZdSmkjW6K','WRWWW5XIWQi','gmkDW64','yfCMW4a','hwdcNCo9qa','WO7cIgBcRu0','WR/cJgddVCkg','hJaDWPJcQW','pqKJWP/cLW','Fv3cLmozW7y','d1dcQ37cRW','FWBdH3TO','WROOW6r8WOS','uxtcPSo6W68','W4uAWQCGW7S','WPCjW4bX','vmkGW4BdHdS','fJldTmobAW','W4tdNCoe','jNNcRq','WRO7omkzpW','W5JdL8osW4WU','WP8xmvJdIq','W5/dUSoWW5Pe','WPtdNM14DW','xmo9WPVcGsVcLh/dSmonW5G','WQfguSkJFW','W7ldK3RcHvK','qLBcUwlcSG','FvtcN8oyW7y','mcWJku4','ACoqbMXe','kcWYl0W','nSkaybm7W4ddH2OebIG5','rL3dOSopfSo+quDHWQq','amoQWQRcJg0','nJyWW5pcHW','W6JcL2pdPvK','ASoXsaOU','W7hdHg3dHG','xIpcO8oiW5K','W6P1WP1iW70','W5pcMmosW4XN','pmozWQmAW6W','WQOlvCkbzG','WOmzg8kspG','WPqwrmkgoG','aahcLSkyda','kY80WQhcVq','qCkrjq','W6lcLIRdSKu','mqFdKmoNCa','oCoYwreQ','fSoboCoTW7q','AgddG8oGAG','W7RdKxZdPfS','Emk+j8oztW','b8kFWPGDhCo8aSk4WPyceCo2aW','WQOcaCkMFW','ECkfq8kjqq','gqmzcvW','WOBdOfpcHgC','W43dMKBdSxC','nxJdSSo0rW','mmoAWOqmWQK','b8kPW5pdMZC','nCkeygfnWOpdNgau','vu4IW4tdJG','W5JdJmoLW4P7','EGZdGwD1','hCo1pCoLt8kOj8kladq','WPXkW6y4WQKDgYPogSobgW','oCk8xXCI','W6zJWP1rW6y','ts3dQubk','kSobi0n0','vYhcSSoTW7m','WRddNMi','W7blhwD1','vSoIAraH','WPGxWRS1aq','kgddSmo7ya','WRFdGKldHmk8','W4ddJLiQW6W','WPiBcSkekW','s8o9WOmGiq','W4TwEW','aCkQWO0','WOeiBSkAxa','W5KQWQWUbW','W7xdHtFdTfG','W7H/rYFcOG','WPCbW4DSWQG','mcyKiXa','b8kQW4BdLd0','W5JcMmo1W6zA','mcq0b1W','WOuOsCkpWRy','cmo/bmoPW4q','WQyJW41NW70','vSkTWQPZgW','pCownLfQ','W6mYwSoYWOW','WQFcJc7dPuC','b8o+hmohW4u','BCoeWReMmW','W50kWRjPW7q','eGhcQmkswW','WOPpW7JcMCoJ','W6P0wrdcJq','n8oZW7ffWQC','W40EWQfNW74','W5fnsCoixW','bSkyWPSDhmo6zSkkWPWqg8oJ','WOhcRKtdJg8','nY4UzLW','AbOlWQ7cJG','mY7dUSo7AW','W7FdIxRdL0G','WO5dEGNcIG','zSorjWj3','jZC3WOzD','WP8YWQi1aG','W6rXB8oMEa','WPmOECkPWPy','jN/cUSoH','W7Guud5Y','nSkLg05N','o3dcTSoWrW','W7zbgwW','l3mmWQdcKG','W559cLrQ','cdWvWOi','WOqXW6PWWQ8','W59NW5VdPSoL','W5HqrSoq','xCkrgmoQxq','W5ldIfTR','aYNcM8kfdW','WRlcRwdcLw4','pSoRWP3cTxS','gIWtWP5R','p8oqWPSmW6C','xCoWW75HWOa','imoqWOCCW6W','zIekWRJcLG','W58VFmkIta','vmkMhmobW5dcOSo/W6i','DWldG2f1','z27cSCo2FWVdRG','CX3dG2W','tSk2W4BdGtS','DhrIWPxdKqdcRxOvfYVdNG','eIBcN8k2ma','oXJcMmkzhq','W7XUWOjwW7S','aYyPWRJcIa','W5mPDSkLnW','WPOhW50LWRC','W5TiWRvWWRi'];a0_0x56ae=function(){return _0x2f7450;};return a0_0x56ae();}import{dirname,resolve}from'node:path';import{existsSync}from'node:fs';async function readStdin(){const _0x2d31c1=a0_0x49e5;let _0x4f01c7='';for await(const _0x5a962a of process[_0x2d31c1(0x120,'LHMM')])_0x4f01c7+=_0x5a962a;return _0x4f01c7;}function a0_0x49e5(_0x1e381d,_0x3db808){_0x1e381d=_0x1e381d-(0x61*-0x4b+-0x192b+0x3644);const _0xb34e80=a0_0x56ae();let _0xb9666a=_0xb34e80[_0x1e381d];if(a0_0x49e5['bhnCNj']===undefined){var _0x4f569c=function(_0x16754b){const _0x33dd60='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2dad5a='',_0xe21396='';for(let _0x2ac976=0xeab+-0x5*0x2f+0x37*-0x40,_0x1d68b3,_0x25abb8,_0x5dab50=-0x1*0x105c+-0x1b08+0x2b64;_0x25abb8=_0x16754b['charAt'](_0x5dab50++);~_0x25abb8&&(_0x1d68b3=_0x2ac976%(0x7*-0x71+0x10d3+-0xdb8)?_0x1d68b3*(-0x193c+0xd28+-0x107*-0xc)+_0x25abb8:_0x25abb8,_0x2ac976++%(0x1a45+0x1428+-0x2e69))?_0x2dad5a+=String['fromCharCode'](0x15b5+0x1aa6+-0xbd7*0x4&_0x1d68b3>>(-(-0x412+-0x50*-0x7a+-0x220c)*_0x2ac976&-0x1*-0x1583+-0x1c29+0xf4*0x7)):-0x596+0xc5d+-0x6c7){_0x25abb8=_0x33dd60['indexOf'](_0x25abb8);}for(let _0x396dc5=0x226c+0x537*-0x6+-0x1*0x322,_0x4f1fb0=_0x2dad5a['length'];_0x396dc5<_0x4f1fb0;_0x396dc5++){_0xe21396+='%'+('00'+_0x2dad5a['charCodeAt'](_0x396dc5)['toString'](-0x1*-0x29e+0x26*-0xd6+0x1d36))['slice'](-(0x11*-0x6b+0x5c7*-0x2+-0x3*-0x639));}return decodeURIComponent(_0xe21396);};const _0x5e3bfd=function(_0x255863,_0x2384a0){let _0x38dc4a=[],_0x19a480=0x2a7+0x1a3a+-0x1ce1,_0x21d5d5,_0x550d78='';_0x255863=_0x4f569c(_0x255863);let _0x47ded0;for(_0x47ded0=0xfa+-0x1*0x715+0x1*0x61b;_0x47ded0<-0x92*0x16+0x6a*-0x16+0x16a8;_0x47ded0++){_0x38dc4a[_0x47ded0]=_0x47ded0;}for(_0x47ded0=0x2*-0xd92+-0x1c65+0x3789;_0x47ded0<-0x13b0+-0x2f*0x17+0x1*0x18e9;_0x47ded0++){_0x19a480=(_0x19a480+_0x38dc4a[_0x47ded0]+_0x2384a0['charCodeAt'](_0x47ded0%_0x2384a0['length']))%(0x2cf*0x6+0x3cb*-0x2+-0x844),_0x21d5d5=_0x38dc4a[_0x47ded0],_0x38dc4a[_0x47ded0]=_0x38dc4a[_0x19a480],_0x38dc4a[_0x19a480]=_0x21d5d5;}_0x47ded0=-0x19*-0x14c+-0x4cf*0x4+0x2*-0x698,_0x19a480=0x174a+-0x2295+0xb4b;for(let _0x3bc204=-0x2225+0xaeb*0x3+-0x2*-0xb2;_0x3bc204<_0x255863['length'];_0x3bc204++){_0x47ded0=(_0x47ded0+(0x2ff+0x12e7*-0x1+0xfe9))%(0x25*0x51+0xb*0xa2+-0x11ab),_0x19a480=(_0x19a480+_0x38dc4a[_0x47ded0])%(0x105f+-0x718+0x1*-0x847),_0x21d5d5=_0x38dc4a[_0x47ded0],_0x38dc4a[_0x47ded0]=_0x38dc4a[_0x19a480],_0x38dc4a[_0x19a480]=_0x21d5d5,_0x550d78+=String['fromCharCode'](_0x255863['charCodeAt'](_0x3bc204)^_0x38dc4a[(_0x38dc4a[_0x47ded0]+_0x38dc4a[_0x19a480])%(-0x2431+-0x1afe+0x3*0x1565)]);}return _0x550d78;};a0_0x49e5['EHcxuN']=_0x5e3bfd,a0_0x49e5['HIIRaK']={},a0_0x49e5['bhnCNj']=!![];}const _0x44f9ae=_0xb34e80[0xd25+0x5*0x6f7+0x17fc*-0x2],_0x41cbe0=_0x1e381d+_0x44f9ae,_0x51198e=a0_0x49e5['HIIRaK'][_0x41cbe0];return!_0x51198e?(a0_0x49e5['LtiqRK']===undefined&&(a0_0x49e5['LtiqRK']=!![]),_0xb9666a=a0_0x49e5['EHcxuN'](_0xb9666a,_0x3db808),a0_0x49e5['HIIRaK'][_0x41cbe0]=_0xb9666a):_0xb9666a=_0x51198e,_0xb9666a;}function emit(_0x4f1745){const _0x2df082=a0_0x49e5;process[_0x2df082(0x13b,'Deqw')+'t'][_0x2df082(0x193,'IlXp')](JSON[_0x2df082(0x16d,'Qy!P')+_0x2df082(0x11b,'WTD0')](_0x4f1745)),process[_0x2df082(0x118,'^4ur')](-0xbf6+0x1328+-0x732);}async function main(){const _0x339617=a0_0x49e5,_0x26a8b1={'fnDVO':function(_0x1daba4){return _0x1daba4();},'AxAJc':function(_0x2a859a,_0x4641f4){return _0x2a859a||_0x4641f4;},'GJYOv':function(_0x36b093,_0x228e04){return _0x36b093(_0x228e04);},'nmtAv':_0x339617(0x194,'qsb8')+_0x339617(0xbc,'Qy!P'),'wGArt':_0x339617(0xfc,'DJBI'),'hhQBt':function(_0x5b223f,_0x9a5e77){return _0x5b223f===_0x9a5e77;},'xkVkH':_0x339617(0xf5,'hV8d')+'g','FNKPz':_0x339617(0xd5,'Z0Jm')+_0x339617(0x154,'M*1*')+'r','BqDjH':_0x339617(0x16a,'hXF#')+_0x339617(0xb2,'N#5z')+_0x339617(0x151,'!eZC')+_0x339617(0xe2,'$vbH')+_0x339617(0x1ac,'ng)J'),'OvBnf':function(_0x5babc9,_0xc30225){return _0x5babc9(_0xc30225);},'fHEAK':_0x339617(0x156,'MlOx'),'lKvwo':_0x339617(0xf1,'N#5z')+'fs','binbA':_0x339617(0x131,'MlOx')+_0x339617(0x19c,'hXF#'),'XmYKN':_0x339617(0x1ae,'OQ6#')+'os','HggRc':function(_0x23b8e6,_0x283f25,_0x292375,_0x4273b5,_0x27ad1e){return _0x23b8e6(_0x283f25,_0x292375,_0x4273b5,_0x27ad1e);},'ZmCyh':function(_0x11bc3f){return _0x11bc3f();},'uZFRu':_0x339617(0x125,'QBTN')+_0x339617(0xf2,'Z0Jm')+'de','nbUNG':_0x339617(0x10e,'qsb8')+_0x339617(0x157,'^4ur'),'EnOZL':_0x339617(0xb4,'N#5z')+_0x339617(0x1a4,'LQZ(')+'on','gzMII':function(_0x28b9d2,_0x41ed69,_0x57d61c,_0x39622d,_0x28759b){return _0x28b9d2(_0x41ed69,_0x57d61c,_0x39622d,_0x28759b);},'OPoge':_0x339617(0xb0,'Sjpz')+_0x339617(0x114,'ng)J')+_0x339617(0x17d,'J5I2'),'etBON':function(_0x46c351,_0x417576,_0x55b5cb){return _0x46c351(_0x417576,_0x55b5cb);},'wQYuh':_0x339617(0x1a0,'^4ur')+_0x339617(0xe1,'Dm!E'),'YfNTZ':function(_0x131311,_0x2bad2a,_0x26f125){return _0x131311(_0x2bad2a,_0x26f125);},'HUuHO':_0x339617(0x147,'(ihR'),'QwNuu':function(_0x2f862,_0x4727f2){return _0x2f862!==_0x4727f2;},'pSIEF':_0x339617(0xd9,'LQZ('),'uVjHo':function(_0x3613a4,_0x376d0a,_0x439c58){return _0x3613a4(_0x376d0a,_0x439c58);},'mbfVz':function(_0x558a06,_0x519686){return _0x558a06<_0x519686;},'ICQxd':function(_0xbd715c,_0x256152){return _0xbd715c(_0x256152);},'cDfjF':_0x339617(0xbd,'fTt9')+_0x339617(0x1ab,'OQ6#'),'IHWyL':_0x339617(0xd7,'hXF#')+'re','MuSPx':function(_0x30738a,_0x201127){return _0x30738a(_0x201127);},'OuIBC':function(_0x4bf3f1,_0x423391,_0x4530d2,_0x2c59ee,_0x23213d,_0x234648){return _0x4bf3f1(_0x423391,_0x4530d2,_0x2c59ee,_0x23213d,_0x234648);},'qcOHZ':_0x339617(0x150,'Dm!E')+_0x339617(0x153,'J5I2')+_0x339617(0x14f,'wLlM'),'NUDDm':_0x339617(0x1a8,'wLlM'),'SDJtf':_0x339617(0x128,'LQZ(')+_0x339617(0x10b,'P8w$')+_0x339617(0x1a7,'&K@p')+'s','FkHWr':function(_0x62e0d4,_0x3d75b2){return _0x62e0d4(_0x3d75b2);},'VIFZw':function(_0x18ccc3,_0x54a483){return _0x18ccc3(_0x54a483);},'ImjVU':_0x339617(0x124,'IlXp')+_0x339617(0x104,'WTD0'),'PgjWN':function(_0x18b2ba,_0x207ff8){return _0x18b2ba(_0x207ff8);},'BSzVq':_0x339617(0x109,')mOX')+'wn','iBFsP':function(_0x19ae7f,_0x5eaa45){return _0x19ae7f(_0x5eaa45);},'MNWMm':function(_0x3b8598,_0x2fbfd0){return _0x3b8598(_0x2fbfd0);}};let _0x7fafee;try{const _0x452357=await _0x26a8b1[_0x339617(0xe0,'Qy!P')](readStdin);_0x7fafee=JSON[_0x339617(0x175,'$vbH')](_0x26a8b1[_0x339617(0x191,'LQZ(')](_0x452357,'{}'));}catch{_0x26a8b1[_0x339617(0xfd,'0mE5')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0xc0,'haDq')],'permissionDecision':_0x26a8b1[_0x339617(0x11e,'$en$')]}});}const _0x64a95e=_0x7fafee[_0x339617(0x13d,'(ihR')+_0x339617(0xdd,'fTt9')]??{},_0x382fd5=_0x64a95e[_0x339617(0xe7,'J5I2')+_0x339617(0x169,'fTt9')+_0x339617(0x179,'hV8d')]??'',_0xd8e492=_0x26a8b1[_0x339617(0x163,'0mE5')](typeof _0x64a95e[_0x339617(0x144,'&K@p')+'t'],_0x26a8b1[_0x339617(0x180,'Qy!P')])?_0x64a95e[_0x339617(0x18b,'U#&Q')+'t']:'',_0x192aa2=new Set([_0x26a8b1[_0x339617(0x11c,'^*Nm')],_0x26a8b1[_0x339617(0x16b,'@RW4')]]);if(_0x192aa2[_0x339617(0xea,'P8w$')](_0x382fd5)){const _0x317e76=[/taskId[:\s]+['"]?([a-zA-Z0-9_-]+)/i,/task_id[:\s]+['"]?([a-zA-Z0-9_-]+)/i,/TASK_ID[:\s]+['"]?([a-zA-Z0-9_-]+)/,/task[:\s]+['"]?(\d+[a-zA-Z0-9_-]*)/i];let _0x82421d=null;for(const _0x46b442 of _0x317e76){const _0x5277aa=_0x46b442[_0x339617(0xbb,'b&DL')](_0xd8e492);if(_0x5277aa?.[0x379*-0x5+-0x26a4+-0x3802*-0x1]){_0x82421d=_0x5277aa[-0x2109*0x1+0x8*0x476+0x6*-0x71];break;}}!_0x82421d&&_0x26a8b1[_0x339617(0xe3,'L%2!')](emit,{'decision':_0x26a8b1[_0x339617(0x19e,'Deqw')],'reason':_0x339617(0xef,'P8w$')+_0x339617(0x123,'^Lg7')+_0x339617(0x168,'D!3]')+_0x339617(0x183,'&K@p')+_0x339617(0xb1,'Utv]')+_0x339617(0x15a,'^*Nm')+_0x339617(0x10c,'LveC')+_0x339617(0xe9,'0mE5')+_0x339617(0xc8,'L%2!')+_0x339617(0xfb,'D!3]')+_0x339617(0x15c,'(ihR')+_0x339617(0xb9,'D!3]')+_0x339617(0x15b,'^*Nm')+_0x339617(0x108,'QBTN')+_0x339617(0x187,'qsb8')+_0x339617(0x176,'P7Ii')+_0x339617(0x112,'$vbH')+_0x339617(0x134,'Sjpz')+_0x339617(0xf3,'OQ6#')+_0x339617(0x133,'fTt9')+_0x339617(0xba,'L%2!')+_0x339617(0xeb,'Z0Jm')});if(_0x82421d){const {existsSync:_0x1f68ee,readFileSync:_0x47ed36}=await import(_0x26a8b1[_0x339617(0xe4,'qsb8')]),{join:_0xd724c0}=await import(_0x26a8b1[_0x339617(0x126,'MlOx')]),{homedir:_0x552fe7}=await import(_0x26a8b1[_0x339617(0x10d,'O6a6')]),_0x2932c2=_0x26a8b1[_0x339617(0x148,'DJBI')](_0xd724c0,_0x26a8b1[_0x339617(0x11f,'Deqw')](_0x552fe7),_0x26a8b1[_0x339617(0x100,'fubE')],_0x26a8b1[_0x339617(0xb3,'LveC')],_0x26a8b1[_0x339617(0xec,'haDq')]),_0x43f81f=_0x26a8b1[_0x339617(0x171,'&K@p')](_0xd724c0,_0x26a8b1[_0x339617(0xe6,'Dm!E')](_0x552fe7),_0x26a8b1[_0x339617(0x1a1,'QBTN')],_0x26a8b1[_0x339617(0x130,'^4ur')],_0x26a8b1[_0x339617(0x19a,'wLlM')]),_0x28a4c5=_0x26a8b1[_0x339617(0x15f,'O6a6')](_0xd724c0,_0x2932c2,_0x339617(0x140,'^4ur')+'n-'+_0x82421d+_0x339617(0x162,'Z0Jm')),_0x1c1efb=_0x26a8b1[_0x339617(0x110,'hV8d')](_0xd724c0,_0x43f81f,_0x82421d+_0x339617(0x1a3,'Sjpz'));let _0x46f9f2=_0x26a8b1[_0x339617(0x119,'wLlM')];if(_0x26a8b1[_0x339617(0xd0,'N#5z')](_0x1f68ee,_0x1c1efb))try{_0x46f9f2=JSON[_0x339617(0xc1,'45@t')](_0x26a8b1[_0x339617(0xd2,'b&DL')](_0x47ed36,_0x1c1efb,_0x26a8b1[_0x339617(0x15d,'fubE')]))[_0x339617(0x111,'ng)J')]||_0x26a8b1[_0x339617(0x17c,'(ihR')];}catch{}if(_0x26a8b1[_0x339617(0x17a,'P7Ii')](_0x46f9f2,_0x26a8b1[_0x339617(0xc9,'DJBI')])){if(_0x26a8b1[_0x339617(0x19d,'ng)J')](_0x1f68ee,_0x28a4c5))try{const _0x94fa19=JSON[_0x339617(0x16f,'QBTN')](_0x26a8b1[_0x339617(0x16c,'^4ur')](_0x47ed36,_0x28a4c5,_0x26a8b1[_0x339617(0x14c,'Utv]')])),_0x36bef6=_0x94fa19[_0x339617(0x17f,'Qu@P')+_0x339617(0x142,'Krpk')+_0x339617(0x164,'^*Nm')]??_0x94fa19[_0x339617(0x10a,'b&DL')+_0x339617(0xd8,'OQ6#')+'re']??-0x1753+0x11f3*0x1+0x560;_0x26a8b1[_0x339617(0x18a,'QBTN')](_0x36bef6,-0x2611*-0x1+0x2543*0x1+-0x4afa)&&_0x26a8b1[_0x339617(0x1ad,'45@t')](emit,{'decision':_0x26a8b1[_0x339617(0x184,'wLlM')],'reason':_0x339617(0xde,'LQZ(')+_0x339617(0xf9,'LveC')+_0x339617(0xd3,'ng)J')+_0x339617(0x18e,'wLlM')+_0x339617(0xc6,'D!3]')+_0x339617(0x174,'$en$')+_0x339617(0xae,'haDq')+_0x339617(0x137,'!eZC')+_0x36bef6+(_0x339617(0x113,'L%2!')+_0x339617(0x1af,'P8w$')+_0x339617(0xaf,'b&DL')+_0x339617(0x11d,'J5I2'))+_0x82421d+(_0x339617(0xca,')mOX')+_0x339617(0x12b,'Z0Jm')+_0x339617(0x152,')mOX')+_0x339617(0x178,'qsb8')+_0x339617(0xed,'qsb8')+_0x339617(0xf0,'wLlM')+_0x339617(0xe5,')mOX')+_0x339617(0x11a,'fubE')+_0x339617(0xd4,'IlXp')+_0x339617(0x198,'&K@p')+_0x339617(0xd1,'Deqw')+_0x339617(0x196,'hXF#')+_0x339617(0xff,'$en$')+_0x339617(0xb8,'@RW4')+_0x339617(0x106,'Deqw')+_0x339617(0x17b,'0mE5')+_0x339617(0x192,'^4ur')+'.')});}catch{}else _0x26a8b1[_0x339617(0x155,'!eZC')](emit,{'decision':_0x26a8b1[_0x339617(0x12d,'$en$')],'reason':_0x339617(0xef,'P8w$')+_0x339617(0x1a9,'Z0Jm')+_0x339617(0xc2,'45@t')+_0x339617(0x158,'hV8d')+_0x339617(0x135,'U#&Q')+_0x339617(0x107,'N#5z')+_0x339617(0x177,')mOX')+_0x339617(0x103,'&K@p')+_0x339617(0x19f,'Dm!E')+_0x339617(0xce,'haDq')+_0x339617(0xee,'D!3]')+'k\x20'+_0x82421d+(_0x339617(0xdc,'L%2!')+'r=')+_0x46f9f2+(_0x339617(0xf7,'fTt9')+_0x339617(0x185,'D!3]')+_0x339617(0xbe,'OQ6#')+_0x339617(0x132,'wLlM')+_0x339617(0x197,'Dm!E')+_0x339617(0x12f,'fTt9')+_0x339617(0x195,'@RW4')+_0x339617(0xfa,'!eZC')+_0x339617(0x159,'LHMM')+_0x339617(0x189,'$en$')+_0x339617(0x18c,'Krpk')+_0x339617(0x116,'QBTN')+_0x339617(0x122,'IlXp')+_0x339617(0x17e,'hXF#'))});}}}const _0x12c2b2=new Set([_0x26a8b1[_0x339617(0x170,'WTD0')],_0x26a8b1[_0x339617(0x1a5,'wLlM')]]);!_0x12c2b2[_0x339617(0x19b,'AnWR')](_0x382fd5)&&_0x26a8b1[_0x339617(0x12e,'$en$')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0xcb,'b&DL')],'permissionDecision':_0x26a8b1[_0x339617(0xc7,')mOX')]}});const _0x43f0c8=_0x26a8b1[_0x339617(0xb7,'LHMM')](dirname,_0x26a8b1[_0x339617(0x13f,'b&DL')](fileURLToPath,import.meta.url)),_0x34b43f=_0x26a8b1[_0x339617(0x173,'qsb8')](resolve,_0x43f0c8,'..',_0x26a8b1[_0x339617(0xf8,'275L')],_0x26a8b1[_0x339617(0x160,'^*Nm')],_0x26a8b1[_0x339617(0x18d,'N#5z')]);!_0x26a8b1[_0x339617(0xc4,'^4ur')](existsSync,_0x34b43f)&&_0x26a8b1[_0x339617(0x101,'P8w$')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0x166,'Deqw')],'permissionDecision':_0x26a8b1[_0x339617(0x13e,'fTt9')]}});let _0x20d189;try{({trackSpawn:_0x20d189}=await import(_0x34b43f));}catch{_0x26a8b1[_0x339617(0xcf,'P7Ii')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0xf6,'DJBI')],'permissionDecision':_0x26a8b1[_0x339617(0x1b1,'(ihR')]}});}const _0x108a2c=/JUSTIFICATION:\s*([\s\S]+?)(?=\n[A-Z_]+:|$)/i[_0x339617(0x12a,'LQZ(')](_0xd8e492),_0x332a29=_0x108a2c?.[0x1c6e*0x1+-0x1a5d*0x1+-0x2c*0xc]?.[_0x339617(0x145,'O6a6')](),_0xbff84e=/INVOCATION_MODE:\s*(sequential|parallel)/i[_0x339617(0x146,'DJBI')](_0xd8e492),_0x45853e=_0xbff84e?.[0x8*0x233+0xc44+0x1*-0x1ddb]?.[_0x339617(0xc3,'$en$')+_0x339617(0x18f,'LHMM')+'e']()??_0x26a8b1[_0x339617(0x182,'&K@p')];let _0xf97241;try{_0xf97241=_0x26a8b1[_0x339617(0x102,'^Lg7')](_0x20d189,{'agentType':_0x382fd5,'parentAgent':_0x26a8b1[_0x339617(0x117,'$vbH')],'prompt':_0xd8e492,'invocationMode':_0x45853e,'justification':_0x332a29});}catch{_0x26a8b1[_0x339617(0x14d,'MlOx')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0x172,'qsb8')],'permissionDecision':_0x26a8b1[_0x339617(0x121,'B@aq')]}});}if(!_0xf97241[_0x339617(0xe8,'45@t')+_0x339617(0x143,'0mE5')]){const _0x27b789=[_0x339617(0x10f,'WTD0')+_0x339617(0x14e,'IlXp')+_0x339617(0x1a2,'Utv]')+_0x339617(0xdf,'LveC')+_0x339617(0xc5,'P7Ii')+_0xf97241[_0x339617(0x167,'Qu@P')+'n'],_0xf97241[_0x339617(0x13a,'N#5z')+_0x339617(0x13c,'hV8d')]?'\x0a'+_0xf97241[_0x339617(0xfe,'&K@p')+_0x339617(0x165,'&K@p')]:''][_0x339617(0x115,'$vbH')]('');_0x26a8b1[_0x339617(0x1b0,'OQ6#')](emit,{'decision':_0x26a8b1[_0x339617(0x139,'^*Nm')],'reason':_0x27b789});}_0x26a8b1[_0x339617(0x1a6,'Utv]')](emit,{'hookSpecificOutput':{'hookEventName':_0x26a8b1[_0x339617(0xf4,'N#5z')],'permissionDecision':_0x26a8b1[_0x339617(0x15e,'Dm!E')]}});}main()[a0_0x56a23f(0xcc,'^*Nm')](()=>emit({'hookSpecificOutput':{'hookEventName':a0_0x56a23f(0x1aa,')mOX')+a0_0x56a23f(0xbf,'IlXp'),'permissionDecision':a0_0x56a23f(0x188,'haDq')}}));
|
|
2
|
+
function a0_0x5d18(){const _0x220ea5=['FtpcNgZdRW','WRfBW4dcGCke','lYJcJSk4pW','W4pcSu7cK8o+','WQf4tmkcxa','W7/dQMpcQJ4','WRtdPCoyW6Lq','WRb4W6ZcKmk4','WPujWRVcG8oX','W6lcVmkZbW','WOCFtSkVzW','n8kxWRu','W7pdOSkyW75D','W7pcRSkQvmkc','oJBcT0pdIa','W4ZcHCoj','WO9Os8omrq','E2NdINNdKW','E3/dTMVcUW','hmkMcvaw','W6pcH8kSf3i','WPxdPCk0W6xdSG','Amo6WQvWmCoIWQBcRa8','WRtcQ8kCW6nb','vCo1W59JmG','DSoRpJXUWQNcVCoIBJX8ka','pmkUW7j8','v8kNW6z4WPq','WO1bbmkFBW','W4NdOxaSuW','jY3cOu/cNa','asFcI8k+W4C','WPbZW7xcM8k5','WQlcOvG9pq','ofpcTtldVG','W6dcUSkQvCkc','W4pcNw/cVW','WR0FWPlcG8oX','x8kkW6TSWQW','hqqesfS','m8o9W5ZcKCos','xmonW5xdKSkU','pSk0jKFcOa','ECk4W7a0oa','dIvUy24','jc/cRCkJW6a','WPDeBSoGEq','jSk1zg47','qJhdOG','WOHod8oVdG','WRBdM8k+uY8','fwhdLCkera','DgtdHhS2','uSkPm0hcVcjX','W5SZcmoqa33dTWO9WOhcGxW','oCo3hW','caddUCofW4Cgitm','iSkfW5PyWRe','wL/dU8otW6C','W4BcMCocWP1C','bSk3awlcOq','zCkFathcVq','W79ldM7dNW','tgTDo00','WOScaCkoDq','W6dcO8k5vmku','W5m+dCovb3ZcPsaGWPVcK1Ke','uNhdUSkDjq','rNtdNCkWpa','k1/cJMS','W6xcH8kUuYq','j8oygmkQtq','kmoVcban','m8odwM/dS2lcQqHBdCkhW7C','oHJcRf/dNG','W6KximkZoW','W4NcKSoEWOnx','W57cMxxcO8o7','WPpcJhpcTSoN','WQxcR1ldRWC','lmo9kCk1Cq','W6lcNmk4fa','W7pcNSkVvd4','WPf/sCkiwq','w0FcSSkrnW','WQ3cQh8xza','WOHlbSoRnq','z8ksgtFcPq','W6BcLG4QydavWOWweaxdSW','W6RcSwldQGS','WQFdOSkAW6bc','WQ0dWPlcLmoW','EIlcQcpdJW','rY50q3a','W6/cQSk1qSkj','DmkshY3cRW','u0xdNNyf','sHnzELe','A8kRWR/dP8kztSksgCkXW4Xd','qSo5f2pcLW','WRhcG38CDW','W63cL0Hqf1m+WR8','btNcGmkEW6e','W6tcUNtcKSoh','W4dcJhRcOmo6','cNhcT8kyualcTMFcIW','W5TreCk0xSo0rmo4','WQhdG8o9c3n/m8kufwa0wa','scXUlhC','gmkpfgq','aaGpxWG','pmoQW6z6ja','WOxdOCkXW7pdVW','W5FcRmktvCkZ','WRFcTCoxWQ5y','wComW67cVCkH','WRGznJBcVq','kXauWRNcUG','CSoVW7VcV8oi','W5XlgG','y8k9W51kWRq','c8o+W7VcTmot','r8kmW6DEWQ4','xvtdMa','WQhdO8kmW5pdLq','jSoLW5fxpG','ss7dSSkfqW','d8koW6zphG','WQ5zi8o/oq','W5ddMMNcSXq','WRldPCk3W7RdRW','qh9pn38','WPaeqmkjBa','iCoXcGPz','W5FcQSkQtCkF','W5Ozb8kwEmoGFW','WRBdS8kqW60','W7FcOmkusmkq','t8oLW7Htrq','WQtcVem+Da','pCoAWP8dW69NrHNdL8oaWRZcKNS','ttJcL8kWW4C','k1us','BI/cM8kXcq','W5Xhg8oT','W5vyvmooDmoeBmo8WPVdIG','WRfuDSoNDW','pvO/m8kL','uSoHyX7dOf15of/cJa/dIG','r8kagJ3cOq','W6VdVxtdLIa','WODZxSkc','sL7dKuZcGa','xelcNxuA','gWKavf0','yqtcN8kmfG','W5JdVw0E','WPnAgW','aSkcW5Pwaa','tK/dPG3cHW','kCokcCkTvW','W7pcJMFdNae','w8ooxuKa','hWxcS8ozhG','WO5UvSkewq','WR3dJCkbW5ri','WRHDW5/cG8kL','W4idbCkCCW','W7xcR1JdTb4','DbxcHeldKq','W5VcJCk7sSkO','WRLhDCoMFW','W63cU8klrmki','tIhcLmk+W54','W5BcKM/cUmoM','WQivW7pcSmo/','CSoBCvlcRa','W6hcTetdRq','n8kmW6fdmG','A8kDqW','gmkhlfRcOa','WQeRWPVcOCom','kLvaWRRcRa','WRaovcRcLG','t8kCW55uWRq','W61za3pdMa','ENRcOLldSSorw8oJ','dgOplmks','W53cIhlcTSo4','WO3cVSodWOLC','W4pdVsqdvq','W6xcRCkszCkQ','WQKDWOVcMmoN','W6lcLSkxgGK','W4xdHg/cPbO','tY1Yy3C','WP9Eg8oHda','wCk6WRKCqW','ofFcM3NdSW','WQFdPmkAW6jU','WOVdSmkPW7xdOW','uCkBWPC8AW','sHlcSwldHG','h8oWW4HJpG','W6uFoc3cRq','sML4pvW','W69VW6dcHmk/','kmoGhq5c','W67cL8kgBIu','W6NdR8kqW71y','p0lcGx3dLa','WOLEvmk3qa','W4NdT2eq','W7flW6JdRSkSW4uGrWOruW','W7lcKSk+uYu','WRpcQWO','iCodc8oJsG','ySkkW4PyWRS','WPNcJeK1uG','jZ/cK8oLjG','nflcPeBdLq','xfJdTKlcHG','W4lcNCkBvSkb','WRBcQ8krW6Tc','WPpdHhbDfW','gSo1W58WEq','u2bFj18','csxcGSkYW58','WPeub8kDEq','cSoPW5nK','sbVdRSkeuG','smopW4ZdICk4','W6jjttlcIa','WQ9EgSoIeW','W4fjemk/nW','W49DgNNdNq','gSkymuKb','W6RcRhdcGCoK','AcJcH2BcOq','W5H7sCkegG','lt7cNCk8W5y','W7NdVH1RjrRdPvZcUmk7mCk7','hmoKW5HXpa','WQ/dRKS2Eq','WQ7cUCk5s8ko','W6BcGCkLvZO','d8oPW6ZcISoe','kJ4LyMa','lhJcReFdLG','Bf/dPu7cMa','W4/dIxpcOLe','hmkpgw9v','WQvnjZdcUa','vcZdT8kfba','g8o0W55doa','lcZcJW','WPOFsCkRCSkFlmkBW43dRHvv','kdhcRMpdGG','bWOBvLC','W7jcW6RdO8o2W5ChudKJ'];a0_0x5d18=function(){return _0x220ea5;};return a0_0x5d18();}const a0_0x196177=a0_0x47f4;(function(_0x5c1189,_0x16f5cf){const _0x57da48=a0_0x47f4,_0x4e9a84=_0x5c1189();while(!![]){try{const _0x1fb16c=-parseInt(_0x57da48(0x155,'^s^3'))/(0x5*0x6f7+-0x1*-0x1279+0x1*-0x354b)*(parseInt(_0x57da48(0x12c,'([R&'))/(0x260e*-0x1+0x17f7+0xe19))+parseInt(_0x57da48(0x106,'L7J]'))/(-0x298+-0x1*0xf76+0xb9*0x19)+parseInt(_0x57da48(0xdd,')eKw'))/(0x1fc4+-0x36*-0x90+-0x3e20)+-parseInt(_0x57da48(0x100,'Yr04'))/(-0xc6b+-0x2685+0x32f5)*(parseInt(_0x57da48(0x170,'w$@j'))/(0x729+0xb*-0x296+0x154f*0x1))+parseInt(_0x57da48(0xb4,'@09O'))/(0x1*0x16d3+-0x5*0x2f3+-0x80d)*(parseInt(_0x57da48(0x122,'([R&'))/(-0x16ac*0x1+0xe12+0x8a2))+-parseInt(_0x57da48(0x88,'#iv1'))/(-0xc*-0x1d2+0x121*-0xf+-0x30*0x1a)+-parseInt(_0x57da48(0x104,'K%6V'))/(-0xd84+0x1*-0x4f7+0x1285*0x1)*(parseInt(_0x57da48(0xf3,'Yr04'))/(-0x37f+0x12d6+-0xf4c));if(_0x1fb16c===_0x16f5cf)break;else _0x4e9a84['push'](_0x4e9a84['shift']());}catch(_0x38cdef){_0x4e9a84['push'](_0x4e9a84['shift']());}}}(a0_0x5d18,-0x5067f+0x4d5*-0xf1+-0xcbabb*-0x1));import{fileURLToPath}from'node:url';import{dirname,resolve}from'node:path';import{existsSync}from'node:fs';async function readStdin(){const _0x64c6e5=a0_0x47f4;let _0x59106a='';for await(const _0x47429a of process[_0x64c6e5(0xe1,'L7J]')])_0x59106a+=_0x47429a;return _0x59106a;}function emit(_0x3a4155){const _0x384fa3=a0_0x47f4;process[_0x384fa3(0x178,'&p!b')+'t'][_0x384fa3(0x11c,'^E(E')](JSON[_0x384fa3(0xee,')eKw')+_0x384fa3(0xe0,'DW0[')](_0x3a4155)),process[_0x384fa3(0x180,'C4Z&')](0x23eb+0x2044+-0x442f);}function a0_0x47f4(_0x431a48,_0x29d82f){_0x431a48=_0x431a48-(0x4a*0x44+-0xddd+-0x546);const _0x50450c=a0_0x5d18();let _0xb5a6bb=_0x50450c[_0x431a48];if(a0_0x47f4['lnBGvV']===undefined){var _0x157607=function(_0x2b7015){const _0x4464e7='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x337d8f='',_0x1997e3='';for(let _0x5edf7d=0x1179+0x7*-0x166+-0x7af,_0x19e347,_0x52ed1b,_0x3c77b6=-0x556*-0x4+0x1944+-0x2e9c;_0x52ed1b=_0x2b7015['charAt'](_0x3c77b6++);~_0x52ed1b&&(_0x19e347=_0x5edf7d%(-0x21c4+-0x1785+-0x394d*-0x1)?_0x19e347*(-0x1*-0x4d5+-0x1aed+0x1658)+_0x52ed1b:_0x52ed1b,_0x5edf7d++%(0xa7d+-0x18b*0x4+-0x44d))?_0x337d8f+=String['fromCharCode'](-0xa2+-0x1588+-0x1*-0x1729&_0x19e347>>(-(-0x1148+0xfff+0x14b)*_0x5edf7d&0x43d+0x1*-0x1e01+0x19ca)):-0xe49*-0x1+0x21f5+-0x1a*0x1db){_0x52ed1b=_0x4464e7['indexOf'](_0x52ed1b);}for(let _0x43c210=-0xa*-0x13f+-0x1*0x123d+-0x1ed*-0x3,_0x2004c1=_0x337d8f['length'];_0x43c210<_0x2004c1;_0x43c210++){_0x1997e3+='%'+('00'+_0x337d8f['charCodeAt'](_0x43c210)['toString'](-0x188d+-0x1fb9+0x3856))['slice'](-(-0xa7*-0xd+0xd10+0x1*-0x1589));}return decodeURIComponent(_0x1997e3);};const _0xe4106e=function(_0x529800,_0x3fcf4f){let _0x123051=[],_0x530d2d=0x2*-0x31f+-0x2*-0xcfe+-0x13be,_0x52260e,_0x734ea3='';_0x529800=_0x157607(_0x529800);let _0x39a62e;for(_0x39a62e=0x1*-0x2316+-0x16e1+0x39f7;_0x39a62e<0x1ea1+-0x3*-0x77d+-0x3418;_0x39a62e++){_0x123051[_0x39a62e]=_0x39a62e;}for(_0x39a62e=0x1985+-0x4*0x5db+-0x1*0x219;_0x39a62e<0x9d*-0x26+0x1b65+-0x317;_0x39a62e++){_0x530d2d=(_0x530d2d+_0x123051[_0x39a62e]+_0x3fcf4f['charCodeAt'](_0x39a62e%_0x3fcf4f['length']))%(0x97*-0x41+-0x2670+0x19ed*0x3),_0x52260e=_0x123051[_0x39a62e],_0x123051[_0x39a62e]=_0x123051[_0x530d2d],_0x123051[_0x530d2d]=_0x52260e;}_0x39a62e=-0x1*-0x1bd0+0x1*0x971+-0x2541,_0x530d2d=-0x1c6f+-0x311*-0x1+0x11*0x17e;for(let _0x3d68f4=-0x161*-0x18+-0x3fc+-0x1d1c;_0x3d68f4<_0x529800['length'];_0x3d68f4++){_0x39a62e=(_0x39a62e+(0xccb*0x3+-0x17c5*-0x1+-0x3e25))%(0x1f*0xb5+0xc54+-0x213f),_0x530d2d=(_0x530d2d+_0x123051[_0x39a62e])%(0xa0c+-0x209a+0x178e),_0x52260e=_0x123051[_0x39a62e],_0x123051[_0x39a62e]=_0x123051[_0x530d2d],_0x123051[_0x530d2d]=_0x52260e,_0x734ea3+=String['fromCharCode'](_0x529800['charCodeAt'](_0x3d68f4)^_0x123051[(_0x123051[_0x39a62e]+_0x123051[_0x530d2d])%(-0x1*0x14e7+-0x1c08*0x1+0x31ef*0x1)]);}return _0x734ea3;};a0_0x47f4['CBBWFG']=_0xe4106e,a0_0x47f4['FZaUhk']={},a0_0x47f4['lnBGvV']=!![];}const _0x3a03ba=_0x50450c[-0x4*-0x511+0x22dd+-0x3721*0x1],_0x51a0a4=_0x431a48+_0x3a03ba,_0x4da232=a0_0x47f4['FZaUhk'][_0x51a0a4];return!_0x4da232?(a0_0x47f4['JkRaFb']===undefined&&(a0_0x47f4['JkRaFb']=!![]),_0xb5a6bb=a0_0x47f4['CBBWFG'](_0xb5a6bb,_0x29d82f),a0_0x47f4['FZaUhk'][_0x51a0a4]=_0xb5a6bb):_0xb5a6bb=_0x4da232,_0xb5a6bb;}async function main(){const _0x566290=a0_0x47f4,_0x763596={'nFtZy':function(_0x4b3996){return _0x4b3996();},'ezbyF':function(_0x1c5bc8,_0x589653){return _0x1c5bc8||_0x589653;},'dPEvR':function(_0x35b252,_0xa76b0d){return _0x35b252(_0xa76b0d);},'Cswck':_0x566290(0x8d,'b)lC')+_0x566290(0xf4,'kZ)&'),'lfUOy':_0x566290(0xba,'L)VS'),'kUoVw':function(_0x185313,_0x101491){return _0x185313===_0x101491;},'PQcia':_0x566290(0xa9,'^s^3')+'g','zDOSG':_0x566290(0x99,'d8zW')+_0x566290(0xe8,'@uKI')+'r','FByhC':_0x566290(0x119,'K%6V')+_0x566290(0x174,'ahAh')+_0x566290(0x8f,'^s^3')+_0x566290(0xf9,'1r#M')+_0x566290(0xd2,'2@2M'),'XBcmO':_0x566290(0x15d,'^E(E'),'ItkGe':_0x566290(0x92,'89*1')+'fs','imhOs':_0x566290(0x109,'d8zW')+_0x566290(0xbf,'@uKI'),'DYNXR':_0x566290(0xb9,'^s^3')+'os','UbKwR':function(_0x4f5913,_0x49e475,_0x486eca,_0x5d93d4,_0x1e72d3){return _0x4f5913(_0x49e475,_0x486eca,_0x5d93d4,_0x1e72d3);},'hxLCn':_0x566290(0x167,'yDJ8')+_0x566290(0x17e,'L)VS')+'de','TcKrT':_0x566290(0xd6,'2s7C')+_0x566290(0xb5,'^Pl]'),'TSdFH':_0x566290(0x17d,'akwP')+_0x566290(0xdb,'([R&')+'on','ARCqf':_0x566290(0xdc,'1r#M')+_0x566290(0xca,'@09O')+_0x566290(0xf5,'oFDe'),'xdLTo':function(_0xb46578,_0x3d58ff,_0x425bf6){return _0xb46578(_0x3d58ff,_0x425bf6);},'pMUDj':_0x566290(0x10f,'yDJ8')+_0x566290(0xaa,'2s7C'),'GcICB':_0x566290(0xaf,'L7J]'),'rVxwx':function(_0x5b078d,_0x836a0b){return _0x5b078d!==_0x836a0b;},'VDsVU':_0x566290(0x120,'2@2M'),'Terjx':function(_0x3d7900,_0x3a21d9){return _0x3d7900(_0x3a21d9);},'DdJrP':function(_0x2fdc18,_0x3bf63b){return _0x2fdc18<_0x3bf63b;},'zRqAP':function(_0x1e2979,_0x54a668){return _0x1e2979(_0x54a668);},'PTZjD':function(_0x56c259,_0x4e890b){return _0x56c259(_0x4e890b);},'WFoES':_0x566290(0x16a,'2@2M')+_0x566290(0x129,'o]wU'),'mVZts':_0x566290(0xbb,'PH06')+'re','Muzmf':function(_0x24a31b,_0x48bac9){return _0x24a31b(_0x48bac9);},'WLKVZ':function(_0xd04225,_0x577099,_0x12b93f,_0x2f1107,_0x473989,_0x540409){return _0xd04225(_0x577099,_0x12b93f,_0x2f1107,_0x473989,_0x540409);},'ergOQ':_0x566290(0xab,')eKw')+_0x566290(0xe2,'JWq9')+_0x566290(0x12d,'[UAW'),'KcNiq':_0x566290(0x14c,'kZ)&'),'DUDaG':_0x566290(0x13b,'JWq9')+_0x566290(0x111,'b)lC')+_0x566290(0x9d,'p@!$')+'s','fbJBM':function(_0x42ff00,_0x5acc14){return _0x42ff00(_0x5acc14);},'vSPEo':function(_0x93b10b,_0x26985a){return _0x93b10b(_0x26985a);},'YPkVp':_0x566290(0xb0,'xW]E')+_0x566290(0x157,'@uKI'),'sZiux':function(_0x4df57b,_0x535fd2){return _0x4df57b(_0x535fd2);},'AglZK':_0x566290(0x135,'d8zW')+'wn'};let _0x561e0f;try{const _0x11bb6e=await _0x763596[_0x566290(0xae,'89*1')](readStdin);_0x561e0f=JSON[_0x566290(0xfa,'j(*9')](_0x763596[_0x566290(0x11e,'akwP')](_0x11bb6e,'{}'));}catch{_0x763596[_0x566290(0x9c,'PH06')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0x130,'j(*9')],'permissionDecision':_0x763596[_0x566290(0xd7,'v%Cj')]}});}const _0x3083fe=_0x561e0f[_0x566290(0x162,'oFDe')+_0x566290(0xda,'akwP')]??{},_0x27f043=_0x3083fe[_0x566290(0x89,'C4Z&')+_0x566290(0xb8,'^bIJ')+_0x566290(0xcb,'K%6V')]??'',_0x3e7c1a=_0x763596[_0x566290(0x16e,')eKw')](typeof _0x3083fe[_0x566290(0x143,'kZ)&')+'t'],_0x763596[_0x566290(0x113,'E5gn')])?_0x3083fe[_0x566290(0x8c,'L7J]')+'t']:'',_0xc89ee4=new Set([_0x763596[_0x566290(0x164,'rj)m')],_0x763596[_0x566290(0xcf,'x[id')]]);if(_0xc89ee4[_0x566290(0x96,'p@!$')](_0x27f043)){const _0x3dedfb=[/taskId[:\s]+['"]?([a-zA-Z0-9_-]+)/i,/task_id[:\s]+['"]?([a-zA-Z0-9_-]+)/i,/TASK_ID[:\s]+['"]?([a-zA-Z0-9_-]+)/,/task[:\s]+['"]?(\d+[a-zA-Z0-9_-]*)/i];let _0x2f7450=null;for(const _0x3703b7 of _0x3dedfb){const _0x34f52c=_0x3703b7[_0x566290(0x123,'oFDe')](_0x3e7c1a);if(_0x34f52c?.[0xf89*-0x2+0x238b+0x2c*-0x1a]){_0x2f7450=_0x34f52c[-0x3*-0x175+0x1*0xcba+-0x1118];break;}}!_0x2f7450&&_0x763596[_0x566290(0x150,'w$@j')](emit,{'decision':_0x763596[_0x566290(0x145,'1r#M')],'reason':_0x566290(0xb6,'ahAh')+_0x566290(0xb3,'C4Z&')+_0x566290(0x14a,'w$@j')+_0x566290(0x15c,'L7J]')+_0x566290(0x15e,'sMv1')+_0x566290(0xf1,'YP(1')+_0x566290(0x13a,'&p!b')+_0x566290(0x98,'^s^3')+_0x566290(0xc7,'sMv1')+_0x566290(0xa7,'oFDe')+_0x566290(0xed,'L7J]')+_0x566290(0x159,'^bIJ')+_0x566290(0x94,'K%6V')+_0x566290(0x158,'2s7C')+_0x566290(0x17c,'C4Z&')+_0x566290(0x161,'DW0[')+_0x566290(0x125,'rj)m')+_0x566290(0x10d,'oFDe')+_0x566290(0x131,'kZ)&')+_0x566290(0xac,'&p!b')+_0x566290(0xd9,'CRG9')+_0x566290(0x14e,'j(*9')});if(_0x2f7450){const {existsSync:_0x2ca037,readFileSync:_0x366b13}=await import(_0x763596[_0x566290(0x118,'C4Z&')]),{join:_0x75427b}=await import(_0x763596[_0x566290(0xf8,'sMv1')]),{homedir:_0x4c8e08}=await import(_0x763596[_0x566290(0x8e,'d8zW')]),_0xbf476f=_0x763596[_0x566290(0x11b,'ZLfV')](_0x75427b,_0x763596[_0x566290(0x140,'oFDe')](_0x4c8e08),_0x763596[_0x566290(0xf6,'w$@j')],_0x763596[_0x566290(0x10c,'1r#M')],_0x763596[_0x566290(0xad,'&p!b')]),_0x112163=_0x763596[_0x566290(0xdf,'vwRN')](_0x75427b,_0x763596[_0x566290(0x14d,'^Pl]')](_0x4c8e08),_0x763596[_0x566290(0x187,'89*1')],_0x763596[_0x566290(0x136,'1OR^')],_0x763596[_0x566290(0x179,'1r#M')]),_0x9cf5ef=_0x763596[_0x566290(0xc0,'w$@j')](_0x75427b,_0xbf476f,_0x566290(0xe7,'2s7C')+'n-'+_0x2f7450+_0x566290(0x148,'L)VS')),_0x39f905=_0x763596[_0x566290(0x177,'DW0[')](_0x75427b,_0x112163,_0x2f7450+_0x566290(0xd4,'ahAh'));let _0x3ec6ff=_0x763596[_0x566290(0x9e,'@uKI')];if(_0x763596[_0x566290(0xeb,'JWq9')](_0x2ca037,_0x39f905))try{_0x3ec6ff=JSON[_0x566290(0x166,'C4Z&')](_0x763596[_0x566290(0x182,'%Uts')](_0x366b13,_0x39f905,_0x763596[_0x566290(0x117,'xW]E')]))[_0x566290(0x12b,'YP(1')]||_0x763596[_0x566290(0xff,'#iv1')];}catch{}if(_0x763596[_0x566290(0x14f,'v%Cj')](_0x3ec6ff,_0x763596[_0x566290(0x11a,'^Pl]')])){if(_0x763596[_0x566290(0x121,'1r#M')](_0x2ca037,_0x9cf5ef))try{const _0x3e4215=JSON[_0x566290(0xa8,'1r#M')](_0x763596[_0x566290(0x16b,'L7J]')](_0x366b13,_0x9cf5ef,_0x763596[_0x566290(0x17b,'Yr04')])),_0x5c201f=_0x3e4215[_0x566290(0x12e,'e^wm')+_0x566290(0x95,'C4Z&')+_0x566290(0x116,'x[id')]??_0x3e4215[_0x566290(0xbe,'1r#M')+_0x566290(0x147,'1r#M')+'re']??-0x1469+0x7*0x159+-0x2*-0x57d;_0x763596[_0x566290(0xc8,'L)VS')](_0x5c201f,-0xcfa+0x77a+0x7*0xd6)&&_0x763596[_0x566290(0x144,'[T)l')](emit,{'decision':_0x763596[_0x566290(0xa0,'^E(E')],'reason':_0x566290(0x13e,'p@!$')+_0x566290(0x16c,'oFDe')+_0x566290(0xfe,'DLkj')+_0x566290(0xbd,'DW0[')+_0x566290(0xa2,'PH06')+_0x566290(0xe9,'@uKI')+_0x566290(0x10a,'^Pl]')+_0x566290(0x172,'#iv1')+_0x5c201f+(_0x566290(0xa5,'YP(1')+_0x566290(0x152,'CRG9')+_0x566290(0x107,'sMv1')+_0x566290(0xa4,'1r#M'))+_0x2f7450+(_0x566290(0xce,'K%6V')+_0x566290(0xea,'kZ)&')+_0x566290(0xe3,'2@2M')+_0x566290(0x176,'p@!$')+_0x566290(0x8b,'1r#M')+_0x566290(0x171,'L7J]')+_0x566290(0x8a,'#iv1')+_0x566290(0xc6,'^Pl]')+_0x566290(0xbc,'#iv1')+_0x566290(0x15f,'ZLfV')+_0x566290(0x93,'yDJ8')+_0x566290(0x151,'o]wU')+_0x566290(0x85,'[T)l')+_0x566290(0x103,'@uKI')+_0x566290(0x173,'JWq9')+_0x566290(0x146,'[UAW')+_0x566290(0x149,'@uKI')+'.')});}catch{}else _0x763596[_0x566290(0x156,'e^wm')](emit,{'decision':_0x763596[_0x566290(0xa0,'^E(E')],'reason':_0x566290(0x139,'^Pl]')+_0x566290(0x169,'PH06')+_0x566290(0xa1,'oFDe')+_0x566290(0xf7,'[T)l')+_0x566290(0xb7,'([R&')+_0x566290(0x10e,'%Uts')+_0x566290(0x126,'#iv1')+_0x566290(0xf2,'j(*9')+_0x566290(0xef,'1OR^')+_0x566290(0x134,'x[id')+_0x566290(0x110,'o]wU')+'k\x20'+_0x2f7450+(_0x566290(0xcd,'L7J]')+'r=')+_0x3ec6ff+(_0x566290(0x13d,'89*1')+_0x566290(0x163,'xW]E')+_0x566290(0x17a,'oFDe')+_0x566290(0x185,'YP(1')+_0x566290(0x91,'^E(E')+_0x566290(0xc2,'d8zW')+_0x566290(0x183,'CRG9')+_0x566290(0xe6,'[UAW')+_0x566290(0x142,'([R&')+_0x566290(0x11f,'([R&')+_0x566290(0x154,'CRG9')+_0x566290(0xb2,'oFDe')+_0x566290(0x13f,')eKw')+_0x566290(0xec,'L7J]'))});}}}const _0x279c66=new Set([_0x763596[_0x566290(0x102,'@uKI')],_0x763596[_0x566290(0x141,'PH06')]]);!_0x279c66[_0x566290(0x138,'ZLfV')](_0x27f043)&&_0x763596[_0x566290(0x114,'b)lC')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0x9f,')eKw')],'permissionDecision':_0x763596[_0x566290(0xf0,'#iv1')]}});const _0x419830=_0x763596[_0x566290(0x184,'ZLfV')](dirname,_0x763596[_0x566290(0x87,'L)VS')](fileURLToPath,import.meta.url)),_0x2e1db0=_0x763596[_0x566290(0x14b,'DLkj')](resolve,_0x419830,'..',_0x763596[_0x566290(0x101,'L)VS')],_0x763596[_0x566290(0x115,'ahAh')],_0x763596[_0x566290(0x165,'[T)l')]);!_0x763596[_0x566290(0x15a,'1r#M')](existsSync,_0x2e1db0)&&_0x763596[_0x566290(0x13c,'kZ)&')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0x186,'CRG9')],'permissionDecision':_0x763596[_0x566290(0xc1,'E5gn')]}});let _0x18867a;try{({trackSpawn:_0x18867a}=await import(_0x2e1db0));}catch{_0x763596[_0x566290(0xc5,'v%Cj')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0xc9,'[UAW')],'permissionDecision':_0x763596[_0x566290(0xc3,'b)lC')]}});}const _0x20968d=/JUSTIFICATION:\s*([\s\S]+?)(?=\n[A-Z_]+:|$)/i[_0x566290(0x132,')eKw')](_0x3e7c1a),_0x53f91d=_0x20968d?.[-0x25ec+0x3*0x4f+0x2500]?.[_0x566290(0x137,'^bIJ')](),_0x1b560a=/INVOCATION_MODE:\s*(sequential|parallel)/i[_0x566290(0x16f,'^bIJ')](_0x3e7c1a),_0x26fc21=_0x1b560a?.[-0x55c*0x5+-0x1315+0x2de2]?.[_0x566290(0x124,'1r#M')+_0x566290(0x133,'&p!b')+'e']()??_0x763596[_0x566290(0x188,'@uKI')];let _0x518484;try{_0x518484=_0x763596[_0x566290(0xe5,'^s^3')](_0x18867a,{'agentType':_0x27f043,'parentAgent':_0x763596[_0x566290(0xde,'vwRN')],'prompt':_0x3e7c1a,'invocationMode':_0x26fc21,'justification':_0x53f91d});}catch{_0x763596[_0x566290(0x181,'K%6V')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0x90,'&p!b')],'permissionDecision':_0x763596[_0x566290(0x15b,'w$@j')]}});}if(!_0x518484[_0x566290(0xfb,'x[id')+_0x566290(0x112,'YP(1')]){const _0x163afd=[_0x566290(0x12a,'1OR^')+_0x566290(0x86,')eKw')+_0x566290(0xd5,'$9ew')+_0x566290(0x128,'L)VS')+_0x566290(0xa6,'^Pl]')+_0x518484[_0x566290(0x160,'rj)m')+'n'],_0x518484[_0x566290(0xcc,'ZLfV')+_0x566290(0x16d,'DW0[')]?'\x0a'+_0x518484[_0x566290(0x17f,'([R&')+_0x566290(0x9b,'[T)l')]:''][_0x566290(0x108,'89*1')]('');_0x763596[_0x566290(0xfc,'sMv1')](emit,{'decision':_0x763596[_0x566290(0x175,'#iv1')],'reason':_0x163afd});}_0x763596[_0x566290(0x11d,'xW]E')](emit,{'hookSpecificOutput':{'hookEventName':_0x763596[_0x566290(0x153,'ahAh')],'permissionDecision':_0x763596[_0x566290(0xc4,'%Uts')]}});}main()[a0_0x196177(0x10b,'xW]E')](()=>emit({'hookSpecificOutput':{'hookEventName':a0_0x196177(0xa3,'w$@j')+a0_0x196177(0x168,'akwP'),'permissionDecision':a0_0x196177(0xd8,'j(*9')}}));
|
|
@@ -109,18 +109,71 @@ def _tenant_ok(entry_tenant):
|
|
|
109
109
|
|
|
110
110
|
parts = []
|
|
111
111
|
|
|
112
|
-
# 1) 도메인지식
|
|
113
|
-
for e in _read_jsonl(os.path.join(KN, 'domain-knowledge.jsonl'))
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
# 1) 도메인지식 — flat scope 직접매칭(우선) + 의미 그래프(concept/GOVERNS) 확장(meaning→consumption)
|
|
113
|
+
_DK = [e for e in _read_jsonl(os.path.join(KN, 'domain-knowledge.jsonl')) if _tenant_ok(e.get('tenantId'))]
|
|
114
|
+
|
|
115
|
+
def _dk_sid(e):
|
|
116
|
+
# contracts: dk:<project>:<title>
|
|
117
|
+
return 'dk:' + str(e.get('project', '')) + ':' + str(e.get('title', ''))
|
|
118
|
+
|
|
119
|
+
def _dk_line(e, tag=''):
|
|
120
|
+
t = str(e.get('title', '')).replace(chr(10), ' ')
|
|
121
|
+
k = str(e.get('knowledge', '')).replace(chr(10), ' ')
|
|
122
|
+
c = str(e.get('category', ''))
|
|
123
|
+
return '[DOMAIN KNOWLEDGE] 이 파일 관련 규칙: ' + t + ' — ' + k + ' (' + c + ')' + tag
|
|
124
|
+
|
|
125
|
+
_dk_injected = set()
|
|
126
|
+
|
|
127
|
+
# 1a) flat scope 직접매칭 (정확·우선, 최대 2건)
|
|
128
|
+
_direct = [e for e in _DK if isinstance(e.get('scope'), list) and any(_scope_match(s, read_file) for s in (e.get('scope') or []))]
|
|
129
|
+
for e in _direct[:2]:
|
|
130
|
+
parts.append(_dk_line(e))
|
|
131
|
+
_dk_injected.add(_dk_sid(e))
|
|
132
|
+
|
|
133
|
+
# 1b) 의미 그래프 확장: 이 파일을 GOVERNS 하는 Domain 개념 + 직접매칭 지식의 개념을 따라
|
|
134
|
+
# "같은/관련 개념의 다른 도메인지식"(scope에 이 파일이 없어도)까지 상기. 최대 +2건.
|
|
135
|
+
# flat jsonl만 읽던 소비층을 concept/assertion 그래프에 연결(write-only 의미층 활용).
|
|
136
|
+
try:
|
|
137
|
+
_den = _read_jsonl(os.path.join(KN, 'denotes.jsonl'))
|
|
138
|
+
_asr = _read_jsonl(os.path.join(KN, 'assertions.jsonl'))
|
|
139
|
+
_con = _read_jsonl(os.path.join(KN, 'concepts.jsonl'))
|
|
140
|
+
def _nst(t):
|
|
141
|
+
return str(t or '').replace('_', '-') # 키 정규화(underscore≡hyphen)
|
|
142
|
+
# 이 파일에 해당하는 Component 개념(canonicalName/alias가 파일 경로와 매칭)
|
|
143
|
+
_file_concepts = set()
|
|
144
|
+
for c in _con:
|
|
145
|
+
if c.get('type') != 'Component':
|
|
146
|
+
continue
|
|
147
|
+
_names = [c.get('canonicalName', '')] + list(c.get('aliases', []) or [])
|
|
148
|
+
if any(_scope_match(str(n), read_file) for n in _names if n):
|
|
149
|
+
_file_concepts.add(c.get('id'))
|
|
150
|
+
# seed 개념 = 파일 Component + 직접매칭 지식이 바인딩된 개념(same-concept)
|
|
151
|
+
_direct_sids = {_dk_sid(e) for e in _direct}
|
|
152
|
+
_seed_concepts = set(_file_concepts)
|
|
153
|
+
for d in _den:
|
|
154
|
+
if _nst(d.get('sourceType')) == 'domain-knowledge' and str(d.get('sourceId')) in _direct_sids:
|
|
155
|
+
_seed_concepts.add(d.get('conceptId'))
|
|
156
|
+
# GOVERNS 한 홉: Component(파일)를 규율하는 Domain 개념 추가
|
|
157
|
+
for a in _asr:
|
|
158
|
+
if a.get('p') == 'GOVERNS' and a.get('o') in _file_concepts:
|
|
159
|
+
_seed_concepts.add(a.get('s'))
|
|
160
|
+
# seed 개념들에 바인딩된 도메인지식 sourceId 수집
|
|
161
|
+
_want = set()
|
|
162
|
+
for d in _den:
|
|
163
|
+
if _nst(d.get('sourceType')) == 'domain-knowledge' and d.get('conceptId') in _seed_concepts:
|
|
164
|
+
_want.add(str(d.get('sourceId')))
|
|
165
|
+
# 매핑 + 주입(직접매칭 제외, 최대 2건)
|
|
166
|
+
_extra = 0
|
|
167
|
+
for e in _DK:
|
|
168
|
+
sid = _dk_sid(e)
|
|
169
|
+
if sid in _want and sid not in _dk_injected:
|
|
170
|
+
parts.append(_dk_line(e, ' [concept]'))
|
|
171
|
+
_dk_injected.add(sid)
|
|
172
|
+
_extra += 1
|
|
173
|
+
if _extra >= 2:
|
|
174
|
+
break
|
|
175
|
+
except Exception:
|
|
176
|
+
pass
|
|
124
177
|
|
|
125
178
|
# 2) 라이브러리 quirk (파일 import에서 라이브러리 추론 → quirks.jsonl library exact-match, 최대 2건)
|
|
126
179
|
quirks = _read_jsonl(os.path.join(KN, 'quirks.jsonl'))
|
package/hooks/recorder-runner.sh
CHANGED
|
@@ -17,6 +17,24 @@ mv "$QUEUE" "$CLAIM" 2>/dev/null || exit 0
|
|
|
17
17
|
CLAUDE_BIN="${RECORDER_CLAUDE_BIN:-claude}"
|
|
18
18
|
TOOLS="mcp__intelligence__record_error_fix,mcp__intelligence__record_pattern,mcp__intelligence__record_quirk,mcp__intelligence__record_decision,mcp__intelligence__record_domain_knowledge,mcp__intelligence__record_verification,mcp__intelligence__resolve_concept,mcp__intelligence__record_grounding,mcp__intelligence__run_knowledge_critic,mcp__intelligence__mark_session_recorded,Read,Grep,Bash"
|
|
19
19
|
|
|
20
|
+
# ── intelligence MCP 명시 등록 (검증→성숙 루프 점화의 핵심) ─────────
|
|
21
|
+
# 과거엔 --allowedTools에 mcp__intelligence__* 를 나열해도 서버가 미등록이라(비-routinecode
|
|
22
|
+
# 프로젝트 cwd엔 intelligence MCP 없음) 헤드리스 세션이 미연결→stdio 우회 → syncToServer가
|
|
23
|
+
# 스킵됐다(서버 미동기, record_verification 미발동 → 성숙 승격 cold). --mcp-config + --strict로
|
|
24
|
+
# cwd 무관하게 항상 연결해 record_*/record_verification이 서버까지 도달하게 한다.
|
|
25
|
+
# (apiKey·serverUrl은 서버가 ~/.routinecode/config.json에서 읽으므로 추가 env 불필요)
|
|
26
|
+
RC_HOME="$(cd "$(dirname "$0")/.." 2>/dev/null && pwd)"
|
|
27
|
+
MCP_SERVER="$RC_HOME/mcp-intelligence/dist/index.js"
|
|
28
|
+
MCP_ARGS=()
|
|
29
|
+
MCP_CFG=""
|
|
30
|
+
if [ -f "$MCP_SERVER" ]; then
|
|
31
|
+
MCP_CFG="$(mktemp 2>/dev/null)"
|
|
32
|
+
if [ -n "$MCP_CFG" ]; then
|
|
33
|
+
printf '{"mcpServers":{"intelligence":{"command":"node","args":["%s"]}}}\n' "$MCP_SERVER" > "$MCP_CFG"
|
|
34
|
+
MCP_ARGS=(--mcp-config "$MCP_CFG" --strict-mcp-config)
|
|
35
|
+
fi
|
|
36
|
+
fi
|
|
37
|
+
|
|
20
38
|
# ── 비용 가드 ──────────────────────────────────────────────────
|
|
21
39
|
# 한 번의 드레인에서 스폰할 헤드리스 세션 수 상한. 큐가 폭주해도(버그·루프)
|
|
22
40
|
# 무한 스폰을 막는다. 초과분은 CLAIM에 남겨 다음 드레인이 이어받는다.
|
|
@@ -40,7 +58,7 @@ while IFS= read -r task; do
|
|
|
40
58
|
prompt="당신은 routinecode:recorder(지식 전담 기록자)다. 세션 transcript(${tp})를 Read/Grep으로 읽어 error-fix/pattern/quirk/decision/domain-knowledge를 추출하라. 감지된 signals: ${sig}. [도메인지식 능동 탐색 — 신호(${sig})에 domain_knowledge가 없어도 반드시 수행] transcript 전체에서 '코드만 읽어서는 알 수 없는' 정보를 능동적으로 찾아라. 판정 기준 단 하나: 이 정보를 코드/설정/git으로 유도할 수 있으면 저장 금지, 없으면 domain-knowledge다. 특히 두 유형을 놓치지 마라 — (1)암시적 발화: 키워드(기억해/절대/금지) 없이 규칙·정책·이유를 설명한 사용자 발화(예: '이건 카드사가 30분으로 정해둔 거라', '금요일 오후엔 배포 안 해'). '왜 이렇게 했나'의 답이 코드에 없으면 category=why/timing. (2)observed: 구현 중 외부 API가 문서와 다르게 동작한 관찰(예: '문서엔 X인데 실제 응답은 Y', 'rate limit 초과하면 24h 차단')→category=external, source=observed. category(why/timing/external/tenant)·source(user_correction/explicit/observed)·scope(관련 파일 절대경로 필수)를 채워 mcp__intelligence__record_domain_knowledge로 기록하라. 각 지식의 표면 표현을 mcp__intelligence__resolve_concept로 개념 후보를 받아 mcp__intelligence__record_grounding으로 의미층(concept)에 연결하라. 근거(에러원문/파일:line/사용자발화) 없는 지식은 절대 기록하지 마라. [Verification 폐루프 — signals에 verification이 있거나 항상 확인] ~/.routinecode/knowledge/community-usage.json 을 Read하라(있으면). 그 entries의 각 surfaced 지식(id, errorSignature)에 대해 transcript로 (a)실제 적용 여부와 (b)에러 최종 해소 여부를 판정해 mcp__intelligence__record_verification(errorFixId=<id>, result, project)를 호출하라 — 적용+해소=prevented, 적용했으나 실패=still_failed, transcript에 적용 근거 없음=not_applicable(기본값). 근거 없는 prevented는 절대 금지. 이것이 지식이 성숙(observation→pattern→rule)하는 유일한 신호다. 기록을 마쳤으면 mcp__intelligence__run_knowledge_critic(force=true)를 호출해 방금 기록한 지식의 품질(앵커 실존/중복/저신뢰)을 검증·격리하라. 그 다음 반드시 mcp__intelligence__mark_session_recorded(sessionId='${sid}', extracted, grounded, reason)를 호출하라(기록 0건이어도)."
|
|
41
59
|
|
|
42
60
|
drained=$((drained + 1))
|
|
43
|
-
if ROUTINECODE_RECORDER=1 "$CLAUDE_BIN" -p "$prompt" --allowedTools "$TOOLS" >/dev/null 2>&1; then
|
|
61
|
+
if ROUTINECODE_RECORDER=1 "$CLAUDE_BIN" -p "$prompt" --allowedTools "$TOOLS" ${MCP_ARGS[@]+"${MCP_ARGS[@]}"} >/dev/null 2>&1; then
|
|
44
62
|
: # 성공 (recorder가 mark_session_recorded로 마커 남김)
|
|
45
63
|
else
|
|
46
64
|
# 실패 → 재큐 (유실 방지)
|
|
@@ -49,3 +67,4 @@ while IFS= read -r task; do
|
|
|
49
67
|
done < "$CLAIM"
|
|
50
68
|
|
|
51
69
|
rm -f "$CLAIM"
|
|
70
|
+
[ -n "$MCP_CFG" ] && rm -f "$MCP_CFG"
|
package/hooks/session-start.sh
CHANGED
|
@@ -24,6 +24,13 @@ if [ "${ROUTINECODE_RECORDER:-}" != "1" ] && [ -f "$HOOKS_DIR/recorder-runner.sh
|
|
|
24
24
|
nohup bash "$HOOKS_DIR/recorder-runner.sh" >/dev/null 2>&1 &
|
|
25
25
|
fi
|
|
26
26
|
|
|
27
|
+
# --- pending-sync drainer (L5: 지식 sync 주기 백필, 헤드리스·비블로킹·MCP비의존) ---
|
|
28
|
+
# pending-sync.jsonl 을 서버로 push. 디바운스(1h)·rate(>=2.5s)·백오프·dead-letter 는 drainer 내부에서.
|
|
29
|
+
# get_* 트리거에 의존하던 flushPending 과 달리 cwd 무관하게 매 세션 시작 시 드레인한다.
|
|
30
|
+
if [ "${ROUTINECODE_RECORDER:-}" != "1" ] && [ -f "$HOOKS_DIR/pending-drainer.sh" ] && [ -f "$HOME/.routinecode/knowledge/pending-sync.jsonl" ]; then
|
|
31
|
+
nohup bash "$HOOKS_DIR/pending-drainer.sh" >/dev/null 2>&1 &
|
|
32
|
+
fi
|
|
33
|
+
|
|
27
34
|
# --- 0. Hook 자체 건강성 검증 + 자동 복구 (순수 bash, 외부 의존 없음) ---
|
|
28
35
|
PRISTINE_DIR="$HOME/.routinecode/pristine/hooks"
|
|
29
36
|
CRITICAL_HOOKS="pre-credit-guard.sh pre-edit-check.sh pre-agent-spawn.sh pre-webfetch-guard.sh pre-secret-guard.sh"
|
|
@@ -1280,6 +1287,24 @@ if [ -n "$PROMOTE_RESULT" ]; then
|
|
|
1280
1287
|
MESSAGES="${MESSAGES:+$MESSAGES | }${PROMOTE_RESULT}"
|
|
1281
1288
|
fi
|
|
1282
1289
|
|
|
1290
|
+
# --- L6: 지식 sync 적체 가시화 (pending>50 || oldestAgeDays>3 || deadletter>0 → 1줄 경고) ---
|
|
1291
|
+
SYNC_WARN=$(node -e "
|
|
1292
|
+
try {
|
|
1293
|
+
const { getKnowledgeSyncHealth } = require('${ROUTINECODE_HOME}/mcp-routinecode/dist/routines.js');
|
|
1294
|
+
const h = getKnowledgeSyncHealth();
|
|
1295
|
+
if (h.pending > 50 || h.oldestAgeDays > 3 || h.deadletter > 0) {
|
|
1296
|
+
const parts = ['KnowledgeSync backlog: pending=' + h.pending];
|
|
1297
|
+
if (h.oldestAgeDays > 0) parts.push('oldest=' + h.oldestAgeDays + 'd');
|
|
1298
|
+
if (h.deadletter > 0) parts.push('deadletter=' + h.deadletter);
|
|
1299
|
+
process.stdout.write('⚠ ' + parts.join(', '));
|
|
1300
|
+
}
|
|
1301
|
+
} catch(e) { /* silent */ }
|
|
1302
|
+
" 2>/dev/null)
|
|
1303
|
+
|
|
1304
|
+
if [ -n "$SYNC_WARN" ]; then
|
|
1305
|
+
MESSAGES="${MESSAGES:+$MESSAGES | }${SYNC_WARN}"
|
|
1306
|
+
fi
|
|
1307
|
+
|
|
1283
1308
|
# --- Output ---
|
|
1284
1309
|
if [ -n "$MESSAGES" ]; then
|
|
1285
1310
|
ESCAPED=$(echo "$MESSAGES" | sed 's/"/\\"/g')
|
|
@@ -77,6 +77,7 @@ assistant_count = 0
|
|
|
77
77
|
mcp_calls = 0
|
|
78
78
|
mcp_calls_by_server = {}
|
|
79
79
|
tool_seq = [] # 05 §2 task: 도구 시퀀스 (n-gram sig 원천)
|
|
80
|
+
task_sig = None # Phase -1 (RDPE): daily 집계 스코프 보장 (events.jsonl 회전 무관 영속)
|
|
80
81
|
|
|
81
82
|
for e in entries[last_user_idx + 1:]:
|
|
82
83
|
if e.get('type') != 'assistant':
|
|
@@ -238,6 +239,32 @@ for srv, cnt in mcp_calls_by_server.items():
|
|
|
238
239
|
mcp_srv[srv] = mcp_srv.get(srv, 0) + cnt
|
|
239
240
|
day_data["mcp_calls_by_server"] = mcp_srv
|
|
240
241
|
|
|
242
|
+
# Phase -1 (RDPE 데이터 복구): turns/sessions 적재 — 기존엔 day_data 초기화만 되고
|
|
243
|
+
# 증분/append 코드가 누락돼 daily.json에 turns=0·sessions=[]로 영구 고정됐었다.
|
|
244
|
+
# tokens/mcp_calls는 위에서 증분되나 turns/sessions는 여기서 복구한다.
|
|
245
|
+
try:
|
|
246
|
+
day_data["turns"] = day_data.get("turns", 0) + int(end_event["metadata"].get("total_turns", 0))
|
|
247
|
+
_sess = day_data.get("sessions", [])
|
|
248
|
+
if session_id and session_id not in _sess:
|
|
249
|
+
_sess.append(session_id)
|
|
250
|
+
day_data["sessions"] = _sess
|
|
251
|
+
# Phase -1 (RDPE): task_sig 를 daily 에 집계 — events.jsonl 회전과 무관하게 영속.
|
|
252
|
+
# 반복 작업 감지(occurrence_count)의 교차세션 영속 입력. 세션당 마지막 task_sig 1건.
|
|
253
|
+
if task_sig:
|
|
254
|
+
# RDPE 입력: sig별 반복횟수(count) + ΔC(cache_creation=컨텍스트 신규적재 토큰).
|
|
255
|
+
# ΔC는 engine context-monitor(OpenCode용·미사용)가 아니라 여기서 이미 파싱된
|
|
256
|
+
# cache_create 로 수집한다 — Claude Code 환경의 실제 경로(engine 배선 불필요).
|
|
257
|
+
_tsigs = day_data.get("task_sigs", {})
|
|
258
|
+
_prev = _tsigs.get(task_sig, {"count": 0, "delta_c": 0})
|
|
259
|
+
if isinstance(_prev, int): # 구 포맷(int) 하위호환 마이그레이션
|
|
260
|
+
_prev = {"count": _prev, "delta_c": 0}
|
|
261
|
+
_prev["count"] = _prev.get("count", 0) + 1
|
|
262
|
+
_prev["delta_c"] = _prev.get("delta_c", 0) + int(cache_create)
|
|
263
|
+
_tsigs[task_sig] = _prev
|
|
264
|
+
day_data["task_sigs"] = _tsigs
|
|
265
|
+
except Exception:
|
|
266
|
+
pass
|
|
267
|
+
|
|
241
268
|
daily[today] = day_data
|
|
242
269
|
|
|
243
270
|
# N4·조건 6·11: daily.json write를 fail-open으로
|