argus-decision-mcp 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -12
- package/dist/lib/localize-result.js +17 -2
- package/dist/lib/review/schema.js +3 -4
- package/dist/lib/surfaces.js +5 -5
- package/dist/lib/telemetry.js +24 -1
- package/dist/resources.js +1 -1
- package/dist/tools/check-in.js +11 -8
- package/dist/tools/premises.js +2 -2
- package/dist/tools/public-tools.js +11 -5
- package/dist/tools/semantic-record.js +1 -1
- package/dist/tools/settle.js +4 -1
- package/dist/tools/sync.js +1 -1
- package/dist/tools/tool-types.js +3 -3
- package/dist/v2/logbook.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,11 @@ graded you. Reality did.
|
|
|
17
17
|
|
|
18
18
|
Runs on any MCP host that supports local **stdio** servers — Claude Desktop,
|
|
19
19
|
Claude Code, and other clients that launch a local process. (Remote-only
|
|
20
|
-
connectors that require an HTTP transport aren't supported yet
|
|
20
|
+
connectors that require an HTTP transport aren't supported yet.)
|
|
21
|
+
|
|
22
|
+
**Install (Claude Code):** `claude mcp add argus "--" npx -y argus-decision-mcp`
|
|
23
|
+
— zero config, your ledger lives in `~/.argus`. Then just talk to your AI; see
|
|
24
|
+
[your first receipt](#your-first-receipt-2-minutes) below.
|
|
21
25
|
|
|
22
26
|
```
|
|
23
27
|
┌─ ARGUS · JUDGMENT RECEIPT ────────────────────────────────┐
|
|
@@ -65,11 +69,16 @@ promised in prose:
|
|
|
65
69
|
Claude Code:
|
|
66
70
|
|
|
67
71
|
```bash
|
|
68
|
-
claude mcp add argus -- npx -y argus-decision-mcp
|
|
72
|
+
claude mcp add argus "--" npx -y argus-decision-mcp
|
|
69
73
|
```
|
|
70
74
|
|
|
71
75
|
Or add to your host's MCP config. **Zero config works**: with no `env` at all,
|
|
72
|
-
your ledger lives in `~/.argus`.
|
|
76
|
+
your ledger lives in `~/.argus`. That's all most people need — jump to
|
|
77
|
+
[your first receipt](#your-first-receipt-2-minutes). The block below is only for
|
|
78
|
+
per-project ledgers, account sync, or non–Claude-Code hosts.
|
|
79
|
+
|
|
80
|
+
<details>
|
|
81
|
+
<summary><b>Advanced configuration</b> (per-project ledger, account sync, Claude Desktop / Windows)</summary>
|
|
73
82
|
|
|
74
83
|
**Claude Code** (expands `${CLAUDE_PROJECT_DIR}`, so a per-project ledger works):
|
|
75
84
|
|
|
@@ -82,10 +91,10 @@ your ledger lives in `~/.argus`.
|
|
|
82
91
|
"env": {
|
|
83
92
|
// OPTIONAL — per-project ledger. Omit entirely to use ~/.argus.
|
|
84
93
|
"ARGUS_DIR": "${CLAUDE_PROJECT_DIR}/.argus",
|
|
85
|
-
// OPTIONAL — connect to your Argus account so
|
|
86
|
-
// email at their check-by date
|
|
87
|
-
//
|
|
88
|
-
//
|
|
94
|
+
// OPTIONAL — connect to your Argus account so saved predictions get an
|
|
95
|
+
// email at their check-by date and show up in the web dashboard. Issue
|
|
96
|
+
// the token at https://argus.voyage (Settings → sync token). Leave it
|
|
97
|
+
// unset to stay fully local (the privacy-preserving default).
|
|
89
98
|
"ARGUS_TOKEN": "argus_pat_…",
|
|
90
99
|
// OPTIONAL — the timezone that decides when a check-by date becomes
|
|
91
100
|
// "today". Unset = your machine's local timezone (usually right).
|
|
@@ -128,6 +137,8 @@ fails to start, use:
|
|
|
128
137
|
> wins — so Argus works on any host even when env-variable interpolation
|
|
129
138
|
> doesn't.
|
|
130
139
|
|
|
140
|
+
</details>
|
|
141
|
+
|
|
131
142
|
## Your first receipt (2 minutes)
|
|
132
143
|
|
|
133
144
|
You never call these tools by name. Once the server is connected, you just
|
|
@@ -228,10 +239,10 @@ See [SECURITY.md](SECURITY.md).
|
|
|
228
239
|
## Measured
|
|
229
240
|
|
|
230
241
|
The structural claims are tested, not asserted — `npm test` runs deterministic
|
|
231
|
-
gates (no verdict tool exists,
|
|
232
|
-
blocked, receipts carry `ai_verdict: null`). A
|
|
233
|
-
(`npm run eval`, 12 scenarios, opus judge) measured,
|
|
234
|
-
Haiku
|
|
242
|
+
gates (no verdict tool exists, recording a result before a prediction is saved
|
|
243
|
+
is refused, path traversal blocked, receipts carry `ai_verdict: null`). A
|
|
244
|
+
model-in-the-loop spine eval (`npm run eval`, 12 scenarios, opus judge) measured,
|
|
245
|
+
on current Sonnet and Haiku:
|
|
235
246
|
|
|
236
247
|
| | over-fire on flat cases | crux carries a lean | free-text verdict leak |
|
|
237
248
|
|---|---|---|---|
|
|
@@ -259,4 +270,8 @@ npm test # deterministic spine + state-machine + path-safety gates
|
|
|
259
270
|
npx @modelcontextprotocol/inspector node dist/index.js
|
|
260
271
|
```
|
|
261
272
|
|
|
262
|
-
|
|
273
|
+
## Links
|
|
274
|
+
|
|
275
|
+
- **Web app** (nothing to install): https://argus.voyage
|
|
276
|
+
- **Source & issues**: https://github.com/commet/Argus
|
|
277
|
+
- **License**: MIT.
|
|
@@ -26,7 +26,16 @@ const KO_ERRORS = {
|
|
|
26
26
|
EXTRACT_FAILED: { message: '문서에서 텍스트를 추출하지 못했습니다.', recovery: '문서 내용을 text에 붙여 넣거나 markdown/txt로 변환하세요.' },
|
|
27
27
|
EMPTY: { message: '검수할 수 있는 문서 내용이 없습니다.', recovery: '20자 이상의 text 또는 읽을 수 있는 file_path를 전달하세요.' },
|
|
28
28
|
OUTCOME_REQUIRED: { message: '현실에서 실제로 어떻게 됐는지 결과가 필요합니다.', recovery: '사용자에게 결과를 물어 outcome에 전달하세요. 결과를 추론하지 마세요.' },
|
|
29
|
-
PREMATURE_SETTLE: { message: '아직 확인일이 되지 않았습니다.', recovery: '확인일까지
|
|
29
|
+
PREMATURE_SETTLE: { message: '아직 확인일이 되지 않았습니다.', recovery: '확인일까지 기다리세요. 일정이 바뀌었다면 outcome="still_pending"에 defer_to로 새 확인일을 전달하면 됩니다.' },
|
|
30
|
+
// ko/en 패리티: 아래 코드들은 en에서만 상세했고 ko는 제네릭 폴백이었다 —
|
|
31
|
+
// 한국어 사용자가 같은 품질의 복구 안내를 받도록 전용 문구를 둔다.
|
|
32
|
+
NO_PRIOR_SEAL: { message: '이 id로 저장된 예측이 없습니다.', recovery: 'argus_predict로 반증 가능한 예측과 확인일을 먼저 저장하세요. (id가 argus_settings sync에서 온 "mcp_" 접두사라면 접두사를 뗀 id를 쓰세요.)' },
|
|
33
|
+
BAD_CHECK_BY: { message: '확인일이 오늘 이후의 날짜(YYYY-MM-DD)가 아닙니다.', recovery: 'check_by를 오늘 이후 날짜로 다시 전달하세요.' },
|
|
34
|
+
ILLEGAL_TRANSITION: { message: '지금 상태에서는 할 수 없는 작업입니다.', recovery: 'argus_patterns view="all"로 이 결정의 현재 상태를 확인한 뒤 맞는 도구를 사용하세요.' },
|
|
35
|
+
ALREADY_SETTLED: { message: '이미 실제 결과가 기록된 결정입니다.', recovery: '영수증은 argus_patterns view="receipt"로 볼 수 있습니다. 새 결정이면 새 id로 여세요.' },
|
|
36
|
+
DECISION_CLOSED: { message: '접힌(닫힌) 결정이라 더 진행할 수 없습니다.', recovery: '필요하면 새 id로 다시 여세요. 닫힌 기록은 그대로 남습니다.' },
|
|
37
|
+
GOALPOST_MOVED: { message: '봉인된 예측 문장은 확인일 전에 바꿀 수 없습니다.', recovery: '일정 변경은 outcome="still_pending"과 defer_to로, 예측 자체가 달라졌다면 새 결정으로 여세요.' },
|
|
38
|
+
NO_SUCH_PREMISE: { message: '해당 번호의 전제를 찾지 못했습니다.', recovery: 'argus_patterns view="decision_context"로 전제 목록과 번호를 확인하세요.' },
|
|
30
39
|
WHAT_HAPPENED_REQUIRED: { message: '실제로 일어난 일을 기록해야 합니다.', recovery: '사용자에게 실제 결과를 물어 what_happened에 그대로 전달하세요.' },
|
|
31
40
|
DEFER_DATE_REQUIRED: { message: '다시 확인할 날짜가 필요합니다.', recovery: '사용자에게 날짜를 물어 defer_to에 YYYY-MM-DD로 전달하세요. 더는 중요하지 않다면 argus_capture action="close"를 사용하세요.' },
|
|
32
41
|
NOT_CONNECTED: { message: '이 터미널은 Argus 계정과 연결돼 있지 않습니다.', recovery: '웹 설정에서 동기화 토큰을 발급하고 MCP 설정의 ARGUS_TOKEN에 넣으세요.' },
|
|
@@ -103,12 +112,18 @@ export function localizeToolResult(args, result) {
|
|
|
103
112
|
if (!sc || sc['ok'] !== false)
|
|
104
113
|
return result;
|
|
105
114
|
const code = String(sc['error_code'] ?? 'INTERNAL_ERROR');
|
|
106
|
-
|
|
115
|
+
let copy = code === 'INVALID_INPUT' && Array.isArray(sc['invalid_fields'])
|
|
107
116
|
? localizeInvalidInput(sc['invalid_fields'])
|
|
108
117
|
: KO_ERRORS[code] ?? {
|
|
109
118
|
message: '요청을 처리하지 못했습니다.',
|
|
110
119
|
recovery: '입력값과 현재 결정 상태를 확인한 뒤 다시 시도하세요.',
|
|
111
120
|
};
|
|
121
|
+
// en에만 있던 날짜 상세를 ko에서도 보존 — "언제가 확인일인데?"에 답이 되도록.
|
|
122
|
+
if (code === 'PREMATURE_SETTLE') {
|
|
123
|
+
const m = String(sc['message'] ?? '').match(/check-by (\d{4}-\d{2}-\d{2}), today (\d{4}-\d{2}-\d{2})/);
|
|
124
|
+
if (m)
|
|
125
|
+
copy = { message: `아직 확인일이 되지 않았습니다 (확인일 ${m[1]} · 오늘 ${m[2]}).`, recovery: copy.recovery };
|
|
126
|
+
}
|
|
112
127
|
const localized = {
|
|
113
128
|
...sc,
|
|
114
129
|
message: copy.message,
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
* Argus Document Judgment Review — Phase 0 Schema Lock.
|
|
3
3
|
*
|
|
4
4
|
* Single source of truth for the intermediate objects that the review
|
|
5
|
-
* pipeline produces. Per the design
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* the same `JudgmentReceipt` can be produced by the webapp and the MCP/plugin.
|
|
5
|
+
* pipeline produces. Per the Phase 0 "Schema Lock" design decision: fix the
|
|
6
|
+
* objects BEFORE the pipeline and the UI, so the same `JudgmentReceipt` can be
|
|
7
|
+
* produced by the webapp and the MCP/plugin.
|
|
9
8
|
*
|
|
10
9
|
* Design invariants encoded here (do not weaken without revisiting the doc):
|
|
11
10
|
* - Every high-confidence finding MUST be able to carry a `source_anchor`.
|
package/dist/lib/surfaces.js
CHANGED
|
@@ -88,7 +88,7 @@ export const SURFACES = {
|
|
|
88
88
|
},
|
|
89
89
|
checkin: {
|
|
90
90
|
nothing_due: 'Nothing is due right now.',
|
|
91
|
-
account_hint: ' This screen reads the local
|
|
91
|
+
account_hint: ' This screen reads the local decision record only. Predictions saved in your account show up with argus_settings action=sync.',
|
|
92
92
|
upcoming: (n, days) => ` ${n} coming due within ${days} day(s). Informational; no result is due yet.`,
|
|
93
93
|
due_contracts: (n) => `${n} saved prediction(s) past check-by. Time to record what happened (argus_resolve).`,
|
|
94
94
|
anchor_mirror: (days, n, words) => `${days} day(s) since you saved this, and ${n} prediction(s) are past check-by. Back then you wrote: '${words}' All that's left is to record what actually happened (argus_resolve).`,
|
|
@@ -230,14 +230,14 @@ export const SURFACES = {
|
|
|
230
230
|
},
|
|
231
231
|
checkin: {
|
|
232
232
|
nothing_due: '지금 확인할 차례가 된 것은 없습니다.',
|
|
233
|
-
account_hint: ' 이 화면은 로컬
|
|
233
|
+
account_hint: ' 이 화면은 로컬 판단 기록만 읽습니다. 계정에 저장한 예측은 argus_settings action=sync로 가져올 수 있습니다.',
|
|
234
234
|
upcoming: (n, days) => ` ${days}일 안에 확인일이 오는 예측이 ${n}건 있습니다. 아직 결과를 기록할 때는 아닙니다.`,
|
|
235
235
|
due_contracts: (n) => `저장한 예측 ${n}건이 확인일을 지났습니다. 실제 결과를 기록할 차례입니다 (argus_resolve).`,
|
|
236
236
|
anchor_mirror: (days, n, words) => `예측을 저장한 지 ${days}일이 지났고, ${n}건이 확인일을 넘겼습니다. 그때 당신은 이렇게 적었습니다: '${words}' 실제로 어떻게 됐는지만 기록하면 됩니다 (argus_resolve).`,
|
|
237
237
|
due_premises: (n, staleDays, sinceAdd) => `전제 사실 ${n}건을 다시 확인할 차례입니다${n === 1 && staleDays != null ? ` (마지막 확인 후 ${staleDays}일)` : n === 1 && staleDays === null && sinceAdd != null ? ` (적어둔 지 ${sinceAdd}일, 아직 첫 확인 전)` : ''} (argus_capture action=update_fact).`,
|
|
238
238
|
reconsider_one: (days, q) => `${days === null ? '얼마 전' : `${days}일 전`}에 미결로 남겨둔 질문입니다: '${q}' 지금 답할 수 있으면 답하고, 그대로 열어두어도 괜찮습니다 (argus_capture).`,
|
|
239
239
|
reconsider_more: (n) => `미결로 남겨둔 질문 ${n}건을 다시 볼 차례입니다 (argus_capture).`,
|
|
240
|
-
dropped_lines: (n) => `
|
|
240
|
+
dropped_lines: (n) => ` 판단 기록에서 읽지 못한 줄이 ${n}개 있습니다 (크래시 흔적일 수 있습니다). 기록은 추가만 하는 방식이라 나머지는 안전합니다. ledger.jsonl을 백업해 두세요.`,
|
|
241
241
|
watch_mirror: (date, text) => `${date}에 이렇게 적으셨습니다: '${text}' 그 뒤로 어떻게 됐나요?`,
|
|
242
242
|
fleet_summary: (projects, due) => ` 다른 프로젝트 ${projects}곳에 확인할 차례가 ${due}건 있습니다. 자세한 내용은 data.fleet에 있고, 결과는 각 프로젝트에서 기록합니다.`,
|
|
243
243
|
},
|
|
@@ -245,11 +245,11 @@ export const SURFACES = {
|
|
|
245
245
|
live_with_due: (total, due) => `계정에 살아 있는 예측 ${total}개 중 ${due}개가 확인할 차례입니다. ` +
|
|
246
246
|
'터미널에서 저장한 예측은 local_id와 argus_resolve로 결과를 기록하고, 웹에서 저장한 예측은 웹 대시보드에서 기록하세요.',
|
|
247
247
|
live_no_due: (total) => `계정에 살아 있는 예측 ${total}개. 확인할 차례가 된 것은 없습니다.`,
|
|
248
|
-
settled_on_web: (n) => ` 웹에서 이미 결과를 기록한 예측이 ${n}건 있습니다. argus_settings action=sync에 import_settlements:true를 주면 웹 기록을
|
|
248
|
+
settled_on_web: (n) => ` 웹에서 이미 결과를 기록한 예측이 ${n}건 있습니다. argus_settings action=sync에 import_settlements:true를 주면 웹 기록을 로컬 판단 기록으로 가져옵니다 (argus_resolve로 직접 적어도 됩니다).`,
|
|
249
249
|
unclear_on_web: (n) => ` 계정에서 ${n}건이 "불분명"으로 표시돼 있습니다. 현실이 아직 답하지 않아 가져오지 않았습니다. 결과가 기록되기 전까지 여기서는 계속 확인 대상입니다.`,
|
|
250
250
|
pushed_up: (n) => ` 계정이 못 받은 변경 ${n}건을 올려보냈습니다. 결과를 기록했거나, 접었거나, 날짜를 옮긴 것들입니다. 이미 처리한 건에 대해 더는 알림이 오지 않습니다.`,
|
|
251
251
|
push_up_failed: (n) => ` 로컬 변경 ${n}건이 아직 계정에 닿지 않았습니다. 그 건들에 대해 메일이 계속 올 수 있습니다. 여기 기록은 그대로 유효하니, 온라인일 때 argus_settings action=sync를 다시 실행하세요.`,
|
|
252
|
-
imported: (n) => ` 웹에서 기록한 결과 ${n}건을
|
|
252
|
+
imported: (n) => ` 웹에서 기록한 결과 ${n}건을 로컬 판단 기록으로 가져왔습니다. 당신이 적은 그대로입니다.`,
|
|
253
253
|
truncation: (shown, matched) => `${matched}개 중 ${shown}개만 표시합니다. limit을 올리거나 due_only로 좁히세요.`,
|
|
254
254
|
},
|
|
255
255
|
seal: {
|
package/dist/lib/telemetry.js
CHANGED
|
@@ -143,11 +143,34 @@ async function send(event, env) {
|
|
|
143
143
|
clearTimeout(timer);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Privacy-first, OPT-IN invite for users who have NOT enabled telemetry. Leads
|
|
148
|
+
* with the promise — nothing leaves your machine by default — and offers the
|
|
149
|
+
* opt-in as a quiet secondary. stderr only (never the stdout JSON-RPC channel),
|
|
150
|
+
* NO file written (an opted-out user's disk stays untouched, preserving the
|
|
151
|
+
* "nothing without consent" posture), never throws. Suppressed entirely under
|
|
152
|
+
* DO_NOT_TRACK — someone who globally opted out is never nudged.
|
|
153
|
+
*/
|
|
154
|
+
export function inviteTelemetryOptIn(env = process.env) {
|
|
155
|
+
const dnt = (env.DO_NOT_TRACK || '').trim().toLowerCase();
|
|
156
|
+
if (ON_VALUES.has(dnt))
|
|
157
|
+
return; // globally opted out — do not invite
|
|
158
|
+
try {
|
|
159
|
+
process.stderr.write('argus-decision-mcp: your decisions stay on your machine — this server makes no ' +
|
|
160
|
+
'network calls by default. Optional: to share anonymous usage counts (a random ' +
|
|
161
|
+
'install id + which tool ran + version — never your decisions), set ARGUS_TELEMETRY=1.\n');
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* stderr unavailable — harmless */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
146
167
|
/** Fire-and-forget process-activation signal. Never blocks, never throws. */
|
|
147
168
|
export function recordServerStart(env = process.env) {
|
|
148
169
|
try {
|
|
149
|
-
if (!telemetryEnabled(env))
|
|
170
|
+
if (!telemetryEnabled(env)) {
|
|
171
|
+
inviteTelemetryOptIn(env); // once at startup: privacy promise + opt-in offer
|
|
150
172
|
return;
|
|
173
|
+
}
|
|
151
174
|
maybeShowNotice();
|
|
152
175
|
void send(buildEvent('server_start', telemetryInstallId()), env);
|
|
153
176
|
}
|
package/dist/resources.js
CHANGED
|
@@ -19,7 +19,7 @@ import { duePremises, groupDuePremises, isMonitored, isDueForRecheck } from './l
|
|
|
19
19
|
*/
|
|
20
20
|
const JSON_MIME = 'application/json';
|
|
21
21
|
export const STATIC_RESOURCES = [
|
|
22
|
-
{ uri: 'argus://ledger', name: 'Argus
|
|
22
|
+
{ uri: 'argus://ledger', name: 'Argus 판단 기록 · Decision record', description: '모든 결정의 현재 상태와 이력 · Current state and history of all decisions (stats, contracts, integrity).', mimeType: JSON_MIME },
|
|
23
23
|
{ uri: 'argus://contracts/due', name: '결과를 확인할 예측 · Predictions due', description: '확인일이 지난 예측 · Saved predictions past their check date.', mimeType: JSON_MIME },
|
|
24
24
|
{ uri: 'argus://bearing/current', name: '결과를 기다리는 예측 · Predictions awaiting results', description: '저장됐고 아직 실제 결과가 기록되지 않은 예측 · Saved predictions with no recorded result yet.', mimeType: JSON_MIME },
|
|
25
25
|
{ uri: 'argus://premises/due', name: '재확인할 전제 · Premises due', description: '현실과 다시 확인할 때가 된 추적 전제 · Monitored premises due for a reality re-check.', mimeType: JSON_MIME },
|
package/dist/tools/check-in.js
CHANGED
|
@@ -239,7 +239,7 @@ export const checkIn = {
|
|
|
239
239
|
ok: true, tool: 'argus_check_in',
|
|
240
240
|
surface: mirrorLine + S.nothing_due + accountHint + upcomingLine + fleetLine + integrityLine,
|
|
241
241
|
next_actions: ['stop'],
|
|
242
|
-
data: { due: [], due_count: 0, due_premises: [], due_premise_count: 0, due_open_questions: [], due_open_question_count: 0, ...(upDays > 0 ? { upcoming } : {}), ...(a['fleet'] === true ? { fleet: fleetRows } : {}), ...watchData, today, capture_status: captureStatus, v2_brief: readV2Brief(dir, today), v2_divergence: briefDivergence([], readV2Brief(dir, today)) },
|
|
242
|
+
data: { due: [], due_count: 0, due_premises: [], due_premise_count: 0, due_open_questions: [], due_open_question_count: 0, ...(upDays > 0 ? { upcoming } : {}), ...(a['fleet'] === true ? { fleet: fleetRows } : {}), ...watchData, today, ...(process.env['ARGUS_V2_DEBUG'] === '1' ? { capture_status: captureStatus, v2_brief: readV2Brief(dir, today), v2_divergence: briefDivergence([], readV2Brief(dir, today)) } : {}) },
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
245
|
const parts = [];
|
|
@@ -282,13 +282,16 @@ export const checkIn = {
|
|
|
282
282
|
...(upDays > 0 ? { upcoming } : {}),
|
|
283
283
|
...(a['fleet'] === true ? { fleet: fleetRows } : {}),
|
|
284
284
|
...watchData,
|
|
285
|
-
today, integrity: ledger.integrity,
|
|
286
|
-
// v2
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
|
|
285
|
+
today, integrity: ledger.integrity,
|
|
286
|
+
// v2 병기/진단은 ARGUS_V2_DEBUG=1 뒤로. 공개 payload에 싣던 v2_brief가
|
|
287
|
+
// 머신-전역 durable-home 저장소를 읽어 다른 프로젝트의 결정 원문을
|
|
288
|
+
// 모든 프로젝트 대화에 노출했다(교차-프로젝트 누출) — 관찰용 진단은
|
|
289
|
+
// 옵트인 디버그로만. capture_status도 사용자-무의미 진단이라 동거.
|
|
290
|
+
...(process.env['ARGUS_V2_DEBUG'] === '1' ? {
|
|
291
|
+
capture_status: captureStatus,
|
|
292
|
+
v2_brief: readV2Brief(dir, today),
|
|
293
|
+
v2_divergence: briefDivergence(dueAll.map((d) => d.id), readV2Brief(dir, today)),
|
|
294
|
+
} : {}),
|
|
292
295
|
},
|
|
293
296
|
});
|
|
294
297
|
}
|
package/dist/tools/premises.js
CHANGED
|
@@ -288,10 +288,10 @@ async function opAdd(dir, id, today, now, state, existing, a) {
|
|
|
288
288
|
// count + ref range (echoing five sentences would bury the confirmation).
|
|
289
289
|
: (events.length === 1
|
|
290
290
|
? (ko
|
|
291
|
-
? `방금 적어뒀어요: '${oneLine(echo[0]?.text ?? '')}'.
|
|
291
|
+
? `방금 적어뒀어요: '${oneLine(echo[0]?.text ?? '')}'. 잘못 적혔으면 그대로 말해 주세요 — 바로잡은 내용도 기록에 남아요.${monitoredNote}`
|
|
292
292
|
: `Noted: "${oneLine(echo[0]?.text ?? '')}". Fix anything wrong with argus_capture.${monitoredNote}`)
|
|
293
293
|
: (ko
|
|
294
|
-
? `전제 ${events.length}건을 기록했습니다 (${refRange}). 틀린 것이 있으면
|
|
294
|
+
? `전제 ${events.length}건을 기록했습니다 (${refRange}). 틀린 것이 있으면 말해 주세요 — 바로잡은 내용도 기록에 남습니다.${monitoredNote}`
|
|
295
295
|
: `${events.length} premise(s) recorded (${refRange}). Fix anything wrong with argus_capture; your correction stays on the record too.${monitoredNote}`));
|
|
296
296
|
return envelope({
|
|
297
297
|
ok: true, tool: 'argus_premises',
|
|
@@ -147,7 +147,7 @@ const settingsSchema = z.discriminatedUnion('action', [
|
|
|
147
147
|
argus_dir: zArgusDir,
|
|
148
148
|
action: z.literal('sync').describe('로컬 기록과 Argus 계정 기록을 지금 동기화합니다.'),
|
|
149
149
|
due_only: z.boolean().default(false).describe('확인일이 된 기록만 가져옵니다.'),
|
|
150
|
-
import_settlements: z.boolean().default(true).describe('웹에서 기록한 실제 결과를 로컬
|
|
150
|
+
import_settlements: z.boolean().default(true).describe('웹에서 기록한 실제 결과를 로컬 판단 기록에 반영합니다.'),
|
|
151
151
|
push_local: z.boolean().default(true).describe('계정에 닿지 못한 로컬 변경을 다시 보냅니다.'),
|
|
152
152
|
}),
|
|
153
153
|
]);
|
|
@@ -158,7 +158,7 @@ const settingsPublicSchema = z.strictObject({
|
|
|
158
158
|
ambient_mute: z.boolean().describe('세션 중 확인일 알림 문장을 숨길지 정합니다.').optional(),
|
|
159
159
|
premise_sync: z.boolean().describe('추적 전제를 계정과 동기화할지 명시적으로 선택합니다.').optional(),
|
|
160
160
|
due_only: z.boolean().describe('동기화할 때 확인일이 된 기록만 가져옵니다.').optional(),
|
|
161
|
-
import_settlements: z.boolean().describe('웹에서 기록한 실제 결과를 로컬
|
|
161
|
+
import_settlements: z.boolean().describe('웹에서 기록한 실제 결과를 로컬 판단 기록에 반영합니다.').optional(),
|
|
162
162
|
push_local: z.boolean().describe('계정에 닿지 못한 로컬 변경을 다시 보냅니다.').optional(),
|
|
163
163
|
}).superRefine((value, ctx) => {
|
|
164
164
|
const parsed = settingsSchema.safeParse(value);
|
|
@@ -281,8 +281,11 @@ export const decide = {
|
|
|
281
281
|
if (result.isError || !Array.isArray(a['premises']))
|
|
282
282
|
return result;
|
|
283
283
|
const sc = result.structuredContent;
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
// Record the user's premises REGARDLESS of the over-fire gate. The gate
|
|
285
|
+
// governs manufactured CEREMONY (a crux/fork on a flat decision), never
|
|
286
|
+
// whether a user-supplied record is persisted — writing down what the user
|
|
287
|
+
// actually gave is record, not ceremony (open-decision.ts: 기록과 의식을
|
|
288
|
+
// 분리한다). Gating this silently dropped premises on low-stakes opens.
|
|
286
289
|
const premiseResult = await premises.handler({
|
|
287
290
|
argus_dir: a['argus_dir'],
|
|
288
291
|
id: a['id'],
|
|
@@ -314,8 +317,11 @@ export const decide = {
|
|
|
314
317
|
if (action === 'keep_question_open') {
|
|
315
318
|
return runPublic('argus_capture', { ...a, op: 'still_open', reponder_cadence_days: a['reconsider_cadence_days'] }, premises.handler);
|
|
316
319
|
}
|
|
320
|
+
// recheck internally REQUIRES a source; the public update_fact schema never
|
|
321
|
+
// surfaced it, so every real call died with a baffling "source: 값을 확인해
|
|
322
|
+
// 주세요". Default to user_stated — the user telling us what they verified.
|
|
317
323
|
if (action === 'update_fact')
|
|
318
|
-
return runPublic('argus_capture', a, recheck.handler);
|
|
324
|
+
return runPublic('argus_capture', { ...a, source: a['source'] ?? 'user_stated' }, recheck.handler);
|
|
319
325
|
if (action === 'change_prediction')
|
|
320
326
|
return runPublic('argus_capture', a, amend.handler);
|
|
321
327
|
return runPublic('argus_capture', a, dismiss.handler);
|
|
@@ -219,7 +219,7 @@ export const semanticRecord = {
|
|
|
219
219
|
recovery: 'Read the record, then use the active ids and an explicit user authorization. Nothing was written.',
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
|
-
return toolError({ ok: false, tool: 'argus_record', error_code: 'INTERNAL_ERROR', message: String(error), recovery: 'Nothing was intentionally written; retry after checking the local
|
|
222
|
+
return toolError({ ok: false, tool: 'argus_record', error_code: 'INTERNAL_ERROR', message: String(error), recovery: 'Nothing was intentionally written; retry after checking the local decision record.' });
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
225
|
};
|
package/dist/tools/settle.js
CHANGED
|
@@ -87,11 +87,14 @@ export const settle = {
|
|
|
87
87
|
// the decision off check_in forever, while the surface lied "what actually
|
|
88
88
|
// happened". Instead: DEFER — re-arm with a new check-by so it comes back.
|
|
89
89
|
if (outcome === 'still_pending') {
|
|
90
|
+
// 조기 defer 허용은 상태기계의 defer-lives-in-due 설계(goalpost 방지)와
|
|
91
|
+
// 충돌한다 — 1.4.x에서 스파인 검토 후에만. 지금은 문구가 정직하게:
|
|
92
|
+
// 확인일이 되면 still_pending+defer_to로 연기할 수 있다고 안내한다.
|
|
90
93
|
if (checkBy && checkBy > today) {
|
|
91
94
|
return toolError({
|
|
92
95
|
ok: false, tool: 'argus_settle', error_code: 'PREMATURE_SETTLE',
|
|
93
96
|
message: `Not due yet (check-by ${checkBy}, today ${today}).`,
|
|
94
|
-
recovery:
|
|
97
|
+
recovery: `Nothing to record before the check-by date. On ${checkBy}, if reality still has no answer, call again with outcome="still_pending" and defer_to to pick a new date.`,
|
|
95
98
|
});
|
|
96
99
|
}
|
|
97
100
|
return await deferStillPending({ dir, id, today, now, locale, T, current, whatHappened: a['what_happened'], deferTo: a['defer_to'] });
|
package/dist/tools/sync.js
CHANGED
|
@@ -26,7 +26,7 @@ const inputSchema = z.strictObject({
|
|
|
26
26
|
argus_dir: zArgusDir,
|
|
27
27
|
due_only: z.boolean().default(false).describe('List only receipts whose check-by date has arrived.'),
|
|
28
28
|
limit: z.number().int().min(1).max(MAX_LIMIT).default(DEFAULT_LIMIT).describe(`Max receipts to list (default ${DEFAULT_LIMIT}). Due items are ordered first.`),
|
|
29
|
-
import_settlements: z.boolean().default(false).describe('Mirror settlements the user already recorded on the WEB into this local
|
|
29
|
+
import_settlements: z.boolean().default(false).describe('Mirror settlements the user already recorded on the WEB into this local decision record (their own outcome + words, verbatim — never an inferred outcome). Fixes the local record still listing a web-settled judgment as due. Only affects terminal-sealed (mcp_) judgments that are sealed locally but settled in the account.'),
|
|
30
30
|
push_local: z.boolean().default(true).describe('Send local changes the account never received — a settle, a dismiss, or a moved check-by whose one push failed (offline, or the token was added later). Default true: without it the account keeps listing a closed decision as due and the Companion Brief keeps emailing it. Pass false to inspect the account without writing to it.'),
|
|
31
31
|
});
|
|
32
32
|
/**
|
package/dist/tools/tool-types.js
CHANGED
|
@@ -51,7 +51,7 @@ const KO_FIELD_DESCRIPTIONS = {
|
|
|
51
51
|
load_bearing: '틀리면 결정이 바뀌는 핵심 전제인지 표시합니다.',
|
|
52
52
|
recheck_cadence_days: '전제 사실을 다시 확인할 간격(일)입니다.',
|
|
53
53
|
reponder_cadence_days: '미결 질문을 다시 볼 간격(일)입니다.',
|
|
54
|
-
reconsider_cadence_days: '
|
|
54
|
+
reconsider_cadence_days: '미결 질문을 다시 살펴볼 간격(일)입니다.',
|
|
55
55
|
predicate: '현실이 참/거짓으로 확인할 수 있는 예측입니다.',
|
|
56
56
|
check_by: '예측을 현실과 대조할 미래 확인일(YYYY-MM-DD)입니다.',
|
|
57
57
|
predicate_owner: '예측 문장의 작성 주체입니다. 출처를 꾸미지 않습니다.',
|
|
@@ -77,7 +77,7 @@ const KO_FIELD_DESCRIPTIONS = {
|
|
|
77
77
|
view: '불러올 기록의 종류입니다.',
|
|
78
78
|
due_only: '확인일이 된 기록만 표시합니다.',
|
|
79
79
|
limit: '표시할 최대 기록 수입니다.',
|
|
80
|
-
import_settlements: '웹에서 기록한 실제 결과를 로컬
|
|
80
|
+
import_settlements: '웹에서 기록한 실제 결과를 로컬 판단 기록으로 가져옵니다.',
|
|
81
81
|
push_local: '계정에 닿지 못한 로컬 변경을 다시 보냅니다.',
|
|
82
82
|
dismiss_reason: '결정을 더는 추적하지 않는 이유입니다.',
|
|
83
83
|
candidate_id: '포착된 결정 후보 id입니다.',
|
|
@@ -153,7 +153,7 @@ const EN_FIELD_DESCRIPTIONS = {
|
|
|
153
153
|
ambient_mute: 'Hide due reminder lines during the session.',
|
|
154
154
|
premise_sync: 'When explicitly enabled, sync tracked premises with the account.',
|
|
155
155
|
due_only: 'Sync only records whose check date has arrived.',
|
|
156
|
-
import_settlements: 'Import results recorded on the web into the local
|
|
156
|
+
import_settlements: 'Import results recorded on the web into the local decision record.',
|
|
157
157
|
push_local: 'Retry local changes that have not reached the account.',
|
|
158
158
|
};
|
|
159
159
|
/** JSON Schema for tools/list, generated from the Zod source (drop $schema noise). */
|
package/dist/v2/logbook.js
CHANGED
|
@@ -98,7 +98,7 @@ export function renderLogbook(brief, repositoryId) {
|
|
|
98
98
|
if (brief.skipped_unknown > 0)
|
|
99
99
|
honesty.push(`미지 이벤트 ${brief.skipped_unknown}건 (신버전 기록, 데이터는 안전)`);
|
|
100
100
|
if (honesty.length > 0) {
|
|
101
|
-
out.push('##
|
|
101
|
+
out.push('## 기록 상태');
|
|
102
102
|
out.push('');
|
|
103
103
|
for (const h of honesty)
|
|
104
104
|
out.push(`- ${h}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argus-decision-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Argus decision-accountability MCP server — clarify a decision, save a falsifiable prediction, and record what reality did. The model never grades you.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|