sprag-cli 3.42.0 → 3.42.2
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.ko.md +86 -84
- package/README.md +86 -84
- package/bin/cli.js +51 -51
- package/package.json +1 -1
- package/src/advice.js +3 -3
- package/src/brief.js +2 -2
- package/src/commands/compact-window.js +9 -9
- package/src/commands/feedback.js +2 -2
- package/src/commands/install.js +7 -7
- package/src/commands/last.js +5 -5
- package/src/commands/mode.js +4 -4
- package/src/commands/route-scan.js +4 -4
- package/src/commands/seed.js +10 -10
- package/src/handoff.js +1 -1
- package/src/history.js +1 -1
- package/src/installer.js +21 -21
- package/src/korean-style.js +6 -2
- package/src/model-rules.js +2 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subcommand: compact-window — audit / pin Claude Code's `autoCompactWindow`.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* sprag compact-window # status
|
|
4
|
+
* sprag compact-window set --global # pin 500k in ~/.claude/settings.json
|
|
5
|
+
* sprag compact-window set --project # pin 500k in <root>/.claude/settings.json
|
|
6
|
+
* sprag compact-window set --global --value 600k
|
|
7
|
+
* sprag compact-window off | on # toggle the statusline warning
|
|
8
8
|
*
|
|
9
9
|
* Scope is deliberately explicit for `set`: writing a global settings.json is
|
|
10
10
|
* not something to guess at, and the non-TTY hook environment cannot prompt.
|
|
@@ -80,14 +80,14 @@ export async function run({ args, hasFlag }) {
|
|
|
80
80
|
console.log(ko
|
|
81
81
|
? ` 그 전까지 모든 요청이 전체 컨텍스트를 재과금합니다. 1M은 너무 크니 ${fmt(s.recommendedMin)}~${fmt(s.recommendedMax)} 범위를 권장합니다 (기본값 ${fmt(s.recommended)}, --value로 조절). 1M 창 자체는 그대로 두고 압축 시점만 앞당깁니다.`
|
|
82
82
|
: ` Until then every request re-bills the whole context. 1M is too large — pick something in ${fmt(s.recommendedMin)}–${fmt(s.recommendedMax)} (default ${fmt(s.recommended)}, override with --value). The 1M window itself stays.`);
|
|
83
|
-
console.log(`\n
|
|
84
|
-
console.log(`
|
|
85
|
-
console.log(`
|
|
83
|
+
console.log(`\n sprag compact-window set --global (~/.claude/settings.json, ${fmt(s.recommended)})`);
|
|
84
|
+
console.log(` sprag compact-window set --project (<root>/.claude/settings.json, ${fmt(s.recommended)})`);
|
|
85
|
+
console.log(` sprag compact-window set --global --value ${fmt(s.recommendedMax)}`);
|
|
86
86
|
console.log(ko ? ' (적용 범위는 사용자에게 먼저 확인할 것)' : ' (confirm the scope with the user first)');
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
console.error(`Unknown compact-window subcommand: ${sub}`);
|
|
91
|
-
console.error('Usage:
|
|
91
|
+
console.error('Usage: sprag compact-window [status|set --global|--project [--value 500k]|off|on]');
|
|
92
92
|
process.exit(1);
|
|
93
93
|
}
|
package/src/commands/feedback.js
CHANGED
|
@@ -25,13 +25,13 @@ import { join } from 'node:path';
|
|
|
25
25
|
import os from 'node:os';
|
|
26
26
|
import { debug } from '../debug.js';
|
|
27
27
|
|
|
28
|
-
const REPO = 'rootstudioyaml/
|
|
28
|
+
const REPO = 'rootstudioyaml/sprag';
|
|
29
29
|
const ISSUES_URL = `https://github.com/${REPO}/issues`;
|
|
30
30
|
|
|
31
31
|
// Anonymous submission endpoint (Google Form). A Google Form's formResponse
|
|
32
32
|
// URL accepts unauthenticated POSTs, which is exactly the property a
|
|
33
33
|
// login-free, GitHub-blocked-network path needs. Responses land in the
|
|
34
|
-
// maintainer's "
|
|
34
|
+
// maintainer's "sprag 피드백 (Feedback)" form (published
|
|
35
35
|
// 2026-09-13, responder access: anyone with the link).
|
|
36
36
|
// id — the /d/e/<id>/ segment of the form URL
|
|
37
37
|
// message — entry.NNNN field id of the message question
|
package/src/commands/install.js
CHANGED
|
@@ -49,7 +49,7 @@ export async function run({ hasFlag }) {
|
|
|
49
49
|
chosen = ko ? 'ko' : 'en';
|
|
50
50
|
}
|
|
51
51
|
setUserLanguage(chosen);
|
|
52
|
-
console.log(` language: set to ${chosen === 'ko' ? '한국어' : 'English'} — change it any time with \`
|
|
52
|
+
console.log(` language: set to ${chosen === 'ko' ? '한국어' : 'English'} — change it any time with \`sprag mode lang=${chosen === 'ko' ? 'en' : 'ko'}\``);
|
|
53
53
|
} else if (process.env.CTS_LANG) {
|
|
54
54
|
// Escape hatch for scripted installs, which cannot answer a prompt but
|
|
55
55
|
// do know which language the machine's user reads.
|
|
@@ -87,8 +87,8 @@ export async function run({ hasFlag }) {
|
|
|
87
87
|
? ' 교체하면 토큰·캐시·상한 경고가 statusline에 표시됩니다. 기존 설정은 사라집니다.'
|
|
88
88
|
: ' replacing it shows token/cache/cap warnings in the statusline; the current one is removed.');
|
|
89
89
|
const replace = await confirm(lang === 'ko'
|
|
90
|
-
? '
|
|
91
|
-
: ' Replace it with the
|
|
90
|
+
? ' sprag statusline으로 교체할까요?'
|
|
91
|
+
: ' Replace it with the sprag statusline?', { defaultValue: false });
|
|
92
92
|
if (replace) {
|
|
93
93
|
const { installStatusline } = await import('../installer.js');
|
|
94
94
|
s = installStatusline({ force: true });
|
|
@@ -336,8 +336,8 @@ export async function run({ hasFlag }) {
|
|
|
336
336
|
? ` seed: 추천 룰 ${pending.length}건이 대기 중입니다 (모델 피팅 + 랫쳇 프리셋).`
|
|
337
337
|
: ` seed: ${pending.length} recommended rule(s) are waiting (model-fitting + ratchet presets).`);
|
|
338
338
|
console.log(lang === 'ko'
|
|
339
|
-
? ' 다음 Claude Code 세션에서 한 건씩 등록할지 물어봅니다. 지금 보려면:
|
|
340
|
-
: ' the next Claude Code session asks about them one at a time. See them now:
|
|
339
|
+
? ' 다음 Claude Code 세션에서 한 건씩 등록할지 물어봅니다. 지금 보려면: sprag seed'
|
|
340
|
+
: ' the next Claude Code session asks about them one at a time. See them now: sprag seed');
|
|
341
341
|
}
|
|
342
342
|
} catch (e) {
|
|
343
343
|
debug('install:seed-offer', e); // optional feature; never fail install
|
|
@@ -352,7 +352,7 @@ export async function run({ hasFlag }) {
|
|
|
352
352
|
}
|
|
353
353
|
console.log('');
|
|
354
354
|
console.log(lang === 'ko'
|
|
355
|
-
? '버그 제보·기능 제안: https://github.com/rootstudioyaml/
|
|
356
|
-
: 'Bug reports & feature requests: https://github.com/rootstudioyaml/
|
|
355
|
+
? '버그 제보·기능 제안: https://github.com/rootstudioyaml/sprag/issues'
|
|
356
|
+
: 'Bug reports & feature requests: https://github.com/rootstudioyaml/sprag/issues');
|
|
357
357
|
return;
|
|
358
358
|
}
|
package/src/commands/last.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Designed for the auto-trigger skill so the user immediately sees
|
|
4
4
|
* "what just fired and how to fix it" without having to read the whole
|
|
5
5
|
* history file.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* sprag last # search last 1 day
|
|
7
|
+
* sprag last --days 7 # widen the lookback
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
|
|
@@ -113,7 +113,7 @@ export async function run({ numArg }) {
|
|
|
113
113
|
console.log('💡 ' + (lang === 'ko' ? CAP_TIPS.ko : CAP_TIPS.en));
|
|
114
114
|
console.log('');
|
|
115
115
|
console.log(lang === 'ko' ? '실행:' : 'Run:');
|
|
116
|
-
console.log('
|
|
116
|
+
console.log(' sprag handoff');
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
// Chip warning path: render full ISSUE_MESSAGES advice for each code,
|
|
@@ -121,8 +121,8 @@ export async function run({ numArg }) {
|
|
|
121
121
|
// the history.md format).
|
|
122
122
|
if (latest.codes.length === 0) {
|
|
123
123
|
console.log(lang === 'ko'
|
|
124
|
-
? '(진단 코드 없음 — 표 뷰를 열어보세요: `
|
|
125
|
-
: '(No diagnostic code attached — open the table view: `
|
|
124
|
+
? '(진단 코드 없음 — 표 뷰를 열어보세요: `sprag --days 1`)'
|
|
125
|
+
: '(No diagnostic code attached — open the table view: `sprag --days 1`)');
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
// Pick a single language per field; fall back to EN when KO is missing.
|
package/src/commands/mode.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subcommand: mode — persist statusline preferences so future runs pick
|
|
3
3
|
* them up without flags or wrapper edits.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* sprag mode # show current config
|
|
5
|
+
* sprag mode icon verbose # set icon + verbose
|
|
6
|
+
* sprag mode reset # clear back to defaults
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
|
|
@@ -28,7 +28,7 @@ export async function run({ args }) {
|
|
|
28
28
|
console.log(`Stored config file (${configPath()}):`);
|
|
29
29
|
console.log(` ${Object.keys(raw).length === 0 ? '(none — using defaults)' : JSON.stringify(raw)}`);
|
|
30
30
|
console.log('');
|
|
31
|
-
console.log('Change with:
|
|
31
|
+
console.log('Change with: sprag mode <keywords...>');
|
|
32
32
|
console.log(`Keywords: ${VALID_KEYWORDS.join(', ')}`);
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
@@ -303,13 +303,13 @@ export async function run({ args, hasFlag, numArg }) {
|
|
|
303
303
|
? [
|
|
304
304
|
`[sprag update] 새 버전이 나와 있습니다: v${u.current} → ${u.latest}.`,
|
|
305
305
|
'사용자에게 지금 업그레이드할지 물어보고, 승낙하면 아래 명령을 실행하십시오. 묻지 않고 설치하지는 마십시오.',
|
|
306
|
-
'
|
|
306
|
+
' sprag upgrade # 업그레이드 실행',
|
|
307
307
|
' sprag update-check --dismiss # 사용자가 원치 않으면 (다음 버전이 나올 때까지 다시 묻지 않습니다)',
|
|
308
308
|
].join('\n')
|
|
309
309
|
: [
|
|
310
310
|
`[sprag update] A newer version is available: v${u.current} → ${u.latest}.`,
|
|
311
311
|
'Ask the user whether to upgrade now, and run the command below only if they agree. Do not install without asking.',
|
|
312
|
-
'
|
|
312
|
+
' sprag upgrade # perform the upgrade',
|
|
313
313
|
' sprag update-check --dismiss # if they decline (stays quiet until a newer release)',
|
|
314
314
|
].join('\n');
|
|
315
315
|
}
|
|
@@ -366,8 +366,8 @@ export async function run({ args, hasFlag, numArg }) {
|
|
|
366
366
|
}
|
|
367
367
|
if (reviewRules.length > 0) {
|
|
368
368
|
lines.push(lang === 'ko'
|
|
369
|
-
? '[
|
|
370
|
-
: '[
|
|
369
|
+
? '[sprag rule-health] 사용자가 승인한 위임 룰 중, 위임 대상 유형의 최근 에러율이 기준(20%)을 넘어 재검토가 필요한 룰이 있습니다 — 사용자에게 브리핑하고 조건 좁히기/제거를 상의하세요:'
|
|
370
|
+
: '[sprag rule-health] Some user-approved delegation rules now exceed the 20% error-rate threshold for their delegated category — brief the user and discuss narrowing or removing them:');
|
|
371
371
|
for (const r of reviewRules) {
|
|
372
372
|
// Say WHICH signal tripped: a measured delegation failure rate is a
|
|
373
373
|
// much stronger claim than the shape-based proxy, and the user's
|
package/src/commands/seed.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subcommand: seed — register the bundled starter rules, one answer at a time.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* sprag seed # what is still pending
|
|
5
|
+
* sprag seed accept <id> --global # register one rule
|
|
6
|
+
* sprag seed accept <id> --project # ... into this project only
|
|
7
|
+
* sprag seed accept all --global # when the user says "all of them"
|
|
8
|
+
* sprag seed skip <id> | skip all # never offer it again
|
|
9
|
+
* sprag seed reset # make every preset pending again
|
|
10
10
|
*
|
|
11
11
|
* Scope is explicit on purpose, exactly as `harness promote` requires it: the
|
|
12
12
|
* hook environment is non-TTY, so the model has to ask the user and pass the
|
|
@@ -36,8 +36,8 @@ export async function run({ args, hasFlag }) {
|
|
|
36
36
|
const ids = args.slice(2).filter((a) => !a.startsWith('-'));
|
|
37
37
|
if (ids.length === 0) {
|
|
38
38
|
console.error(ko
|
|
39
|
-
? 'id를 지정하십시오 (목록:
|
|
40
|
-
: 'Pass an id (list them with `
|
|
39
|
+
? 'id를 지정하십시오 (목록: sprag seed). 전체는 `all`.'
|
|
40
|
+
: 'Pass an id (list them with `sprag seed`), or `all`.');
|
|
41
41
|
process.exit(1);
|
|
42
42
|
}
|
|
43
43
|
const pending = seed.pendingSeeds({ lang, root });
|
|
@@ -99,7 +99,7 @@ export async function run({ args, hasFlag }) {
|
|
|
99
99
|
if (pending.length > 0) {
|
|
100
100
|
console.log('');
|
|
101
101
|
console.log(ko
|
|
102
|
-
? '등록:
|
|
103
|
-
: 'register:
|
|
102
|
+
? '등록: sprag seed accept <id> --global|--project · 거절: seed skip <id>'
|
|
103
|
+
: 'register: sprag seed accept <id> --global|--project · decline: seed skip <id>');
|
|
104
104
|
}
|
|
105
105
|
}
|
package/src/handoff.js
CHANGED
|
@@ -70,7 +70,7 @@ function renderTemplate({ now, cwd, git, caps }) {
|
|
|
70
70
|
const lines = [];
|
|
71
71
|
lines.push(`# Handoff — ${ymd(now)} ${pad(now.getHours())}:${pad(now.getMinutes())}`);
|
|
72
72
|
lines.push('');
|
|
73
|
-
lines.push(`Generated by \`
|
|
73
|
+
lines.push(`Generated by \`sprag handoff\`.`);
|
|
74
74
|
lines.push('');
|
|
75
75
|
lines.push('## Context');
|
|
76
76
|
lines.push('');
|
package/src/history.js
CHANGED
|
@@ -306,7 +306,7 @@ export function recordCapTransition(window) {
|
|
|
306
306
|
|
|
307
307
|
/**
|
|
308
308
|
* Record a handoff write — invoked by the `handoff` subcommand so
|
|
309
|
-
* `
|
|
309
|
+
* `sprag history` shows when work was backed up to a HANDOFF file.
|
|
310
310
|
*
|
|
311
311
|
* @param {string} filePath
|
|
312
312
|
* @returns {boolean}
|
package/src/installer.js
CHANGED
|
@@ -22,19 +22,19 @@ const STATUSLINE_REFRESH_INTERVAL = 5;
|
|
|
22
22
|
|
|
23
23
|
const SKILL_BODY = `---
|
|
24
24
|
name: claude-token-saver
|
|
25
|
-
description: Use when the user mentions Claude Code token usage, prompt cache hit rate, TTL/expiry, the 1M context window, cache misses, output spikes, rate-limit caps (5h/7d), or anything in the statusline produced by
|
|
25
|
+
description: Use when the user mentions Claude Code token usage, prompt cache hit rate, TTL/expiry, the 1M context window, cache misses, output spikes, rate-limit caps (5h/7d), or anything in the statusline produced by sprag (chips like "🚨 5H 94%", "🚨 7D 92%", "⚠ Ctx 500k+", "⚠ Input spike", "⚠ Cache miss", "⚠ 5m TTL", "⚠ Rebuild churn", "⚠ Output heavy", "⚠ Call surge", "⏳ Cache expires", "💰 Cache saved", "🧠 Cache hit"). Also use when they ask to view token-usage history, want to understand a warning they just saw, or want to back up work before a session cap with \`sprag handoff\`.
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
#
|
|
28
|
+
# sprag — Claude Code Token Monitor
|
|
29
29
|
|
|
30
|
-
This skill helps users interpret and act on the \`
|
|
30
|
+
This skill helps users interpret and act on the \`sprag\` statusline
|
|
31
31
|
in Claude Code. The statusline updates every ~1s and shows cache health, TTL
|
|
32
32
|
countdown, savings, and (when relevant) a leading warning chip.
|
|
33
33
|
|
|
34
34
|
## Response language
|
|
35
35
|
|
|
36
36
|
Respond in the user's configured output language. Run
|
|
37
|
-
\`
|
|
37
|
+
\`sprag mode\` once at the start of the session and read the
|
|
38
38
|
\`Output language\` field — if it shows \`language: ko\`, write **all of your
|
|
39
39
|
prose to the user in Korean** (summary, "All clear" status lines, headings,
|
|
40
40
|
recommendations). If it shows \`language: en\` (the default), write in
|
|
@@ -52,7 +52,7 @@ honor that for the rest of the turn without changing the saved setting.
|
|
|
52
52
|
"when did this start happening", or similar.
|
|
53
53
|
- The user is approaching a rate-limit cap and wants to back up the current
|
|
54
54
|
work so a fresh session can continue (point them at
|
|
55
|
-
\`
|
|
55
|
+
\`sprag handoff\`).
|
|
56
56
|
- The user wants to see the token-usage history file or asks for a summary
|
|
57
57
|
of recent warnings.
|
|
58
58
|
- The user asks for a quick token report or "current state" check (the
|
|
@@ -62,16 +62,16 @@ honor that for the rest of the turn without changing the saved setting.
|
|
|
62
62
|
## What to do
|
|
63
63
|
|
|
64
64
|
1. **Lead with the most recent warning + how to handle it.** Run
|
|
65
|
-
\`
|
|
65
|
+
\`sprag last\` first. It returns the most recent warning event
|
|
66
66
|
(chip + detail + timestamp) plus the full advice block for it. Surface that
|
|
67
67
|
to the user before anything else — this is what they came for.
|
|
68
68
|
2. **Identify the chip.** If the user pasted a statusline (instead of relying
|
|
69
69
|
on \`last\`), pull out the leading \`⚠ ...\` chip. That maps to a specific
|
|
70
70
|
issue category.
|
|
71
|
-
3. **Show recent history.** Run \`
|
|
71
|
+
3. **Show recent history.** Run \`sprag history\` (default last 7
|
|
72
72
|
days) to see the chronology of warning transitions. Each entry is timestamped,
|
|
73
73
|
bilingual (English line + 한국어), and includes a \`💡\` action tip inline.
|
|
74
|
-
4. **Drill down on the live state.** Run \`
|
|
74
|
+
4. **Drill down on the live state.** Run \`sprag --days 1\` (or
|
|
75
75
|
another window) to render the full table view, which lists per-session
|
|
76
76
|
spikes and recommended actions.
|
|
77
77
|
5. **Explain the warning** in plain language. Use the chip → cause table:
|
|
@@ -94,7 +94,7 @@ honor that for the rest of the turn without changing the saved setting.
|
|
|
94
94
|
that is expected, not a failure of this tool.
|
|
95
95
|
|
|
96
96
|
6. **Suggest the next action.** For \`🚨 5H/7D\` chips, recommend running
|
|
97
|
-
\`
|
|
97
|
+
\`sprag handoff\` to back up the current work to a
|
|
98
98
|
\`HANDOFF-*.md\` file before the cap hits, then continue in a fresh
|
|
99
99
|
session. For \`⚠ Ctx 500k+\`, recommend \`/compact\` or \`/clear\` and
|
|
100
100
|
checking what is pinned into context. For
|
|
@@ -103,18 +103,18 @@ honor that for the rest of the turn without changing the saved setting.
|
|
|
103
103
|
|
|
104
104
|
## Useful commands
|
|
105
105
|
|
|
106
|
-
- \`
|
|
107
|
-
- \`
|
|
108
|
-
- \`
|
|
109
|
-
- \`
|
|
110
|
-
- \`
|
|
106
|
+
- \`sprag last\` — most recent warning + full advice (start here).
|
|
107
|
+
- \`sprag last --days 7\` — widen the lookback window.
|
|
108
|
+
- \`sprag\` — full table report (default last 1 day).
|
|
109
|
+
- \`sprag --days 7\` — wider window.
|
|
110
|
+
- \`sprag history\` — recent warning transitions per day, with
|
|
111
111
|
inline \`💡\` action tips.
|
|
112
|
-
- \`
|
|
113
|
-
- \`
|
|
112
|
+
- \`sprag history --days 30\` — longer history.
|
|
113
|
+
- \`sprag handoff\` — write a HANDOFF-*.md template in cwd
|
|
114
114
|
capturing git status + cap snapshot, so a fresh session can resume cleanly.
|
|
115
|
-
- \`
|
|
116
|
-
- \`
|
|
117
|
-
- \`
|
|
115
|
+
- \`sprag mode\` — show statusline preferences.
|
|
116
|
+
- \`sprag mode icon verbose 1d\` — change preferences.
|
|
117
|
+
- \`sprag feedback "<message>"\` — file a bug report or feature
|
|
118
118
|
request for this tool right from the session (tries the gh CLI, then an
|
|
119
119
|
anonymous no-login submission, then saves locally with a prefilled GitHub
|
|
120
120
|
issue URL; \`--anonymous\` skips the gh path).
|
|
@@ -163,7 +163,7 @@ export function removeLegacyCommand() {
|
|
|
163
163
|
|
|
164
164
|
// Registers/repairs the Claude Code statusLine entry in ~/.claude/settings.json.
|
|
165
165
|
// - No statusLine yet: insert ours with refreshInterval:STATUSLINE_REFRESH_INTERVAL.
|
|
166
|
-
// - statusLine already points at
|
|
166
|
+
// - statusLine already points at sprag: ensure that refreshInterval
|
|
167
167
|
// (this is the bit that makes the TTL countdown tick every second while idle).
|
|
168
168
|
// - statusLine points at a different command: leave it alone unless --force.
|
|
169
169
|
export function installStatusline({ force = false } = {}) {
|
|
@@ -219,7 +219,7 @@ export function installStatusline({ force = false } = {}) {
|
|
|
219
219
|
|
|
220
220
|
// Registers the SessionStart hook that surfaces route-scan delegation
|
|
221
221
|
// candidates as session context (startup + /clear). Idempotent: skips when a
|
|
222
|
-
//
|
|
222
|
+
// sprag route-scan hook is already present; never touches other
|
|
223
223
|
// hooks the user configured.
|
|
224
224
|
const ROUTE_SCAN_HOOK_COMMAND = 'claude-token-saver route-scan --hook';
|
|
225
225
|
|
package/src/korean-style.js
CHANGED
|
@@ -67,9 +67,13 @@ export function koreanStyleDecided(cfg = loadConfig()) {
|
|
|
67
67
|
* locale variables, then (macOS only, where those are routinely unset) the
|
|
68
68
|
* system locale.
|
|
69
69
|
*/
|
|
70
|
-
export function koreanLocaleDetected({ env = process.env, platform = process.platform } = {}) {
|
|
70
|
+
export function koreanLocaleDetected({ env = process.env, platform = process.platform, cfg } = {}) {
|
|
71
71
|
try {
|
|
72
|
-
|
|
72
|
+
// The saved language answer only applies to the live process environment.
|
|
73
|
+
// A caller that injects a synthetic `env` (tests, simulations) is asking
|
|
74
|
+
// about that environment, not about this machine's recorded choice.
|
|
75
|
+
const c = cfg !== undefined ? cfg : (env === process.env ? loadConfig() : null);
|
|
76
|
+
if (c && c.language === 'ko') return true;
|
|
73
77
|
} catch { /* unreadable config falls through to the env checks */ }
|
|
74
78
|
const posix = [env.LC_ALL, env.LC_MESSAGES, env.LANG, env.LANGUAGE].filter(
|
|
75
79
|
(v) => typeof v === 'string' && v.trim() && v !== 'C' && v !== 'POSIX',
|
package/src/model-rules.js
CHANGED
|
@@ -198,7 +198,7 @@ export function removeModelRule(index1) {
|
|
|
198
198
|
export function renderModelRatchet(rules, lang = userLanguage()) {
|
|
199
199
|
const ko = lang === 'ko';
|
|
200
200
|
const lines = ko ? [
|
|
201
|
-
'# Model-Fitting Ratchet (
|
|
201
|
+
'# Model-Fitting Ratchet (sprag 자동 관리)',
|
|
202
202
|
'',
|
|
203
203
|
'로그 기반 티어 위임 룰. 이 파일은 route-scan이 매 스캔마다 통째로 재생성하므로',
|
|
204
204
|
'직접 수정하지 마세요 — 목록/제거: `sprag route-scan rules [rm <N>]`.',
|
|
@@ -245,7 +245,7 @@ export function renderModelRatchet(rules, lang = userLanguage()) {
|
|
|
245
245
|
'## Rules',
|
|
246
246
|
'',
|
|
247
247
|
] : [
|
|
248
|
-
'# Model-Fitting Ratchet (managed by
|
|
248
|
+
'# Model-Fitting Ratchet (managed by sprag)',
|
|
249
249
|
'',
|
|
250
250
|
'Log-derived tier delegation rules. route-scan regenerates this file in full',
|
|
251
251
|
'on every scan — do not edit it by hand. List / remove with:',
|