tonedial 0.1.0 → 0.1.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.
@@ -61,7 +61,6 @@ const messages = {
61
61
  `Ejecuta tonedial use ${was} y guárdalo como ${tried}.`,
62
62
  noLatin: (name) => `«${name}»: no contiene letras latinas ni dígitos para el identificador`,
63
63
  nameTooLong: (given, cap) => `Nombre visible: ${given} caracteres · máximo ${cap}`,
64
- sparsity: (slug, count) => `${slug}: ${count} ejes cambiados · se recomiendan 3–7 (5±2). Menos extremos reducen conflictos`,
65
64
  replaced: (slug) => `${slug}: se reemplazó el preajuste existente`,
66
65
  imported: (slug, replaced) => `${slug}: ${replaced ? "reemplazado" : "importado"}`,
67
66
  unreadable: (path, reason) => `${path}\nNo se puede leer: ${reason}`,
@@ -86,7 +85,7 @@ const messages = {
86
85
  introduction: "Elige nombre, identificador, formas de trato y rol; después ajusta los doce ejes. Enter conserva el valor; \"\" borra un campo opcional. La aprobación final guarda y aplica todo el perfil.",
87
86
  name: "Nombre visible",
88
87
  slug: "Identificador (minúsculas, dígitos y guiones)",
89
- user: "Tu contexto o preferencias (hasta 200 caracteres)",
88
+ user: "Tu rol o contexto (hasta 200 caracteres)",
90
89
  agent: "Rol del agente (hasta 200 caracteres)",
91
90
  register: "Registro (auto, polite, plain)",
92
91
  safeword: "Palabra clave",
@@ -133,13 +132,13 @@ const messages = {
133
132
  addressNeedsPair: "address necesita ambos nombres: tonedial address <self name> <user name>. " +
134
133
  'Usa una cadena vacía en cada posición para borrarla. Sin argumentos en un terminal, se te preguntará.',
135
134
  askSelf: "¿Cómo debe llamarse el agente a sí mismo?",
135
+ rolesNeedsPair: 'persona necesita ambas descripciones: tonedial persona <rol del agente> <rol del usuario>. Usa "" para borrar una descripción o ejecútalo sin argumentos en una terminal.',
136
+ rolesIntroduction: 'Define el rol del agente y tu rol o contexto. Enter conserva el valor actual; "" borra el rol. Los cambios se aplican al terminar ambas respuestas.',
136
137
  askUser: "¿Cómo debe llamarte?",
137
138
  addressKept: (current) => `actual ${current} · Enter lo conserva`,
138
139
  addressNone: "Sin definir · Enter lo mantiene así",
139
140
  age: (given, bands) => `persona.age=${given} · disponibles: ${bands.join(", ")}`,
140
141
  gender: (options) => `persona.gender · disponibles: ${options.join(", ")}`,
141
- noteOverCap: (given, cap) => `persona.note: ${given} caracteres · supera los ${cap} recomendados`,
142
- noteNamesAxis: (axes) => `persona.note se solapa con los ejes ${axes.join(", ")}. Los criterios de los ejes prevalecen en caso de conflicto.`,
143
142
  callsYou: (term) => `nombre del usuario ${term}`,
144
143
  callsItself: (term) => `nombre propio ${term}`,
145
144
  noteChars: (count) => `nota de ${count} caracteres`,
@@ -158,15 +157,12 @@ const messages = {
158
157
  register: (level) => `registro ${level}`,
159
158
  },
160
159
  artifact: {
161
- budget: (chars, cap) => `TONE.md ${chars} / ${cap}`,
160
+ size: (chars) => `TONE.md ${chars} caracteres`,
162
161
  wouldWrite: "se escribiría",
163
162
  wrote: "escrito",
164
- overCap: (chars, cap) => `TONE.md: ${chars} caracteres · supera el máximo de ${cap}`,
165
- overTarget: (chars, target) => `TONE.md: ${chars} caracteres · supera el objetivo de ${target}`,
166
163
  notWritten: "Falta TONE.md. Ejecuta tonedial compile",
167
164
  notSetUp: "Sin inicializar. Ejecuta tonedial init",
168
165
  movedFromDefault: "difiere del valor predeterminado de ToneDial",
169
- recompiled: (chars, cap) => `TONE.md ${chars.toLocaleString("es")} / ${cap.toLocaleString("es")}`,
170
166
  defaultMarker: "marca un eje distinto del valor predeterminado de ToneDial, no del tono nativo del agente.",
171
167
  riskMarker: "! riesgo",
172
168
  riskHeading: "Niveles de riesgo orientativos:",
@@ -259,14 +255,14 @@ const messages = {
259
255
  inspectScope: "Para seguir usando estas conexiones, inspecciona este ámbito:",
260
256
  disconnectScope: "Si ya no se necesitan, desconecta todos los agentes de este ámbito:",
261
257
  scope: "Ámbito de inspección: proyecto",
262
- toLookAt: (count) => `${count} requieren atención · --fix repara lo posible`,
258
+ toLookAt: (count) => `${count} ${count === 1 ? "comprobación requiere" : "comprobaciones requieren"} atención`,
263
259
  needsAPerson: "revisión manual necesaria · consulta los detalles anteriores",
264
260
  toneMatches: "coincide con config.json",
265
261
  toneNotWritten: "sin escribir",
266
262
  toneDisagrees: "difiere de config.json · edición directa o escritura interrumpida",
263
+ seedsHeading: "Archivos incluidos",
267
264
  seedsOk: (version) => `versión ${version}`,
268
265
  seedsNotRun: "sin archivos incluidos · aquí no se ha ejecutado init",
269
- seedsStale: (labels) => `${labels.length} necesitan actualizarse: ${labels.join(", ")}`,
270
266
  seedsAttention: "los archivos incluidos requieren atención",
271
267
  recoveryPending: "Hay una operación activa o pendiente de recuperación. No se cambió nada. Consulta los ID con tonedial doctor --json. Revierte con doctor --fix --rollback ID o reconstruye desde una operación válida detenida con doctor --fix --from-operation ID. Los propietarios activos o ambiguos siguen protegidos.",
272
268
  contextCurrent: "La estructura de AGENTS.md y TONE.md está al día.",
@@ -302,13 +298,12 @@ const messages = {
302
298
  rollbackAction: { applied: "restaurar", "already-reverted": "ya restaurado", changed: "cambiado · conservar", unsupported: "no admitido · conservar" },
303
299
  rollbackQuestion: "¿Restaurar la operación elegida?",
304
300
  seedReason: {
305
- missing: "falta · ejecuta init con los agentes necesarios",
306
- stale: "archivo incluido antiguo · revisa una actualización con init",
307
- modified: "modificado localmente · revisa antes de reemplazar",
308
- foreign: "No pertenece a ToneDial. Consérvalo y elige un directorio de estado exclusivo.",
309
- unreadable: "No se puede leer con seguridad. Comprueba la ruta y sus permisos.",
301
+ missing: "Falta un archivo incluido",
302
+ stale: "Actualización de archivo incluido disponible",
303
+ modified: "Modificado localmente · revisar antes de reemplazar",
304
+ foreign: "No gestionado por ToneDial · conservado",
305
+ unreadable: "No se puede leer con seguridad · comprobar ruta y permisos",
310
306
  },
311
- seedsBehind: (had, has) => `versión local ${had} · versión del paquete ${has}. Actualizar npm no renueva los archivos locales existentes`,
312
307
  skillLinked: "enlazado a la copia incluida",
313
308
  skillCopied: "copiado · la plataforma no admite enlaces",
314
309
  skillForeign: (path) => `${path}: no lo instaló ToneDial; no se reemplazará`,
@@ -325,9 +320,7 @@ const messages = {
325
320
  },
326
321
  hookSettingScope: "El estado del hook solo procede del archivo inspeccionado; no se verificaron las anulaciones del cliente ni la entrega a la sesión.",
327
322
  hookGroupHeading: "Hooks de agentes",
328
- hookGroupUnknown: (tools) => `No se pudo confirmar la activación de los hooks de: ${tools.join(", ")}.`,
329
- hookGroupMissing: "No hay hooks de ToneDial gestionados para estos agentes en este ámbito.",
330
- hookGroupAction: "Para conectar ToneDial, ejecuta init en este ámbito y elige estos agentes.",
323
+ hookGroupUnknown: (tools) => `Sin conectar: ${tools.join(", ")}.`,
331
324
  hookNotConnected: "No hay un hook gestionado que inspeccionar. Para conectar, ejecuta init en el mismo ámbito y elige este agente.",
332
325
  hookNeedsInspection: "Resuelve el problema de ajustes o del programa del hook antes de comprobar su activación en la aplicación.",
333
326
  hookGuidance: {
@@ -371,20 +364,32 @@ const messages = {
371
364
  "Busca el prefijo global: npm prefix -g\nAñade su directorio bin (macOS/Linux) a PATH.",
372
365
  },
373
366
  notice: {
374
- modelExpectation: "El modelo podría no producir el tono esperado.",
375
367
  riskIntro: "Para divertirse; no se recomienda en producción. Los tonos de riesgo pueden distorsionar juicios e informes con falsedades, omisiones o exageraciones. ! es una advertencia, no una probabilidad medida.",
376
368
  riskAxes: (axes) => `! ${axes.join(", ")} · ${[axes.some(axis => axis === "profanity" || axis === "critique") ? "lenguaje duro" : null, axes.some(axis => axis === "flattery" || axis === "conviction" || axis === "bravado") ? "juicios sesgados o informes exagerados" : null, axes.some(axis => axis === "compliance" || axis === "refusal") ? "acción precipitada o rechazo" : null].filter(Boolean).join("; ")}`,
377
- personaUnanchored: "La personalidad no tiene criterios fijos; prevalecen los ejes. El texto puede afectar al contenido. " +
378
- "Interpretar un rol no verifica credenciales ni concede permisos.",
379
369
  roleplay: "Un playfulness alto pide expresiones frecuentes y exageradas, como «su humilde servidor» o «sacar esa función de las cuentas». Pueden sonar groseras o violentas; ToneDial no las filtra.",
380
370
  risk: "para divertirse; no se recomienda en producción",
381
371
  },
382
372
  update: {
383
373
  running: (version) => `tonedial ${version}`,
384
- installedBy: (shape) => `método de instalación ${shape}`,
385
- toUpdate: "para actualizar:",
386
- thenRefresh: "después comprueba y reconstruye los archivos conservando los ajustes:",
387
- neverInitialised: "init no ejecutado · sin archivos locales que actualizar",
374
+ toUpdate: "Actualización del paquete:",
375
+ thenRefresh: "Actualizar los archivos de la aplicación:",
376
+ setupNeeded: "Configurar ToneDial:",
377
+ refreshFiles: (count) => `Archivos incluidos con actualizaciones: ${count}`,
378
+ reviewState: "Inspeccionar los archivos afectados:",
379
+ npmQuestion: " ¿Ejecutar esta actualización de npm?",
380
+ npmComplete: (version) => `Actualización de npm completada · instalado ${version}`,
381
+ npmMissing: "No se encontró npm en PATH. Usa la instalación de Node/npm que gestiona esta copia de ToneDial.",
382
+ npmScopeUnknown: "No se puede verificar el directorio global de npm. Comprueba npm prefix -g y npm root -g antes de reintentar.",
383
+ npmScopeMismatch: "Esta copia de ToneDial no es el paquete global gestionado por el npm seleccionado. Usa la instalación de Node/npm correspondiente. No se ejecutó la actualización.",
384
+ npmFailed: "La actualización de npm falló. Comprueba los permisos y el registro, y ejecuta el comando mostrado para ver el diagnóstico de npm.",
385
+ versionUnknown: "No se pudo verificar la versión instalada de ToneDial. Comprueba la instalación del paquete antes de reintentar.",
386
+ stateIssue: {
387
+ missing: "Faltan los ajustes guardados.",
388
+ unsafe: "No se pueden leer los ajustes con seguridad. Comprueba los enlaces y los tipos de archivo.",
389
+ changed: "Los ajustes cambiaron durante la inspección. Reintenta cuando terminen los cambios.",
390
+ invalid: "Los ajustes guardados no son válidos.",
391
+ unreadable: "No se pudo leer el estado de la aplicación. Comprueba la ruta y los permisos.",
392
+ },
388
393
  fetching: (registry) => `consultando · ${registry}`,
389
394
  found: (version, bytes) => `${version}, ${bytes.toLocaleString("es")} bytes`,
390
395
  already: (version) => `${version} ya está instalado`,
@@ -392,11 +397,10 @@ const messages = {
392
397
  question: (version) => ` ¿Reemplazar esta instalación por ${version}?`,
393
398
  replaced: (version) => `actualizado · ${version}`,
394
399
  declined: "cancelado · se conserva la instalación existente",
395
- onlyCurl: (shape) => `instalación de ${shape} · usa su método de actualización`,
396
400
  noTar: "La actualización necesita tar, pero no está en PATH",
397
401
  notAPackage: "La descarga no es un paquete de ToneDial",
398
402
  linkInPackage: "La publicación contiene un enlace simbólico, innecesario en los archivos publicados",
399
- needsApproval: "Reemplazar la instalación requiere aprobación y no hay terminal. Repite con --auto.",
403
+ needsApproval: "La actualización requiere aprobación y no se ha ejecutado. Ejecuta tonedial update --auto para aprobarla.",
400
404
  integrityMismatch: "El hash de la descarga no coincide con el del registro",
401
405
  notOurs: (dir) => `${dir}: no lo creó ToneDial; elimínalo manualmente`,
402
406
  swapFailed: (reason) => `Instalación detenida: ${reason}. Revisa la recuperación antes de reintentar.`,
@@ -413,8 +417,9 @@ const messages = {
413
417
  init: "configurar y actualizar archivos incluidos",
414
418
  set: "cambiar ejes, rol o ajustes · sin argumentos abre el dial",
415
419
  address: "definir los nombres de ambas partes · sin argumentos pregunta",
420
+ persona: "definir roles del agente y usuario · sin argumentos pregunta",
416
421
  reset: "restablecer un eje · sin argumentos restablece todos",
417
- show: "ajustes actuales · con identificador previsualiza lo guardado",
422
+ show: "ajustes actuales · con identificador previsualiza un perfil guardado",
418
423
  test: "probar los ajustes o un preajuste en una conversación nueva",
419
424
  save: "guardar el tono actual como perfil",
420
425
  create: "crear y aplicar un preajuste · sin argumentos guía la configuración",
@@ -459,14 +464,8 @@ const messages = {
459
464
  },
460
465
  combos: {
461
466
  contradiction: (rule) => `${rule} se contradice.`,
462
- reads: (rule) => `${rule}:`,
463
467
  refusalCompliance: "Un eje pide declarar una negativa; el otro, actuar sin comentarios. Reduce uno de los dos.",
464
- formalSelfRef: "El lenguaje ceremonial contrasta con un nombre propio familiar.",
465
- casualUserRef: "El lenguaje familiar contrasta con una forma de trato honorífica.",
466
- teensFormal: "Una personalidad adolescente con lenguaje ceremonial puede sonar teatral.",
467
- seniorJuniorSelfRef: "La edad y el nombre propio sugieren posiciones distintas.",
468
468
  nothingBlocked: "No se bloquea nada.",
469
- addressUnlikely: "Las respuestas breves o poco emotivas pueden omitir nombres; un rol intenso puede usarlos más.",
470
469
  },
471
470
  errors: {
472
471
  notACommand: (name, known, nearest) => `${name} no es un comando.${nearest ? ` ¿Querías decir ${nearest}?` : ""} ` +
@@ -628,7 +627,7 @@ export const es = {
628
627
  "persona.gender": "género que puede asociar el modelo",
629
628
  "persona.self_ref": "cómo se llama el agente a sí mismo",
630
629
  "persona.user_ref": "cómo llama el agente al usuario",
631
- "persona.note": "rol que los ejes no expresan · avisa al superar 200 caracteres",
630
+ "persona.note": "rol o manera de hablar que los ejes no expresan",
632
631
  "persona.user": "contexto del usuario · máximo 200 caracteres",
633
632
  "persona.agent": "rol ficticio del agente · máximo 200 caracteres · credenciales sin verificar; no concede capacidad ni permisos",
634
633
  },
@@ -61,7 +61,6 @@ const messages = {
61
61
  `tonedial use ${was} を実行し、${tried} として保存してください。`,
62
62
  noLatin: (name) => `「${name}」: スラッグに使える英字か数字がありません`,
63
63
  nameTooLong: (given, cap) => `表示名:${given}文字 · 上限 ${cap}`,
64
- sparsity: (slug, count) => `${slug}: 変更軸 ${count}個 · 推奨3–7(5±2)。極端な値が少ないほど競合を抑えられます`,
65
64
  replaced: (slug) => `${slug}: 既存プリセットを置き換えました`,
66
65
  imported: (slug, replaced) => `${slug}: ${replaced ? "置き換えました" : "読み込みました"}`,
67
66
  unreadable: (path, reason) => `${path}\n読み取れません:${reason}`,
@@ -86,7 +85,7 @@ const messages = {
86
85
  introduction: "プロファイル名、スラッグ、呼称、役割を選び、12個の軸を調整します。Enterで表示値を保持し、\"\"で任意項目を消去します。最後の承認で全設定を保存・適用します。",
87
86
  name: "表示名",
88
87
  slug: "スラッグ(英小文字・数字・ハイフン)",
89
- user: "あなたの背景や希望(200文字まで)",
88
+ user: "あなたの役割や背景(200文字まで)",
90
89
  agent: "エージェントの役割(200文字まで)",
91
90
  register: "敬語区分(auto, polite, plain)",
92
91
  safeword: "合言葉",
@@ -133,13 +132,13 @@ const messages = {
133
132
  addressNeedsPair: "address には両方の呼称が必要です:tonedial address <self name> <user name>。" +
134
133
  '各位置に空文字列を指定すると消去できます。ターミナルでは引数なしで実行すると入力できます。',
135
134
  askSelf: "エージェントは自分をどう呼びますか?",
135
+ rolesNeedsPair: 'persona には両方の説明が必要です: tonedial persona <エージェントの役割> <ユーザーの役割>。消す項目には "" を指定してください。端末では引数なしで対話入力できます。',
136
+ rolesIntroduction: 'エージェントの役割と、あなたの役割や背景を設定します。Enter で現在の値を維持し、"" で役割を消去します。両方の入力が終わってからまとめて適用します。',
136
137
  askUser: "あなたをどう呼びますか?",
137
138
  addressKept: (current) => `現在 ${current} · Enterで保持`,
138
139
  addressNone: "未設定 · Enterで未設定のまま保持",
139
140
  age: (given, bands) => `persona.age=${given} · 選択肢:${bands.join(", ")}`,
140
141
  gender: (options) => `persona.gender · 選択肢:${options.join(", ")}`,
141
- noteOverCap: (given, cap) => `persona.note: ${given}文字 · 推奨上限 ${cap} を超えています`,
142
- noteNamesAxis: (axes) => `persona.note が ${axes.join(", ")} 軸と重複しています。軸には基準文があり、競合時は軸が優先されます。`,
143
142
  callsYou: (term) => `ユーザー呼称 ${term}`,
144
143
  callsItself: (term) => `自称 ${term}`,
145
144
  noteChars: (count) => `メモ ${count}文字`,
@@ -158,15 +157,12 @@ const messages = {
158
157
  register: (level) => `敬語区分 ${level}`,
159
158
  },
160
159
  artifact: {
161
- budget: (chars, cap) => `TONE.md ${chars} / ${cap}`,
160
+ size: (chars) => `TONE.md ${chars}文字`,
162
161
  wouldWrite: "書き込み予定",
163
162
  wrote: "書き込み済み",
164
- overCap: (chars, cap) => `TONE.md: ${chars}文字 · 上限 ${cap} を超えています`,
165
- overTarget: (chars, target) => `TONE.md: ${chars}文字 · 目標 ${target} を超えています`,
166
163
  notWritten: "TONE.md がありません。tonedial compile を実行してください",
167
164
  notSetUp: "未初期化です。tonedial init を実行してください",
168
165
  movedFromDefault: "ToneDialの既定値と異なります",
169
- recompiled: (chars, cap) => `TONE.md ${chars.toLocaleString("ja")} / ${cap.toLocaleString("ja")}`,
170
166
  defaultMarker: "ToneDialの既定値と異なる軸を示します。エージェント本来の口調との比較ではありません。",
171
167
  riskMarker: "! 要注意",
172
168
  riskHeading: "注意が必要なレベル(参考):",
@@ -259,14 +255,14 @@ const messages = {
259
255
  inspectScope: "引き続き使う場合は、この範囲を確認してください:",
260
256
  disconnectScope: "不要なら、この範囲の全エージェントの接続を解除してください:",
261
257
  scope: "確認範囲:プロジェクト",
262
- toLookAt: (count) => `${count}件が要確認 · --fix で可能な修復を実施`,
258
+ toLookAt: (count) => `確認が必要:${count}件`,
263
259
  needsAPerson: "手動確認が必要 · 上の詳細を参照",
264
260
  toneMatches: "config.json と一致",
265
261
  toneNotWritten: "未書き込み",
266
262
  toneDisagrees: "config.json と不一致 · 直接編集か書き込み中断",
263
+ seedsHeading: "同梱ファイル",
267
264
  seedsOk: (version) => `バージョン ${version}`,
268
265
  seedsNotRun: "同梱ファイルなし · ここでは init 未実行",
269
- seedsStale: (labels) => `更新が必要:${labels.length}件 · ${labels.join(", ")}`,
270
266
  seedsAttention: "同梱ファイルの確認が必要",
271
267
  recoveryPending: "実行中または復旧待ちの操作があります。変更はしていません。tonedial doctor --json でIDを確認してください。記録済みの復元は doctor --fix --rollback ID、停止済みの有効な操作からの再構築は doctor --fix --from-operation ID を使います。実行中または所有者不明の操作は保護されます。",
272
268
  contextCurrent: "AGENTS.md と TONE.md の構成は最新です。",
@@ -302,13 +298,12 @@ const messages = {
302
298
  rollbackAction: { applied: "復元", "already-reverted": "復元済み", changed: "変更あり · 保持", unsupported: "未対応 · 保持" },
303
299
  rollbackQuestion: "選択した操作を復元しますか?",
304
300
  seedReason: {
305
- missing: "不足 · 必要なエージェントを選んで init を実行",
306
- stale: "古い同梱ファイル · init による更新を確認",
307
- modified: "ローカル変更あり · 置換前に変更を確認",
308
- foreign: "ToneDialの所有ではありません。保持し、専用の状態ディレクトリを選んでください。",
309
- unreadable: "安全に読み取れません。パスと権限を確認してください。",
301
+ missing: "同梱ファイルなし",
302
+ stale: "同梱ファイルの更新あり",
303
+ modified: "ローカルで変更済み · 置換前に確認",
304
+ foreign: "ToneDialの管理対象外 · 保持",
305
+ unreadable: "安全に読み取れません · パスと権限を確認",
310
306
  },
311
- seedsBehind: (had, has) => `ホームの同梱版 ${had} · パッケージ版 ${has}。npm更新では既存のホームファイルは更新されません`,
312
307
  skillLinked: "同梱コピーへのリンクあり",
313
308
  skillCopied: "コピー済み · この環境はリンク非対応",
314
309
  skillForeign: (path) => `${path}: ToneDialがインストールしたものではないため置き換えません`,
@@ -325,9 +320,7 @@ const messages = {
325
320
  },
326
321
  hookSettingScope: "フック状態は確認対象の設定ファイルのみから取得します。ホスト側の上書きとセッションへの配信は未検証です。",
327
322
  hookGroupHeading: "エージェントのフック",
328
- hookGroupUnknown: (tools) => `フックの有効状態を確認できません:${tools.join(", ")}。`,
329
- hookGroupMissing: "この範囲には、これらのエージェント用の管理対象フックが登録されていません。",
330
- hookGroupAction: "ToneDialを接続するには、この範囲で init を実行し、これらのエージェントを選んでください。",
323
+ hookGroupUnknown: (tools) => `未接続:${tools.join(", ")}`,
331
324
  hookNotConnected: "確認する管理対象フックがありません。接続するには同じ範囲でこのエージェントを選んで init を実行してください。",
332
325
  hookNeedsInspection: "アプリで有効状態を確認する前に、報告されたフック設定かプログラムの問題を解決してください。",
333
326
  hookGuidance: {
@@ -371,20 +364,32 @@ const messages = {
371
364
  "npm prefix -g でグローバルパスを確認し、\nその bin ディレクトリ(macOS/Linux)をPATHに追加してください。",
372
365
  },
373
366
  notice: {
374
- modelExpectation: "モデルによっては期待した口調にならない場合があります。",
375
367
  riskIntro: "娯楽用であり、実務での利用は推奨しません。注意が必要な口調では、虚偽・省略・誇張によって判断や作業報告が歪む可能性があります。! は参考の注意表示で、測定した確率ではありません。",
376
368
  riskAxes: (axes) => `! ${axes.join(", ")} · ${[axes.some(axis => axis === "profanity" || axis === "critique") ? "荒い表現" : null, axes.some(axis => axis === "flattery" || axis === "conviction" || axis === "bravado") ? "偏った判断・誇張した報告" : null, axes.some(axis => axis === "compliance" || axis === "refusal") ? "性急な実行・拒否" : null].filter(Boolean).join("; ")}`,
377
- personaUnanchored: "ペルソナには固定の基準文がなく、軸が優先されます。説明文は内容にも影響する場合があります。" +
378
- "役柄は資格の証明にも権限の付与にもなりません。",
379
369
  roleplay: "playfulness が高いと「畏れながら」「この関数、帳簿から消しましょうか」など役柄の言葉や隠語を頻繁に、大げさに使うよう求めます。無礼・粗暴に聞こえる場合があり、ToneDialはこうした表現を除外しません。",
380
370
  risk: "娯楽用です。実務利用は推奨しません",
381
371
  },
382
372
  update: {
383
373
  running: (version) => `tonedial ${version}`,
384
- installedBy: (shape) => `インストール方式 ${shape}`,
385
- toUpdate: "更新方法:",
386
- thenRefresh: "その後、保存済み設定を保持してアプリのファイルを確認・再構築してください:",
387
- neverInitialised: "init 未実行 · 更新するホームファイルなし",
374
+ toUpdate: "パッケージの更新:",
375
+ thenRefresh: "アプリのファイルを更新:",
376
+ setupNeeded: "ToneDialの初期設定:",
377
+ refreshFiles: (count) => `更新可能な同梱ファイル:${count}件`,
378
+ reviewState: "問題のあるアプリファイルを確認:",
379
+ npmQuestion: " npmで更新しますか?",
380
+ npmComplete: (version) => `npm更新完了 · インストール済み ${version}`,
381
+ npmMissing: "PATHにnpmがありません。このToneDialをインストールしたNode/npm環境を使用してください。",
382
+ npmScopeUnknown: "npmのグローバルインストール先を確認できません。npm prefix -g と npm root -g を確認して再試行してください。",
383
+ npmScopeMismatch: "このToneDialは選択したnpmが管理するグローバルパッケージではありません。対応するNode/npm環境を使用してください。更新は実行していません。",
384
+ npmFailed: "npmの更新に失敗しました。権限とレジストリ設定を確認し、表示されたコマンドを実行してnpmの診断を確認してください。",
385
+ versionUnknown: "インストールされたToneDialのバージョンを確認できません。パッケージの状態を確認して再試行してください。",
386
+ stateIssue: {
387
+ missing: "保存済み設定がありません。",
388
+ unsafe: "保存済み設定を安全に読み取れません。リンクとファイル形式を確認してください。",
389
+ changed: "確認中に保存済み設定が変更されました。変更が終わってから再試行してください。",
390
+ invalid: "保存済み設定が無効です。",
391
+ unreadable: "アプリの状態を読み取れません。パスとアクセス権を確認してください。",
392
+ },
388
393
  fetching: (registry) => `確認中 · ${registry}`,
389
394
  found: (version, bytes) => `${version}、${bytes.toLocaleString("ja")}バイト`,
390
395
  already: (version) => `${version} はインストール済みです`,
@@ -392,11 +397,10 @@ const messages = {
392
397
  question: (version) => ` このインストールを ${version} に置き換えますか?`,
393
398
  replaced: (version) => `更新済み · ${version}`,
394
399
  declined: "キャンセル · 既存インストールを保持",
395
- onlyCurl: (shape) => `${shape} 経由のインストール · その方式で更新してください`,
396
400
  noTar: "更新には tar が必要ですがPATHにありません",
397
401
  notAPackage: "ダウンロードしたものはToneDialパッケージではありません",
398
402
  linkInPackage: "リリースにシンボリックリンクがありますが、公開ファイルには不要です",
399
- needsApproval: "インストールの置換には承認が必要ですがターミナルがありません。--auto で再実行してください。",
403
+ needsApproval: "更新の承認が必要です。更新は実行していません。承認するには tonedial update --auto を実行してください。",
400
404
  integrityMismatch: "ダウンロードのハッシュがレジストリと一致しません",
401
405
  notOurs: (dir) => `${dir}: ToneDialが作成したものではありません。手動で削除してください`,
402
406
  swapFailed: (reason) => `インストール停止:${reason}。再試行前に復旧の詳細を確認してください。`,
@@ -413,8 +417,9 @@ const messages = {
413
417
  init: "初期設定と同梱ファイルの更新",
414
418
  set: "軸・役割・設定を変更 · 引数なしでダイヤル",
415
419
  address: "双方の呼称を設定 · 引数なしで質問",
420
+ persona: "エージェントとユーザーの役割を設定 · 引数なしで質問",
416
421
  reset: "軸を初期化 · 引数なしで全軸",
417
- show: "現在の設定 · スラッグ指定で保存値をプレビュー",
422
+ show: "現在の設定 · スラッグ指定で保存済みプロフィールをプレビュー",
418
423
  test: "新しい会話で現在の設定かプリセットを試す",
419
424
  save: "現在の口調をプロファイルに保存",
420
425
  create: "プリセットを作成・適用 · 引数なしで案内",
@@ -459,14 +464,8 @@ const messages = {
459
464
  },
460
465
  combos: {
461
466
  contradiction: (rule) => `${rule} は自己矛盾しています。`,
462
- reads: (rule) => `${rule}:`,
463
467
  refusalCompliance: "一方の軸は拒否の明示、他方は無言の即時実行を求めます。どちらかを下げてください。",
464
- formalSelfRef: "儀礼的な表現と親しい自称が対照的になります。",
465
- casualUserRef: "親しい表現と敬称が対照的になります。",
466
- teensFormal: "10代のペルソナに儀礼的な表現を合わせると芝居がかって聞こえる場合があります。",
467
- seniorJuniorSelfRef: "設定年齢と自称が異なる立場を示唆しています。",
468
468
  nothingBlocked: "ブロックはしていません。",
469
- addressUnlikely: "短い回答や感情の薄い回答では呼称が省かれる場合があります。役柄が強いほど頻出することもあります。",
470
469
  },
471
470
  errors: {
472
471
  notACommand: (name, known, nearest) => `${name} はコマンドではありません。${nearest ? `${nearest} のことですか?` : ""} ` +
@@ -628,7 +627,7 @@ export const ja = {
628
627
  "persona.gender": "モデルに連想させるジェンダー",
629
628
  "persona.self_ref": "エージェントの自称",
630
629
  "persona.user_ref": "エージェントが使うユーザーの呼称",
631
- "persona.note": "軸で表せない役割 · 200文字超で警告",
630
+ "persona.note": "軸で表せない役割や話し方",
632
631
  "persona.user": "ユーザーの背景 · 上限200文字",
633
632
  "persona.agent": "架空の役割 · 上限200文字 · 資格は未検証で、能力や権限は付与しません",
634
633
  },
@@ -61,7 +61,6 @@ const messages = {
61
61
  `请运行 tonedial use ${was},然后另存为 ${tried}。`,
62
62
  noLatin: (name) => `“${name}”:没有可用于标识名的拉丁字母或数字`,
63
63
  nameTooLong: (given, cap) => `显示名称:${given} 字符 · 上限 ${cap}`,
64
- sparsity: (slug, count) => `${slug}:${count} 个变更语气轴 · 建议 3–7(5±2)。极端值越少,冲突越少`,
65
64
  replaced: (slug) => `${slug}:已替换现有预设`,
66
65
  imported: (slug, replaced) => `${slug}:${replaced ? "已替换" : "已导入"}`,
67
66
  unreadable: (path, reason) => `${path}\n无法读取:${reason}`,
@@ -86,7 +85,7 @@ const messages = {
86
85
  introduction: "选择配置名称、标识名、称呼和角色,再调整全部十二个语气轴。Enter 保留显示值;\"\" 清空可选项。最终确认后保存并应用完整配置。",
87
86
  name: "显示名称",
88
87
  slug: "标识名(小写字母、数字、连字符)",
89
- user: "你的背景或偏好(最多 200 字符)",
88
+ user: "你的角色或背景(最多 200 字符)",
90
89
  agent: "代理角色(最多 200 字符)",
91
90
  register: "敬语形式(auto, polite, plain)",
92
91
  safeword: "安全词",
@@ -133,13 +132,13 @@ const messages = {
133
132
  addressNeedsPair: "address 需要两个称呼:tonedial address <self name> <user name>。" +
134
133
  '每个位置使用空字符串即可清空。在终端不带参数运行可交互输入。',
135
134
  askSelf: "代理如何自称?",
135
+ rolesNeedsPair: 'persona 需要两项描述:tonedial persona <代理角色> <用户角色>。用 "" 清除对应描述,也可在终端中不带参数交互输入。',
136
+ rolesIntroduction: '设置代理的角色,以及你的角色或背景。按 Enter 保留当前值,输入 "" 清除该角色。两项输入完成后统一应用。',
136
137
  askUser: "代理该如何称呼你?",
137
138
  addressKept: (current) => `当前 ${current} · Enter 保留`,
138
139
  addressNone: "当前未设置 · Enter 保持未设置",
139
140
  age: (given, bands) => `persona.age=${given} · 可选:${bands.join(", ")}`,
140
141
  gender: (options) => `persona.gender · 可选:${options.join(", ")}`,
141
- noteOverCap: (given, cap) => `persona.note:${given} 字符 · 超过建议上限 ${cap}`,
142
- noteNamesAxis: (axes) => `persona.note 与 ${axes.join(", ")} 语气轴重叠。语气轴有固定基准,冲突时优先。`,
143
142
  callsYou: (term) => `用户称呼 ${term}`,
144
143
  callsItself: (term) => `自称 ${term}`,
145
144
  noteChars: (count) => `备注 ${count} 字符`,
@@ -158,15 +157,12 @@ const messages = {
158
157
  register: (level) => `敬语形式 ${level}`,
159
158
  },
160
159
  artifact: {
161
- budget: (chars, cap) => `TONE.md ${chars} / ${cap}`,
160
+ size: (chars) => `TONE.md ${chars} 字符`,
162
161
  wouldWrite: "将写入",
163
162
  wrote: "已写入",
164
- overCap: (chars, cap) => `TONE.md:${chars} 字符 · 超过上限 ${cap}`,
165
- overTarget: (chars, target) => `TONE.md:${chars} 字符 · 超过目标 ${target}`,
166
163
  notWritten: "缺少 TONE.md,请运行 tonedial compile",
167
164
  notSetUp: "尚未初始化,请运行 tonedial init",
168
165
  movedFromDefault: "与 ToneDial 默认值不同",
169
- recompiled: (chars, cap) => `TONE.md ${chars.toLocaleString("zh")} / ${cap.toLocaleString("zh")}`,
170
166
  defaultMarker: "标记与 ToneDial 默认值不同的语气轴,不代表与代理原生语气的差异。",
171
167
  riskMarker: "! 风险语气",
172
168
  riskHeading: "风险等级提示:",
@@ -259,14 +255,14 @@ const messages = {
259
255
  inspectScope: "若要继续使用这些连接,请检查此范围:",
260
256
  disconnectScope: "若不再需要,请断开此范围内的所有代理:",
261
257
  scope: "检查范围:项目",
262
- toLookAt: (count) => `${count} 项需要处理 · --fix 修复可处理的问题`,
258
+ toLookAt: (count) => `${count} 项需要检查`,
263
259
  needsAPerson: "需要人工检查 · 参见上方详情",
264
260
  toneMatches: "与 config.json 一致",
265
261
  toneNotWritten: "未写入",
266
262
  toneDisagrees: "与 config.json 不同 · 可能被直接编辑或写入中断",
263
+ seedsHeading: "内置文件",
267
264
  seedsOk: (version) => `版本 ${version}`,
268
265
  seedsNotRun: "无内置文件 · 尚未在此运行 init",
269
- seedsStale: (labels) => `${labels.length} 项需要刷新:${labels.join(", ")}`,
270
266
  seedsAttention: "内置文件需要处理",
271
267
  recoveryPending: "有操作正在运行或需要恢复,未作任何修改。请用 tonedial doctor --json 查看 ID。已有回滚记录用 doctor --fix --rollback ID;已停止的有效操作可用 doctor --fix --from-operation ID 重建应用。运行中或所有者不明确的操作仍受保护。",
272
268
  contextCurrent: "AGENTS.md 与 TONE.md 布局已是最新。",
@@ -302,13 +298,12 @@ const messages = {
302
298
  rollbackAction: { applied: "恢复", "already-reverted": "已恢复", changed: "已更改 · 保留", unsupported: "不支持 · 保留" },
303
299
  rollbackQuestion: "恢复所选操作吗?",
304
300
  seedReason: {
305
- missing: "缺失 · 请选择所需代理并运行 init",
306
- stale: "旧版内置文件 · 请检查 init 刷新计划",
307
- modified: "本地已修改 · 替换前请检查变更",
308
- foreign: "不属于 ToneDial。请保留文件并选择专用状态目录。",
309
- unreadable: "无法安全读取,请检查路径及权限。",
301
+ missing: "内置文件缺失",
302
+ stale: "内置文件有更新",
303
+ modified: "本地已修改 · 替换前需检查",
304
+ foreign: "不由 ToneDial 管理 · 已保留",
305
+ unreadable: "无法安全读取 · 请检查路径和权限",
310
306
  },
311
- seedsBehind: (had, has) => `主目录内置文件版本 ${had} · 包版本 ${has}。npm 更新不会刷新主目录中的现有文件`,
312
307
  skillLinked: "已链接到内置副本",
313
308
  skillCopied: "已复制 · 平台不支持链接",
314
309
  skillForeign: (path) => `${path}:不是由 ToneDial 安装,因此不会替换`,
@@ -325,9 +320,7 @@ const messages = {
325
320
  },
326
321
  hookSettingScope: "钩子状态仅来自所检查的设置文件;主机覆盖项和会话注入尚未验证。",
327
322
  hookGroupHeading: "代理钩子",
328
- hookGroupUnknown: (tools) => `无法确认以下工具的钩子启用状态:${tools.join(", ")}。`,
329
- hookGroupMissing: "此范围内未为这些代理注册受管理的 ToneDial 钩子。",
330
- hookGroupAction: "要连接 ToneDial,请在此范围运行 init 并选择这些代理。",
323
+ hookGroupUnknown: (tools) => `未连接:${tools.join(", ")}`,
331
324
  hookNotConnected: "没有可检查的受管理钩子。要连接,请在同一范围运行 init 并选择此代理。",
332
325
  hookNeedsInspection: "在应用中检查启用状态前,请先解决报告的钩子设置或程序问题。",
333
326
  hookGuidance: {
@@ -371,20 +364,32 @@ const messages = {
371
364
  "运行 npm prefix -g 查找全局前缀,\n再将其 bin 目录(macOS/Linux)加入 PATH。",
372
365
  },
373
366
  notice: {
374
- modelExpectation: "模型可能无法呈现预期的语气。",
375
367
  riskIntro: "本工具用于娱乐,不建议用于生产工作。风险语气可能通过虚假、遗漏或夸张歪曲判断和工作报告。! 是风险提示,不是测得的概率。",
376
368
  riskAxes: (axes) => `! ${axes.join(", ")} · ${[axes.some(axis => axis === "profanity" || axis === "critique") ? "粗俗表达" : null, axes.some(axis => axis === "flattery" || axis === "conviction" || axis === "bravado") ? "偏颇判断或夸张报告" : null, axes.some(axis => axis === "compliance" || axis === "refusal") ? "仓促行动或拒绝" : null].filter(Boolean).join("; ")}`,
377
- personaUnanchored: "人设没有固定行为基准,语气轴优先。描述文字也可能影响内容。" +
378
- "角色扮演不验证资历,也不授予权限。",
379
369
  roleplay: "playfulness 较高时,会要求更频繁、夸张地使用“臣斗胆进言”“把这函数从账上划掉?”等角色用语和黑话。这些话可能显得无礼或粗暴,ToneDial 不会过滤。",
380
370
  risk: "仅供娱乐,不建议用于生产工作",
381
371
  },
382
372
  update: {
383
373
  running: (version) => `tonedial ${version}`,
384
- installedBy: (shape) => `安装方式 ${shape}`,
385
- toUpdate: "更新方法:",
386
- thenRefresh: "然后保留已保存的设置,检查并重建应用文件:",
387
- neverInitialised: "尚未运行 init · 无主目录文件需要刷新",
374
+ toUpdate: "更新软件包:",
375
+ thenRefresh: "更新应用文件:",
376
+ setupNeeded: "初始化 ToneDial:",
377
+ refreshFiles: (count) => `可更新的内置文件:${count} 个`,
378
+ reviewState: "检查有问题的应用文件:",
379
+ npmQuestion: " 使用 npm 更新吗?",
380
+ npmComplete: (version) => `npm 更新完成 · 已安装 ${version}`,
381
+ npmMissing: "PATH 中未找到 npm。请使用安装此 ToneDial 的 Node/npm 环境。",
382
+ npmScopeUnknown: "无法确认 npm 的全局安装目录。请检查 npm prefix -g 和 npm root -g 后重试。",
383
+ npmScopeMismatch: "当前 ToneDial 不是所选 npm 管理的全局软件包。请使用对应的 Node/npm 环境。未执行更新。",
384
+ npmFailed: "npm 更新失败。请检查权限和镜像设置,并直接运行显示的命令查看 npm 的诊断信息。",
385
+ versionUnknown: "无法确认安装的 ToneDial 版本。请检查软件包的安装状态后重试。",
386
+ stateIssue: {
387
+ missing: "保存的设置缺失。",
388
+ unsafe: "无法安全读取保存的设置。请检查链接和文件类型。",
389
+ changed: "检查期间保存的设置已更改。请等待更改完成后重试。",
390
+ invalid: "保存的设置无效。",
391
+ unreadable: "无法读取应用状态。请检查路径和权限。",
392
+ },
388
393
  fetching: (registry) => `正在检查 · ${registry}`,
389
394
  found: (version, bytes) => `${version},${bytes.toLocaleString("zh")} 字节`,
390
395
  already: (version) => `${version} 已安装`,
@@ -392,11 +397,10 @@ const messages = {
392
397
  question: (version) => ` 将此安装替换为 ${version} 吗?`,
393
398
  replaced: (version) => `已更新 · ${version}`,
394
399
  declined: "已取消 · 保留现有安装",
395
- onlyCurl: (shape) => `通过 ${shape} 安装 · 请使用对应方式更新`,
396
400
  noTar: "更新需要 tar,但 PATH 中未找到",
397
401
  notAPackage: "下载内容不是 ToneDial 包",
398
402
  linkInPackage: "发行包包含符号链接,但发布文件不应依赖链接",
399
- needsApproval: "替换安装需要批准,但当前没有终端。请使用 --auto 重新运行。",
403
+ needsApproval: "更新需要批准,尚未执行。请运行 tonedial update --auto 批准更新。",
400
404
  integrityMismatch: "下载哈希与仓库记录不一致",
401
405
  notOurs: (dir) => `${dir}:不是由 ToneDial 创建,请自行移除`,
402
406
  swapFailed: (reason) => `安装已停止:${reason}。重试前请检查恢复详情。`,
@@ -413,8 +417,9 @@ const messages = {
413
417
  init: "初始化并刷新内置文件",
414
418
  set: "修改语气轴、角色或设置 · 无参数打开面板",
415
419
  address: "设置双方称呼 · 无参数则交互输入",
420
+ persona: "设置代理和用户角色 · 无参数则交互输入",
416
421
  reset: "重置语气轴 · 无参数重置全部",
417
- show: "当前设置 · 指定标识名预览保存值",
422
+ show: "当前设置 · 指定标识名预览已保存的配置档案",
418
423
  test: "在新对话中试用当前设置或预设",
419
424
  save: "将当前语气保存为配置",
420
425
  create: "创建并应用预设 · 无参数则引导设置",
@@ -459,14 +464,8 @@ const messages = {
459
464
  },
460
465
  combos: {
461
466
  contradiction: (rule) => `${rule} 自相矛盾。`,
462
- reads: (rule) => `${rule}:`,
463
467
  refusalCompliance: "一个语气轴要求明确罢工,另一个要求不加评论立即执行。请降低其中一项。",
464
- formalSelfRef: "庄重措辞与亲近的自称形成反差。",
465
- casualUserRef: "亲近措辞与敬称形成反差。",
466
- teensFormal: "青少年人设搭配庄重措辞,可能显得戏剧化。",
467
- seniorJuniorSelfRef: "所设年龄和自称暗示不同地位。",
468
468
  nothingBlocked: "没有阻止任何设置。",
469
- addressUnlikely: "简短或感情淡薄的回答可能省略称呼;角色扮演较强时称呼可能更频繁。",
470
469
  },
471
470
  errors: {
472
471
  notACommand: (name, known, nearest) => `${name} 不是命令。${nearest ? `是否想输入 ${nearest}?` : ""} ` +
@@ -628,7 +627,7 @@ export const zh = {
628
627
  "persona.gender": "模型可能联想的性别",
629
628
  "persona.self_ref": "代理自称",
630
629
  "persona.user_ref": "代理对用户的称呼",
631
- "persona.note": "语气轴无法表达的角色 · 超过 200 字符会警告",
630
+ "persona.note": "语气轴无法表达的角色或表达方式",
632
631
  "persona.user": "用户背景 · 最多 200 字符",
633
632
  "persona.agent": "虚构代理角色 · 最多 200 字符 · 不验证资历,不授予能力或权限",
634
633
  },
@@ -11,7 +11,7 @@ import { captureRawEntry, caseRenameMatchesCurrent, isNoop, planChange, planEntr
11
11
  import { BUNDLED, builtinPresetDir, LEGACY_BUILTIN_SLUGS, RETIRED_PRESETS } from "./presets.js";
12
12
  import { SKILL_MD, SKILL_NAME, SKILL_TRAITS_MD } from "./skill.js";
13
13
  // Bump for changed generated content; freshness also checks each managed seed's bytes/provenance.
14
- export const SEED_VERSION = 15;
14
+ export const SEED_VERSION = 17;
15
15
  /** The state-root operating boundaries. The compiler owns the current tone separately. */
16
16
  export const GUIDE_MD = `${GUIDE_FORMAT_MARKER}
17
17
  ToneDial changes manner only; it never expands task scope or permissions.
@@ -73,10 +73,10 @@ export function seedFiles(paths, selection) {
73
73
  };
74
74
  const native = [
75
75
  reader,
76
- { id: "skill/body", version: 15, path: join(paths.skill, SKILL_NAME, "SKILL.md"), label: `skill/${SKILL_NAME}/SKILL.md`, contents: SKILL_MD },
76
+ { id: "skill/body", version: 17, path: join(paths.skill, SKILL_NAME, "SKILL.md"), label: `skill/${SKILL_NAME}/SKILL.md`, contents: SKILL_MD },
77
77
  {
78
78
  id: "skill/traits",
79
- version: 8,
79
+ version: 9,
80
80
  path: join(paths.skill, SKILL_NAME, "references", "traits.md"),
81
81
  label: `skill/${SKILL_NAME}/references/traits.md`,
82
82
  contents: SKILL_TRAITS_MD,