aptly 0.1.1 → 0.1.3

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.
@@ -0,0 +1,13 @@
1
+ export interface UpdateResult {
2
+ status: 'complete' | 'error';
3
+ codes: string[];
4
+ version?: string;
5
+ }
6
+ export interface UpdateDependencies {
7
+ nodePath?: string;
8
+ run?: (executable: string, args: readonly string[], timeout: number) => string;
9
+ }
10
+ /** Explicit global-only update. Never invokes a shell, PATH npm, setup, or an existing host launcher. */
11
+ export declare function updateGlobalInstallation(options: {
12
+ packageRoot: string;
13
+ }, dependencies?: UpdateDependencies): UpdateResult;
@@ -0,0 +1,68 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { lstatSync, readFileSync, realpathSync } from 'node:fs';
3
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
4
+ const failed = (code) => { throw new Error(code); };
5
+ const runNpm = (executable, args, timeout) => execFileSync(executable, [...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout, maxBuffer: 1024 * 1024, windowsHide: true });
6
+ const metadata = (root) => JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
7
+ const canonical = (path) => realpathSync(path);
8
+ function absoluteOutput(output) {
9
+ const path = output.trim();
10
+ if (!path || !isAbsolute(path) || /[\r\n\0]/.test(path))
11
+ failed('update_global_install_unverified');
12
+ return resolve(path);
13
+ }
14
+ function verifyPackage(root) {
15
+ const pkg = metadata(root);
16
+ if (pkg.name !== 'aptly' || typeof pkg.version !== 'string' || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(pkg.version) || pkg.bin?.aptly !== 'dist/bin/aptly.js')
17
+ failed('update_global_install_unverified');
18
+ const cli = join(root, 'dist', 'bin', 'aptly.js');
19
+ if (!lstatSync(cli).isFile() || canonical(cli) !== join(canonical(root), 'dist', 'bin', 'aptly.js'))
20
+ failed('update_global_install_unverified');
21
+ return pkg.version;
22
+ }
23
+ /** Explicit global-only update. Never invokes a shell, PATH npm, setup, or an existing host launcher. */
24
+ export function updateGlobalInstallation(options, dependencies = {}) {
25
+ let stage = 'update_global_install_unverified';
26
+ try {
27
+ const node = dependencies.nodePath ?? process.execPath, run = dependencies.run ?? runNpm;
28
+ if (!isAbsolute(node) || !isAbsolute(options.packageRoot))
29
+ failed(stage);
30
+ const nodeDirectory = dirname(node);
31
+ const npm = process.platform === 'win32' ? join(nodeDirectory, 'node_modules', 'npm', 'bin', 'npm-cli.js') : resolve(nodeDirectory, '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js');
32
+ if (!lstatSync(npm).isFile() || metadata(dirname(dirname(npm))).name !== 'npm')
33
+ failed(stage);
34
+ const invoke = (args, timeout = 15000) => run(node, [npm, ...args], timeout);
35
+ const npmVersion = invoke(['--version']).trim().match(/^(\d+)\.(\d+)\.(\d+)$/);
36
+ if (!npmVersion || !npmVersion.slice(1).every(part => Number.isSafeInteger(Number(part))))
37
+ failed('update_npm_unsupported');
38
+ const prefix = absoluteOutput(invoke(['prefix', '--global'])), root = absoluteOutput(invoke(['root', '--global']));
39
+ const expectedRoot = process.platform === 'win32' ? join(prefix, 'node_modules') : join(prefix, 'lib', 'node_modules');
40
+ if (canonical(root) !== canonical(expectedRoot))
41
+ failed(stage);
42
+ const target = join(root, 'aptly');
43
+ if (lstatSync(target).isSymbolicLink() || !lstatSync(target).isDirectory() || canonical(target) !== canonical(options.packageRoot))
44
+ failed(stage);
45
+ verifyPackage(target);
46
+ // Query the same effective global npm configuration used for installation.
47
+ // A successful dry-run does not prove the on-disk package was updated.
48
+ stage = 'update_configuration_unverified';
49
+ const dryRun = invoke(['config', 'get', 'dry-run', '--global', '--prefix', prefix]).trim();
50
+ if (dryRun === 'true')
51
+ failed('update_dry_run_enabled');
52
+ if (dryRun !== 'false')
53
+ failed(stage);
54
+ // Explicit prefix pins the operation to the verified installation, including custom prefixes.
55
+ // Lifecycle scripts remain disabled: updating code must not rewrite host registration or trust.
56
+ stage = 'update_install_failed';
57
+ invoke(['install', '-g', 'aptly@latest', '--ignore-scripts', '--prefix', prefix], 120000);
58
+ stage = 'update_result_unverified';
59
+ if (lstatSync(target).isSymbolicLink() || canonical(target) !== canonical(options.packageRoot))
60
+ failed(stage);
61
+ const version = verifyPackage(target);
62
+ return { status: 'complete', codes: ['package_updated', 'host_configuration_preserved', 'setup_required', 'mcp_restart_required'], version };
63
+ }
64
+ catch (error) {
65
+ const code = error instanceof Error && ['update_global_install_unverified', 'update_npm_unsupported', 'update_dry_run_enabled'].includes(error.message) ? error.message : stage;
66
+ return { status: 'error', codes: [code] };
67
+ }
68
+ }
@@ -1 +1 @@
1
- export declare const VERSION = "0.1.1";
1
+ export declare const VERSION = "0.1.3";
@@ -1 +1 @@
1
- export const VERSION = '0.1.1';
1
+ export const VERSION = '0.1.3';
package/docs/guide/en.md CHANGED
@@ -4,24 +4,61 @@
4
4
 
5
5
  [Back to README](../../README.en.md)
6
6
 
7
- Korean is the canonical documentation. This guide targets Aptly 0.1.1. Package availability does not establish model access for every account. Claude Code or Codex controls native subagent execution, approvals, sandboxing, and MCP permissions.
7
+ Korean is the canonical documentation. This guide covers general Aptly installation and usage. Package availability does not establish model access for every account. Claude Code or Codex controls native subagent execution, approvals, sandboxing, and MCP permissions.
8
8
 
9
9
  ## Installation
10
10
 
11
- Requires Node.js 24 or later and Claude Code or Codex. When 0.1.1 is available on npm, use these global installation commands:
11
+ Requires Node.js 24 or later and Claude Code or Codex. Install the latest stable npm release globally:
12
+
13
+ **Before upgrading an existing persistent ledger to 0.1.2 or later**, stop every host, MCP server, standalone CLI, and older process that can access it. The persistent gate cannot coexist with older writers. Fresh installations need no legacy-lock quarantine. If an old empty lock remains, follow the [ledger transition procedure](#interrupted-processes-and-ledger-locks): quarantine only a confirmed legacy lock while offline and preserve the JSON ledger, `unknown` records, costs, and completed cache.
12
14
 
13
15
  ```sh
14
- npm install -g aptly@0.1.1
16
+ npm install -g aptly@latest --allow-scripts=aptly
15
17
  aptly setup --client all --mode defaults
16
18
  aptly --version
17
19
  ```
18
20
 
19
- `aptly --version` should print `0.1.1`. Switching Node.js environments may require reinstalling.
21
+ Use `aptly --version` to check the installed version. Switching Node.js environments may require reinstalling.
20
22
 
21
23
  `postinstall` registers the MCP server and a `PreToolUse` Hook in the current user's existing host configuration directories. If you use `CODEX_HOME` or `CLAUDE_CONFIG_DIR`, pass the same environment to installation. Automatic registration skips host directories that do not exist; explicit `setup` can create them. To register only one host, use `--client codex` or `--client claude`.
22
24
 
23
25
  New registrations set `ROUTER_PROVIDER=decisions`, the Hook's `defaults` policy, and a private ledger for each host. Other settings and Hooks, and existing Aptly commands, environments, providers, and ledger paths, are preserved. Existing fixture settings are not automatically switched to paid mode.
24
26
 
27
+ ### npm install-script approval
28
+
29
+ The installation command above uses `--allow-scripts=aptly` to explicitly allow Aptly's `postinstall` for that installation. Support was checked with npm 11.19.1; the command does not change user-wide npm approval settings. See the [official npm guidance](https://docs.npmjs.com/cli/v11/commands/npm-rebuild/#allow-scripts).
30
+
31
+ `npm warn install-scripts ... not yet covered by allowScripts` reports an unreviewed policy entry. In npm 11.19.1, this warning alone does not mean scripts were blocked. Behavior depends on npm version, strict policy, and `ignore-scripts`; installation success alone does not verify MCP or Hook registration. npm may hide postinstall output.
32
+
33
+ For npm versions without this option, or to configure explicitly instead of automatic registration, run:
34
+
35
+ ```sh
36
+ npm install -g aptly@latest --ignore-scripts
37
+ aptly setup --client all --mode defaults
38
+ ```
39
+
40
+ Explicit `setup` works regardless of lifecycle execution. It preserves existing launchers; use the recovery steps below for stale paths. Key setup, MCP restart, and Codex `/hooks` trust review remain separate steps.
41
+
42
+ ### Package updates
43
+
44
+ `aptly update` requires **Aptly 0.1.3 or later**. It requires a verified global npm installation and installs `aptly@latest` into the same verified prefix as the running package. Local installations, source checkouts, and unverified paths are rejected. If the effective npm configuration has `dry-run=true`, the command refuses with `update_dry_run_enabled` before starting installation. If configuration cannot be verified, it stops with `update_configuration_unverified`. A dry-run is never reported as a successful update.
45
+
46
+ Stop other host, MCP, and CLI processes using the ledger before updating, following the transition steps above. The command skips lifecycle scripts; explicitly configure afterward and restart hosts:
47
+
48
+ ```sh
49
+ aptly update
50
+ aptly setup --client all --mode defaults
51
+ aptly --version
52
+ ```
53
+
54
+ Existing MCP launchers and user wrappers are not automatically migrated. Follow the launcher recovery instructions below if old paths remain. Key setup and Codex `/hooks` trust review remain separate. For npm authentication, network, or permission failures, use the manual installation instructions. Updates are never installed automatically.
55
+
56
+ ### New-version notifications
57
+
58
+ **Aptly 0.1.3 or later** checks the latest stable version during interactive human-facing CLI commands and suggests `aptly update` on stderr when a newer version exists. All three standard streams must be terminals. MCP serving, automatic setup, recommendation/classification paths, pipes, and CI skip checks. JSON stdout and MCP/Hook payloads stay unchanged.
59
+
60
+ Only public Aptly version metadata is requested from the npm registry; no key, task summary, or host configuration is sent. Network and body reads are limited to 800ms and 16KiB. Results are cached at `~/.cache/aptly/update-check.json` for 24 hours, with a one-hour cooldown after failure. Network/cache errors cannot fail the requested command. Set `APTLY_NO_UPDATE_NOTIFIER=1` in the CLI environment to disable checks; it is not a supported key for `aptly set env`. Notifications never install updates.
61
+
25
62
  ### Configure with the CLI
26
63
 
27
64
  The `set` commands require 0.1.1 or later. Commands do not automatically switch existing launch paths. API-key setup accepts only the current package’s standard Node/server registration with a verified OS-source-compatible runtime. Custom wrappers, older versions, and other installation prefixes are rejected with `credential_launcher_unverified`; explicitly switch the registration or upgrade it before trying again.
@@ -56,6 +93,34 @@ A store timeout or malformed acknowledgement may occur after the OS has written
56
93
 
57
94
  Restart MCP, then inspect `provider`, candidates, and `credential_status` with `get_routing_capabilities`. `os_store` means a key was loaded, not that the API authenticated it. Default and public-variable setup continue to preserve custom wrappers. API-key setup does not change host settings for an unverified launch path and restores that host's previous key where possible if storage was already attempted. Do not assume a new key automatically takes effect through an existing wrapper. These commands do not bypass Codex `/hooks` trust or host permissions.
58
95
 
96
+ ### Recover an incompatible launcher
97
+
98
+ These options require Aptly 0.1.2 or later and are not in npm 0.1.1. To test from source, run `npm ci --ignore-scripts` and `npm run build`, then replace `aptly` below with `node bin/aptly.ts`.
99
+
100
+ Key setup diagnoses selected hosts before input or storage. If any host fails, it does not prompt or change any host. `--check` does not access keys or the credential store. `credential_node_mismatch`, `credential_server_mismatch`, and `credential_runtime_unsupported` identify incompatible Node paths, server paths, and OS-store support respectively.
101
+
102
+ If only Claude failed, diagnose that host and review migration only when `launcher_migration_available` is returned:
103
+
104
+ ```sh
105
+ aptly set env OPENAI_API_KEY --client claude --check
106
+ aptly setup --client claude --migrate-launcher --dry-run
107
+ aptly setup --client claude --migrate-launcher
108
+ aptly set env OPENAI_API_KEY --client claude
109
+ ```
110
+
111
+ `--dry-run` makes no changes. Migration replaces the Node/server paths of a receipt-matching, Aptly-owned standard registration with the current build. It preserves environment settings, Hooks, policy and other hosts, accesses no credentials, and never executes the old launcher. Custom wrappers and missing or modified ownership records are rejected. Review such registrations locally; use the wrapper's secure environment or a separately reviewed standard registration. Do not edit or delete ownership records to bypass validation.
112
+
113
+ If `launcher_migration_not_owned` refers to a preserved registration (`mcp_created: false`), **Aptly 0.1.3 or later** offers the explicit `--include-existing` opt-in. Install 0.1.3 or later, then run:
114
+
115
+ ```sh
116
+ aptly setup --client claude --migrate-launcher --include-existing --dry-run
117
+ aptly setup --client claude --migrate-launcher --include-existing
118
+ ```
119
+
120
+ Review the local registration first. A valid existing Aptly ownership receipt and matching managed environment additions, Hook, and policy are required. Only an absolute Node path with a single standard server path is accepted; wrappers and registrations without a receipt remain unsupported. This does not make the entire MCP registration Aptly-owned: later removal preserves the migrated launcher and original user settings. The option applies only to explicit single-client migration, never automatic installation.
121
+
122
+ A successful Codex configuration needs no reset. Retry only the affected host and restart MCP. Codex still requires `/hooks` trust review. Changes after diagnosis stop with `concurrent_configuration_change`. If recovery observes another key or cannot read the current key, it leaves the store unchanged and reports `credential_rollback_failed`. Files and the OS store do not form an atomic transaction; avoid concurrent configuration operations.
123
+
59
124
  ### Keys and restarting
60
125
 
61
126
  Pass the classification key, `OPENAI_API_KEY`, through a secure environment or credential launcher to the MCP process. It is separate from host subscription login. Never write key values into command arguments, requests, configuration files, source, logs, or temporary files.
@@ -129,7 +194,7 @@ See the official [Codex configuration reference](https://learn.chatgpt.com/docs/
129
194
  ### Skipping registration and removing it
130
195
 
131
196
  ```sh
132
- APTLY_SKIP_SETUP=1 npm install -g aptly@0.1.1
197
+ APTLY_SKIP_SETUP=1 npm install -g aptly@latest
133
198
  aptly setup --client codex --mode defaults
134
199
  aptly remove --client all
135
200
  ```
@@ -156,6 +221,20 @@ The CLI without additional configuration, and existing manual configurations, de
156
221
  | `get_routing_precedence` | Explains preserved choices and unverified configuration sources for a call |
157
222
  | `route_spawn_hook` | Selects defaults for eligible calls or passes advice only, according to the installed policy |
158
223
 
224
+ ### Outbound data and disabling automatic sharing
225
+
226
+ For automatic classification, `summary` is an **excerpt assembled from an accepted task label and the clipped first paragraph** of the body. It is not a semantic rewrite or anonymization. Its UTF-8 size is at most `min(4000, max_summary_bytes)`; this is not a limit on the whole HTTP request. The opaque-message fallback in Codex uses only a sufficiently descriptive `task_name`, without decoding or transmitting that body. Labels can also contain sensitive information.
227
+
228
+ Decisions receives `client`, `task.summary`, `task.operation`, `task.context_sufficient`, candidate profile IDs, model/effort descriptions, and configured model facts. The classification API key is sent in `Authorization`; the request ID is sent in `X-Client-Request-Id`. Automatic IDs are hashes; direct recommendation IDs are caller-supplied. Do not put secrets in IDs or candidate descriptions.
229
+
230
+ To disable automatic sharing, change **only `enabled` to `false`** in the existing private policy file referenced by `APTLY_HOOK_POLICY_PATH`. Preserve the other fields and ownership record. Subsequent automatic Hook calls preserve the original call before classification or creation of a call-binding file. This cannot undo a transmission already started or recall information received by the server. Editing a generated policy can cause ownership conflicts in setup, configuration, or removal commands; those commands do not overwrite the disabled policy. Do not edit ownership records to bypass the checks.
231
+
232
+ `mode: advisory` still transmits classification data; it is not a privacy opt-out. Removing `APTLY_HOOK_POLICY_PATH` can activate the older strict path, so do not use removal as an alternative. `enabled: false` does not block explicit `recommend_agent` or `aptly recommend` requests.
233
+
234
+ For control over the shared summary, disable automatic sharing and write only the information needed for a direct recommendation. Aptly does not automatically fetch documents at URLs or attach source files mentioned in the summary. Checks for known key and Bearer patterns do not provide complete secret detection or establish that text is safe to transmit.
235
+
236
+ The ledger and Hook bindings store request metadata, hashes, and cached results, not task excerpts. Aptly diagnostics also exclude raw task text. The local Hook's `updatedInput` retains the original task so the host can continue execution. Aptly does not control the host's own transcript or log retention.
237
+
159
238
  ## Direct recommendations
160
239
 
161
240
  The `recommend_agent` MCP tool and CLI `recommend` accept a task summary and recommend a profile. They do not spawn subagents. Pass this JSON as MCP tool arguments, or save it to a file and provide it to the CLI through standard input.
@@ -254,6 +333,14 @@ These are USD conversions of measured native tokens at the [official Standard AP
254
333
 
255
334
  The measured workflow was **explicit MCP recommendation → native execution with the recommended profile passed as arguments**. It did not test automatic Hook URL retrieval or forwarding. The prior benchmark was reused as the control, with three samples per condition. Full-document reads, matching source quotes, and output structure were checked, but the results do not establish equal quality, statistical significance, or savings for other tasks.
256
335
 
336
+ ### Interrupted processes and ledger locks
337
+
338
+ This locking design requires Aptly `0.1.2` or later and is not included in npm `0.1.1`. The JSON ledger keeps its request IDs, `unknown` records, completed cache, call counts, and reserved costs. Only persistent ledgers use Node.js 24's built-in SQLite. The adjacent `ledger.json.lock` remains after a normal exit; its presence alone does not mean an active lock. With the new design, process exit releases the OS lock so a later request can use the same ledger. It does not retry an existing uncertain ID or refund reserved costs.
339
+
340
+ Keep the ledger and lock in a private directory on a local filesystem that supports hard links, and use one canonical path for each ledger. Network shares, cloud-synced directories, and path aliases are outside the supported scope. Do not delete or replace the new lock or SQLite journal, or open them with another database tool while in use. Age and PID alone do not establish that an owner has exited.
341
+
342
+ An old empty `.lock` cannot establish whether its owner is still alive, so it is never initialized or removed automatically. Stop every relevant host, MCP process, and ledger-accessing process, including older versions, and upgrade all writers. Only after confirming that the file belongs to the legacy locking design may you quarantine that file and restart against the same JSON ledger path. Do not reset or delete the ledger, `unknown` records, costs, or completed results. If ownership or format is uncertain, leave access blocked and investigate.
343
+
257
344
  ## Diagnostics and development
258
345
 
259
346
  ```sh
package/docs/guide/ja.md CHANGED
@@ -4,24 +4,61 @@
4
4
 
5
5
  [README に戻る](../../README.ja.md)
6
6
 
7
- 韓国語版が正本です。このガイドは Aptly 0.1.1 を対象とします。パッケージをインストールできることは、すべてのアカウントでモデルにアクセスできることを意味しません。子エージェントの実行・承認・サンドボックス・MCP 権限は、Claude Code または Codex が管理します。
7
+ 韓国語版が正本です。このガイドでは Aptly の基本的なインストール方法と使い方を説明します。パッケージをインストールできることは、すべてのアカウントでモデルにアクセスできることを意味しません。子エージェントの実行・承認・サンドボックス・MCP 権限は、Claude Code または Codex が管理します。
8
8
 
9
9
  ## インストール
10
10
 
11
- Node.js 24 以上と Claude Code または Codex が必要です。0.1.1 が npm で公開されている場合は、以下のグローバルインストールコマンドを使用してください:
11
+ Node.js 24 以上と Claude Code または Codex が必要です。npm の最新安定版をグローバルにインストールするには、次のコマンドを実行してください:
12
+
13
+ **既存の永続台帳を 0.1.2 以降に更新する前に**、その台帳にアクセスする可能性があるすべてのホスト、MCP サーバー、単独 CLI、旧版プロセスを停止してください。新しい永続ロックは旧版の書き込み側と併用できません。新規インストールでは旧ロックの隔離は不要です。旧版の空のロックが残る場合は、[台帳の移行手順](#プロセス中断と台帳ロック)に従い、確認済みの旧ロックだけをオフラインで隔離し、JSON 台帳、`unknown` 記録、費用、完了済みキャッシュを保持してください。
12
14
 
13
15
  ```sh
14
- npm install -g aptly@0.1.1
16
+ npm install -g aptly@latest --allow-scripts=aptly
15
17
  aptly setup --client all --mode defaults
16
18
  aptly --version
17
19
  ```
18
20
 
19
- `aptly --version` が `0.1.1` を表示することを確認してください。Node.js 環境を切り替えると再インストールが必要な場合があります。
21
+ `aptly --version` でインストール済みのバージョンを確認してください。Node.js 環境を切り替えると再インストールが必要な場合があります。
20
22
 
21
23
  `postinstall` は、現在のユーザーの既存のホスト設定ディレクトリに MCP と `PreToolUse` Hook を登録します。`CODEX_HOME`・`CLAUDE_CONFIG_DIR` を使う場合は、インストールプロセスにも同じ環境を渡してください。まだ存在しないホストディレクトリは自動登録ではスキップし、明示的な `setup` で作成できます。必要なホストだけを登録するには、`--client codex` または `--client claude` を使用してください。
22
24
 
23
25
  新規登録では `ROUTER_PROVIDER=decisions`、Hook の `defaults` ポリシー、ホストごとの非公開台帳を指定します。他の既存設定・Hook と、既存の Aptly のコマンド・環境・provider・台帳パスは保持します。既存の fixture 設定を自動で有料モードに切り替えることはありません。
24
26
 
27
+ ### npm インストールスクリプトの許可
28
+
29
+ 上記の `--allow-scripts=aptly` は、そのインストールで Aptly の `postinstall` を明示的に許可します。npm 11.19.1 で対応を確認しており、ユーザー全体の npm 許可設定は変更しません。[npm 公式ガイド](https://docs.npmjs.com/cli/v11/commands/npm-rebuild/#allow-scripts)を参照してください。
30
+
31
+ `npm warn install-scripts ... not yet covered by allowScripts` は、許可ポリシーに未登録であることを示します。npm 11.19.1 では、この警告だけでスクリプトがブロックされたとは判断できません。npm のバージョン・厳格なポリシー・`ignore-scripts` によって挙動が異なり、インストール成功だけでは MCP・Hook の登録成功を確認できません。postinstall の出力は npm によって非表示になる場合があります。
32
+
33
+ このオプションに未対応の npm を使う場合や、自動登録の代わりに手動設定する場合は、次を実行してください。
34
+
35
+ ```sh
36
+ npm install -g aptly@latest --ignore-scripts
37
+ aptly setup --client all --mode defaults
38
+ ```
39
+
40
+ スクリプトの実行にかかわらず、明示的な `setup` を利用できます。既存の起動パスは保持するため、旧パスのエラーは以下の復旧手順に従ってください。キー設定・MCP の再起動と Codex の `/hooks` 信頼確認は別途必要です。
41
+
42
+ ### パッケージの更新
43
+
44
+ `aptly update` は **Aptly 0.1.3 以降で利用できます**。確認済みの npm グローバルインストールが必要で、実行中のパッケージと一致する確認済み prefix に `aptly@latest` をインストールします。ローカルインストール・ソースチェックアウト・確認できないパスは拒否します。 npm の有効な設定が `dry-run=true` の場合は、インストール前に `update_dry_run_enabled` で拒否します。設定を確認できない場合は `update_configuration_unverified` で停止し、試行のみの実行を更新成功とは報告しません。
45
+
46
+ 更新前に、上記の台帳移行手順に従い、台帳を使用する他のホスト・MCP・CLI プロセスを停止してください。インストールスクリプトは実行しないため、更新後に明示的に設定し、ホストを再起動してください。
47
+
48
+ ```sh
49
+ aptly update
50
+ aptly setup --client all --mode defaults
51
+ aptly --version
52
+ ```
53
+
54
+ 既存の MCP 起動パスやユーザーラッパーは自動移行しません。旧パスが残る場合は以下の復旧手順に従ってください。キー設定と Codex の `/hooks` 信頼確認は別途必要です。npm の認証・ネットワーク・権限エラーが発生した場合は手動インストールの案内を使用してください。更新の自動インストールは行いません。
55
+
56
+ ### 新しいバージョンの通知
57
+
58
+ **Aptly 0.1.3 以降では**、対話形式の通常 CLI コマンドで最新の安定版を確認し、新版があれば stderr に `aptly update` を案内します。 標準入出力と標準エラー出力がすべてターミナルの場合のみ動作し、MCP サーバー・自動 setup・推薦や分類の経路・パイプ・CI では確認しません。JSON stdout と MCP・Hook の応答は変更しません。
59
+
60
+ 公開 npm レジストリから Aptly のバージョン情報のみを取得し、キー・タスク要約・ホスト設定は送信しません。ネットワークと応答読み取りは 800ms・16KiB に制限し、結果を `~/.cache/aptly/update-check.json` に 24 時間キャッシュします。失敗後は 1 時間待機し、通信・キャッシュエラーで元のコマンドを失敗させません。CLI の環境に `APTLY_NO_UPDATE_NOTIFIER=1` を設定すると確認を停止できます。この変数は `aptly set env` の対象ではありません。通知による自動更新は行いません。
61
+
25
62
  ### CLI による設定
26
63
 
27
64
  `set` コマンドは 0.1.1 以降で利用できます。既存の起動パスは自動で切り替えません。API キー設定は、現在のパッケージの標準 Node/サーバー登録で、OS 資格情報の参照に対応する実行環境だと確認できた場合にのみ使用できます。独自ラッパー、旧バージョン、別のインストール先は `credential_launcher_unverified` で拒否します。登録を明示的に切り替えるかアップグレードしてから、再度実行してください。
@@ -56,6 +93,34 @@ API キーは macOS Keychain、インストール済みの Linux `secret-tool`
56
93
 
57
94
  変更後は MCP を再起動し、`get_routing_capabilities` の `provider`、候補、`credential_status` を確認してください。`os_store` はキーを読み込めたことを示し、API 認証の成功を示すものではありません。デフォルト設定と公開変数の設定では、引き続き独自ラッパーを保持します。API キー設定は未確認の起動パスのホスト設定を変更せず、保存を試みていた場合は可能な限りそのホストの旧キーを復元します。既存のラッパーにも新しいキーが自動で適用されるとは想定しないでください。Codex の `/hooks` 信頼承認やホスト権限は迂回しません。
58
95
 
96
+ ### 起動パスのエラーからの復旧
97
+
98
+ 以下のオプションは Aptly 0.1.2 以降で利用でき、npm 0.1.1 には含まれません。ソースから試す場合は `npm ci --ignore-scripts` と `npm run build` を実行し、以下の `aptly` を `node bin/aptly.ts` に置き換えます。
99
+
100
+ キー設定は入力・保存前に対象ホストを診断します。いずれかが失敗すると入力を求めず、全ホストを変更しません。`--check` はキーや資格情報ストアにアクセスしません。`credential_node_mismatch`、`credential_server_mismatch`、`credential_runtime_unsupported` はそれぞれ Node パス、サーバーパス、OS ストア対応の不一致を示します。
101
+
102
+ Claude だけが失敗した場合は次の順序で診断し、`launcher_migration_available` の場合にのみ移行を検討してください。
103
+
104
+ ```sh
105
+ aptly set env OPENAI_API_KEY --client claude --check
106
+ aptly setup --client claude --migrate-launcher --dry-run
107
+ aptly setup --client claude --migrate-launcher
108
+ aptly set env OPENAI_API_KEY --client claude
109
+ ```
110
+
111
+ `--dry-run` は変更しません。移行は所有記録と一致する Aptly の標準登録に限り、Node・サーバーパスを現在のビルドへ更新します。環境設定・Hook・ポリシー・他のホストを保持し、資格情報へのアクセスや古い起動プログラムの実行は行いません。独自ラッパー、所有記録のない登録、変更済みの登録は拒否します。その場合は登録をローカルで確認し、ラッパーの安全な環境変数受け渡しを使うか、別途確認した標準登録へ切り替えてください。検証を回避するために所有記録を編集・削除しないでください。
112
+
113
+ `launcher_migration_not_owned` が既存の登録を保持した状態(`mcp_created: false`)を指す場合、**Aptly 0.1.3 以降では** `--include-existing` を明示して移行できます。0.1.3 以降をインストールし、次を実行してください。
114
+
115
+ ```sh
116
+ aptly setup --client claude --migrate-launcher --include-existing --dry-run
117
+ aptly setup --client claude --migrate-launcher --include-existing
118
+ ```
119
+
120
+ 実行前にローカルの登録を確認してください。有効な既存の Aptly 所有記録と、記録に一致する管理対象の環境変数・Hook・ポリシーが必要です。絶対 Node パスと単一の標準サーバーパスのみを許可し、ラッパーや記録のない登録は拒否します。MCP 登録全体を Aptly 所有には変更しないため、その後の削除でも移行後の起動パスと元のユーザー設定を保持します。明示的な単一ホストの移行専用で、自動インストールには適用されません。
121
+
122
+ 成功した Codex の再設定は不要です。失敗したホストだけを指定して再試行し、MCP を再起動してください。Codex では引き続き `/hooks` の信頼確認が必要です。診断後の設定変更は `concurrent_configuration_change` で中断します。復旧時に別のキーを検出した場合や現在値を読めない場合は上書きせず、`credential_rollback_failed` を返します。ファイルと OS ストアは原子的なトランザクションではないため、設定操作を同時に実行しないでください。
123
+
59
124
  ### キーと再起動
60
125
 
61
126
  分類用の `OPENAI_API_KEY` は、安全な環境や資格情報ランチャーを通して MCP プロセスに渡してください。ホストのサブスクリプション認証とは別です。キーの値をコマンド引数・リクエスト・設定ファイル・ソース・ログ・一時ファイルに記録しないでください。
@@ -129,7 +194,7 @@ APTLY_CODEX_MODELS = '["gpt-6-luna","gpt-6.1-terra","gpt-6.1-sol"]'
129
194
  ### スキップ・削除
130
195
 
131
196
  ```sh
132
- APTLY_SKIP_SETUP=1 npm install -g aptly@0.1.1
197
+ APTLY_SKIP_SETUP=1 npm install -g aptly@latest
133
198
  aptly setup --client codex --mode defaults
134
199
  aptly remove --client all
135
200
  ```
@@ -156,6 +221,20 @@ aptly remove --client all
156
221
  | `get_routing_precedence` | 呼び出しを保持する根拠と、未確認の設定元を説明します |
157
222
  | `route_spawn_hook` | インストールしたポリシーに応じて、対象呼び出しのデフォルト値を選択するか、推薦だけを伝えます |
158
223
 
224
+ ### 外部送信と自動共有の無効化
225
+
226
+ 自動分類の `summary` は、有効なタスクラベルと本文の**最初の段落を切り詰めて組み合わせた抜粋**です。意味を再要約したものでも、匿名化したものでもありません。UTF-8 のサイズは `min(4000, max_summary_bytes)` 以下ですが、HTTP リクエスト全体の上限ではありません。Codex の opaque メッセージへのフォールバックでは、本文を復号・送信せず、十分に具体的な `task_name` だけを使用します。ラベルにも機密情報が含まれる可能性があります。
227
+
228
+ Decisions には `client`、`task.summary`、`task.operation`、`task.context_sufficient` と、候補プロファイル ID・モデルと effort の説明・設定したモデル特性を送信します。分類用 API キーは `Authorization` ヘッダー、リクエスト ID は `X-Client-Request-Id` ヘッダーで送信します。自動経路の ID はハッシュで、直接推薦の ID は呼び出し元が指定します。ID や候補の説明にも秘密情報を含めないでください。
229
+
230
+ 自動共有を無効にするには、`APTLY_HOOK_POLICY_PATH` が指す既存の非公開ポリシーファイルで、**`enabled` だけを `false` に変更**してください。他のフィールドと所有権の記録は保持してください。その後の自動 Hook 呼び出しは、分類や呼び出しバインディングファイルの作成前に元の呼び出しを保持します。開始済みの送信を取り消したり、サーバーが受信した情報を回収したりすることはできません。生成済みのポリシーを変更すると、登録・設定・削除コマンドの所有権検査で競合する場合があり、それらのコマンドは無効化したポリシーを上書きしません。検査を回避するために所有権の記録を編集しないでください。
231
+
232
+ `mode: advisory` でも分類データは送信されるため、プライバシー上の共有停止にはなりません。`APTLY_HOOK_POLICY_PATH` を削除すると従来の strict 経路が有効になる場合があるため、共有停止の代わりにしないでください。`enabled: false` は、明示的な `recommend_agent` や `aptly recommend` のリクエストを止めるものではありません。
233
+
234
+ 共有する要約を自分で選ぶ場合は、自動共有を無効にしてから直接推薦に必要な情報だけを記述してください。Aptly は要約中の URL の文書や、言及されたソースファイルを自動取得・添付しません。既知のキーや Bearer のパターン検査は、完全な秘密情報の検出や送信の安全性を保証しません。
235
+
236
+ 台帳と Hook バインディングにはリクエストのメタデータ・ハッシュ・キャッシュ結果を保存し、タスクの抜粋は保存しません。Aptly の診断にもタスク原文を含めません。ただし、ローカルの Hook の `updatedInput` は、ホストが実行を続けられるよう元のタスクを保持します。ホスト自身の会話やログの保存は Aptly の制御対象ではありません。
237
+
159
238
  ## 直接推薦
160
239
 
161
240
  `recommend_agent` MCP と CLI の `recommend` は、タスク要約を受け取ってプロファイルを推薦します。子エージェントを直接生成することはありません。以下の JSON を MCP ツールの引数として渡すか、ファイルに保存して CLI の標準入力に渡してください。
@@ -254,6 +333,14 @@ Codex が子エージェントの `message` を暗号文として Hook に渡す
254
333
 
255
334
  測定経路は、**明示的な MCP 推薦 → 推薦プロファイルを引数として渡したホスト上での実行**です。自動 Hook の URL 収集・伝達機能を検証したものではありません。基準群は直前の実測を再利用しており、条件ごとの標本は 3 回です。ドキュメント全体の読み取り・原文の引用一致・出力形式は確認しましたが、品質の同等性、統計的有意性、他のタスクでの費用削減を保証するものではありません。
256
335
 
336
+ ### プロセス中断と台帳ロック
337
+
338
+ このロック方式は Aptly `0.1.2` 以降で利用でき、npm `0.1.1` には含まれません。JSON 台帳のリクエスト ID・`unknown`・完了済みキャッシュ・呼び出し数・予約費用の形式は維持します。永続台帳だけが Node.js 24 内蔵の SQLite を使用します。隣接する `ledger.json.lock` は正常終了後も残るため、ファイルの存在だけではロックが使用中かどうかを判断できません。新方式ではプロセス終了時に OS のロックが解放され、後続のリクエストが同じ台帳を使用できます。結果が不明な既存 ID の再試行や予約費用の返却は行いません。
339
+
340
+ 台帳とロックは、ハードリンクに対応したローカルファイルシステムの非公開ディレクトリに置き、各台帳に同一の正規パスを使用してください。ネットワーク共有・クラウド同期ディレクトリ・パスの別名はサポート範囲外です。新しいロックや SQLite journal を削除・置換したり、使用中に他の DB ツールで開いたりしないでください。ファイルの古さや PID だけでは所有プロセスの終了を確認できません。
341
+
342
+ 旧版の空の `.lock` ファイルでは所有プロセスが生存しているかを確認できないため、自動で初期化・削除しません。旧版を含む関連ホスト・MCP・台帳にアクセスするすべてのプロセスを停止し、書き込み側をすべて新しい版に更新してください。旧方式のロックであると確認できた場合だけ、そのファイルを別途隔離し、同じ JSON 台帳パスで再開します。台帳・`unknown`・費用・完了結果を初期化・削除しないでください。所有者や形式を確認できない場合は、遮断状態を保って調査してください。
343
+
257
344
  ## 診断と開発
258
345
 
259
346
  ```sh
package/docs/guide/ko.md CHANGED
@@ -4,24 +4,61 @@
4
4
 
5
5
  [README로 돌아가기](../../README.md)
6
6
 
7
- 한국어가 정본입니다. 이 안내는 Aptly 0.1.1을 기준으로 합니다. 패키지를 설치할 수 있다는 사실이 모든 계정의 모델 접근 가능성을 뜻하지는 않습니다. 실제 자식 실행·승인·샌드박스·MCP 권한은 Claude Code 또는 Codex가 담당합니다.
7
+ 한국어가 정본입니다. 이 안내는 Aptly의 일반적인 설치·사용 방법을 설명합니다. 패키지를 설치할 수 있다는 사실이 모든 계정의 모델 접근 가능성을 뜻하지는 않습니다. 실제 자식 실행·승인·샌드박스·MCP 권한은 Claude Code 또는 Codex가 담당합니다.
8
8
 
9
9
  ## 설치
10
10
 
11
- Node.js 24 이상과 Claude Code 또는 Codex가 필요합니다. 0.1.1이 npm에 게시된 경우 다음 전역 설치 명령을 사용하십시오:
11
+ Node.js 24 이상과 Claude Code 또는 Codex가 필요합니다. npm의 최신 안정 버전을 전역 설치하려면 다음 명령을 사용하십시오:
12
+
13
+ **기존 영속 원장을 0.1.2 이상으로 업그레이드하기 전에**, 해당 원장을 사용하는 모든 호스트·MCP 서버·별도 CLI와 구버전 프로세스를 정지하십시오. 새 영구 잠금은 구버전 writer와 함께 사용할 수 없습니다. 새 설치에는 기존 잠금 격리가 필요하지 않습니다. 이전 빈 잠금이 남았다면 [원장 잠금 전환 절차](#중단된-프로세스와-원장-잠금)를 따라 확인된 기존 잠금만 오프라인으로 격리하고, JSON 원장·`unknown`·비용·완료 캐시는 보존하십시오.
12
14
 
13
15
  ```sh
14
- npm install -g aptly@0.1.1
16
+ npm install -g aptly@latest --allow-scripts=aptly
15
17
  aptly setup --client all --mode defaults
16
18
  aptly --version
17
19
  ```
18
20
 
19
- `aptly --version`의 출력은 `0.1.1`이어야 합니다. Node.js 환경을 바꾸면 재설치가 필요할 수 있습니다.
21
+ `aptly --version`으로 설치된 버전을 확인하십시오. Node.js 환경을 바꾸면 재설치가 필요할 수 있습니다.
20
22
 
21
23
  `postinstall`은 현재 사용자의 기존 호스트 설정 디렉터리에 MCP와 `PreToolUse` Hook을 등록합니다. `CODEX_HOME`·`CLAUDE_CONFIG_DIR`을 사용한다면 설치 프로세스에도 같은 환경을 전달하십시오. 아직 없는 호스트 디렉터리는 자동 등록에서 건너뛰고, 명시적인 `setup`으로 만들 수 있습니다. 필요한 호스트만 등록하려면 `--client codex` 또는 `--client claude`를 사용하십시오.
22
24
 
23
25
  새 등록은 `ROUTER_PROVIDER=decisions`, Hook `defaults` 정책과 호스트별 비공개 원장을 지정합니다. 기존 다른 설정·Hook, 기존 Aptly의 실행 명령·환경·분류 방식·원장 경로는 보존합니다. 기존 fixture 설정을 자동으로 유료 모드로 바꾸지 않습니다.
24
26
 
27
+ ### npm 설치 스크립트 허용
28
+
29
+ 위 설치 명령의 `--allow-scripts=aptly`는 해당 설치에서 Aptly의 `postinstall`을 명시적으로 허용합니다. npm 11.19.1에서 지원을 확인했으며, 사용자 전체의 npm 허용 설정은 변경하지 않습니다. [npm 공식 안내](https://docs.npmjs.com/cli/v11/commands/npm-rebuild/#allow-scripts)를 참고하십시오.
30
+
31
+ `npm warn install-scripts ... not yet covered by allowScripts`는 허용 정책에 아직 등록되지 않았다는 안내입니다. npm 11.19.1에서는 이 경고만으로 스크립트가 차단됐다고 판단할 수 없습니다. npm 버전·엄격 정책·`ignore-scripts`에 따라 동작이 달라지며, 설치 성공만으로 MCP·Hook 등록 성공을 확인할 수는 없습니다. `postinstall`은 npm 출력에 표시되지 않을 수도 있습니다.
32
+
33
+ 옵션을 지원하지 않는 npm이거나 자동 등록 대신 직접 설정하려면 다음 명령을 사용하십시오:
34
+
35
+ ```sh
36
+ npm install -g aptly@latest --ignore-scripts
37
+ aptly setup --client all --mode defaults
38
+ ```
39
+
40
+ 명시적 `setup`은 설치 스크립트 실행 여부와 관계없이 사용할 수 있습니다. 기존 실행 경로는 보존하므로 구버전 경로 오류는 아래 복구 절차를 따르십시오. 키 설정·MCP 재시작과 Codex의 `/hooks` 신뢰 승인은 별도로 필요합니다.
41
+
42
+ ### 패키지 업데이트
43
+
44
+ `aptly update`는 **Aptly 0.1.3부터 지원합니다**. 검증된 전역 npm 설치에서만 현재 실행 중인 패키지와 동일한 prefix의 `aptly@latest`를 설치합니다. 로컬 설치·소스 체크아웃·확인할 수 없는 경로는 거절합니다. npm의 유효 설정에서 `dry-run=true`이면 실제 설치를 시작하기 전에 `update_dry_run_enabled`로 거절합니다. 설정을 확인할 수 없으면 `update_configuration_unverified`로 중단합니다. 시험 실행을 업데이트 성공으로 보고하지 않습니다.
45
+
46
+ 업데이트 전에 위 원장 전환 절차에 따라 다른 호스트·MCP·CLI 프로세스를 중지하십시오. 명령은 설치 스크립트를 실행하지 않으므로 업데이트 후 명시적으로 설정하고 호스트를 재시작하십시오:
47
+
48
+ ```sh
49
+ aptly update
50
+ aptly setup --client all --mode defaults
51
+ aptly --version
52
+ ```
53
+
54
+ 기존 MCP 실행 경로와 사용자 래퍼를 자동으로 전환하지 않습니다. 이전 경로가 남으면 아래 실행 경로 복구 안내를 따르십시오. 키 설정과 Codex의 `/hooks` 신뢰 검토는 별도 단계입니다. npm 인증·네트워크·권한 오류로 실패하면 수동 설치 안내를 사용하십시오. 자동 업데이트는 수행하지 않습니다.
55
+
56
+ ### 새 버전 알림
57
+
58
+ **Aptly 0.1.3부터** 일반 CLI의 대화형 실행에서 최신 안정 버전을 확인하고, 더 새 버전이 있으면 stderr에 `aptly update`를 안내합니다. stdin·stdout·stderr가 모두 터미널일 때만 동작하며, MCP 서버·자동 setup·추천/분류 경로·파이프·CI에서는 확인하지 않습니다. 기존 JSON stdout과 MCP·Hook 응답은 유지합니다.
59
+
60
+ 공개 npm 레지스트리의 Aptly 버전 메타데이터만 조회하며 키·작업 요약·호스트 설정은 보내지 않습니다. 네트워크와 응답 읽기는 최대 800ms·16KiB로 제한하고, 결과는 `~/.cache/aptly/update-check.json`에 24시간 캐시합니다. 실패 후에는 1시간 대기하며, 조회·캐시 오류로 원래 명령을 실패시키지 않습니다. 버전 조회를 끄려면 CLI 실행 환경에 `APTLY_NO_UPDATE_NOTIFIER=1`을 설정하십시오. 이 변수는 MCP 키 설정용 `aptly set env`의 지원 대상이 아닙니다. 알림은 업데이트를 설치하지 않습니다.
61
+
25
62
  ### CLI로 설정하기
26
63
 
27
64
  `set` 명령은 0.1.1부터 지원합니다. 명령은 기존 실행 경로를 자동 전환하지 않습니다. API 키 설정은 현재 패키지의 표준 Node/서버 등록과 OS 자격 저장소 참조 지원이 확인된 실행 경로에만 허용됩니다. 사용자 지정 래퍼·구버전·다른 설치 위치는 `credential_launcher_unverified`로 거절하며, 등록을 명시적으로 전환하거나 업그레이드한 뒤 다시 실행해야 합니다.
@@ -56,6 +93,34 @@ API 키는 macOS Keychain, Linux의 설치된 `secret-tool`, 또는 Windows Cred
56
93
 
57
94
  변경 후 MCP를 재시작하고 `get_routing_capabilities`의 `provider`, 후보 목록, `credential_status`를 확인하십시오. `os_store`는 저장소에서 키를 읽었다는 뜻이며 API 유효성 검증은 아닙니다. 기본 설정과 일반 변수 설정은 기존 사용자 지정 래퍼를 보존합니다. API 키 설정은 호환성이 확인되지 않은 실행 경로의 호스트 설정을 변경하지 않으며, 이미 저장을 시도했다면 해당 호스트의 이전 키를 가능한 경우 복원합니다. 새 키가 기존 래퍼에도 자동 적용된다고 가정하지 마십시오. 명령은 Codex의 `/hooks` 신뢰 승인이나 호스트 권한을 우회하지 않습니다.
58
95
 
96
+ ### 실행 경로 오류 복구
97
+
98
+ 아래 옵션은 Aptly 0.1.2부터 지원하며 npm 0.1.1에는 없습니다. 소스에서 시험하려면 `npm ci --ignore-scripts`와 `npm run build` 후 `aptly` 대신 `node bin/aptly.ts`를 사용합니다.
99
+
100
+ 키 설정은 입력·저장 전에 선택한 호스트를 진단합니다. 하나라도 실패하면 입력을 받지 않고 모든 호스트를 그대로 둡니다. `--check`는 키나 자격 저장소에 접근하지 않습니다. `credential_node_mismatch`, `credential_server_mismatch`, `credential_runtime_unsupported`는 각각 Node 경로, 서버 경로, OS 저장소 지원의 불일치입니다.
101
+
102
+ Claude만 실패했다면 다음 순서로 진단하고, `launcher_migration_available`일 때만 이전을 검토하십시오:
103
+
104
+ ```sh
105
+ aptly set env OPENAI_API_KEY --client claude --check
106
+ aptly setup --client claude --migrate-launcher --dry-run
107
+ aptly setup --client claude --migrate-launcher
108
+ aptly set env OPENAI_API_KEY --client claude
109
+ ```
110
+
111
+ `--dry-run`은 변경하지 않습니다. 이전 명령은 소유 기록과 일치하는 Aptly 표준 등록의 Node·서버 경로를 현재 빌드로 바꿉니다. 기존 환경·Hook·정책·다른 호스트는 보존하며 키를 읽거나 저장하지 않습니다. 오래된 실행 파일을 실행하지 않습니다. 사용자 래퍼, 소유 기록이 없거나 수정된 등록은 거절합니다. 이 경우 로컬에서 등록을 검토하고 래퍼의 안전한 환경 전달을 사용하거나 별도로 검토한 표준 등록으로 전환하십시오. 소유 기록을 삭제하거나 편집해 검증을 우회하지 마십시오.
112
+
113
+ `launcher_migration_not_owned`가 나오고 기존 등록을 보존한 상태(`mcp_created: false`)라면, **Aptly 0.1.3부터** `--include-existing`으로 명시적으로 이전할 수 있습니다. 0.1.3 이상을 설치한 뒤 다음 명령을 실행하십시오:
114
+
115
+ ```sh
116
+ aptly setup --client claude --migrate-launcher --include-existing --dry-run
117
+ aptly setup --client claude --migrate-launcher --include-existing
118
+ ```
119
+
120
+ 실행 전에 로컬 등록을 검토하십시오. 유효한 기존 Aptly 소유 기록과 일치하는 관리 환경변수·Hook·정책이 필요하며, 절대 Node 경로와 단일 표준 서버 경로만 허용합니다. 사용자 래퍼나 기록이 없는 등록은 이 옵션으로도 이전하지 않습니다. 기존 MCP 전체를 Aptly 소유로 바꾸지 않으므로, 이후 `remove`도 이전한 MCP 실행 경로와 원래 사용자 설정을 보존합니다. 이 옵션은 단일 호스트의 명시적 이전에만 사용할 수 있고 자동 설치에는 적용되지 않습니다.
121
+
122
+ 이미 성공한 Codex는 재설정할 필요가 없습니다. 실패한 호스트만 지정해 재시도하고 MCP를 재시작하십시오. Codex를 대상으로 하면 `/hooks` 신뢰 검토가 계속 필요합니다. 진단 이후 설정 변경은 `concurrent_configuration_change`로 중단합니다. 저장 실패 후 다른 키가 관찰되거나 현재 키를 읽지 못하면 덮어쓰지 않고 `credential_rollback_failed`를 반환합니다. 파일과 OS 저장소 사이의 원자적 트랜잭션은 아니므로 다른 설정 작업을 동시에 실행하지 마십시오.
123
+
59
124
  ### 키와 재시작
60
125
 
61
126
  분류용 `OPENAI_API_KEY`를 안전한 환경이나 자격 주입 래퍼를 통해 MCP 프로세스에 전달하십시오. 호스트 구독 로그인과 별개입니다. 키 값을 명령 인자·요청·설정 파일·소스·로그·임시 파일에 기록하지 마십시오.
@@ -129,7 +194,7 @@ APTLY_CODEX_MODELS = '["gpt-6-luna","gpt-6.1-terra","gpt-6.1-sol"]'
129
194
  ### 건너뛰기·제거
130
195
 
131
196
  ```sh
132
- APTLY_SKIP_SETUP=1 npm install -g aptly@0.1.1
197
+ APTLY_SKIP_SETUP=1 npm install -g aptly@latest
133
198
  aptly setup --client codex --mode defaults
134
199
  aptly remove --client all
135
200
  ```
@@ -156,6 +221,20 @@ aptly remove --client all
156
221
  | `get_routing_precedence` | 호출의 보존 근거와 미확인 설정 출처를 설명합니다 |
157
222
  | `route_spawn_hook` | 설치한 정책에 따라 대상 호출의 기본값을 선택하거나 추천만 전달합니다 |
158
223
 
224
+ ### 외부 전송과 자동 공유 끄기
225
+
226
+ 자동 분류의 `summary`는 허용된 작업 라벨과 본문의 **첫 문단을 잘라 붙인 발췌문**입니다. 의미를 새로 요약하거나 익명화하지 않습니다. UTF-8 크기는 `min(4000, max_summary_bytes)` 이하이며 전체 HTTP 요청의 크기 제한은 아닙니다. Codex의 opaque 메시지 fallback은 본문을 해독·전송하지 않고 충분히 구체적인 `task_name`만 사용합니다. 라벨에도 민감한 정보가 들어갈 수 있습니다.
227
+
228
+ Decisions에는 `client`, `task.summary`, `task.operation`, `task.context_sufficient`와 후보 프로필 ID·모델·effort 설명 및 설정된 모델 특성이 전달됩니다. 분류용 API 키는 `Authorization` 헤더로, 요청 ID는 `X-Client-Request-Id` 헤더로 전송됩니다. 자동 경로의 ID는 해시이며 직접 추천의 ID는 호출자가 지정합니다. ID나 후보 설명에도 비밀을 넣지 마십시오.
229
+
230
+ 자동 공유를 끄려면 `APTLY_HOOK_POLICY_PATH`가 가리키는 기존 비공개 정책 파일에서 **`enabled`만 `false`로 변경**하십시오. 나머지 필드와 소유권 기록은 유지하십시오. 이후 자동 Hook 호출은 분류 API나 호출 바인딩 파일을 만들기 전에 원래 호출을 보존합니다. 이미 시작한 전송을 되돌리거나 서버가 받은 내용을 회수하지는 못합니다. 생성된 정책을 바꾸면 설치·설정·제거 명령의 소유권 검사에서 충돌할 수 있으며, 해당 명령은 끄기 설정을 덮어쓰지 않습니다. 소유권 기록을 수정해 검사를 우회하지 마십시오.
231
+
232
+ `mode: advisory`도 분류 정보를 전송하므로 개인정보 보호용 비활성화가 아닙니다. `APTLY_HOOK_POLICY_PATH`를 지우면 기존 strict 경로로 전환될 수 있으므로 공유 끄기의 대안으로 사용하지 마십시오. `enabled: false`는 명시적인 `recommend_agent`·`aptly recommend` 요청까지 차단하지 않습니다.
233
+
234
+ 공유할 요약을 직접 선택하려면 자동 공유를 끈 뒤 직접 추천에 필요한 정보만 작성하십시오. Aptly는 요약에 적은 URL의 문서나 소스 파일을 자동으로 읽어 첨부하지 않습니다. 알려진 키·Bearer 패턴을 거르는 검사는 완전한 비밀 탐지나 전송 안전성 보장이 아닙니다.
235
+
236
+ 원장과 Hook 바인딩에는 요청 메타데이터·해시·캐시 결과를 저장하며 작업 발췌문을 저장하지 않습니다. Aptly의 진단 결과에도 원문을 넣지 않습니다. 다만 로컬 호스트가 실행을 이어가도록 Hook의 `updatedInput`에는 원래 작업이 유지됩니다. 호스트 자체의 대화·로그 저장은 Aptly가 제어하지 않습니다.
237
+
159
238
  ## 직접 추천
160
239
 
161
240
  `recommend_agent` MCP와 CLI `recommend`는 작업 요약을 받아 프로필을 추천합니다. 자식을 직접 생성하지 않습니다. 아래 JSON을 MCP 도구 인자로 전달하거나 파일에 저장해 CLI의 표준 입력으로 제공하십시오.
@@ -254,6 +333,14 @@ Codex가 자식 `message`를 암호문으로 Hook에 전달하는 환경에서
254
333
 
255
334
  측정은 **명시적 MCP 추천 → 추천 프로필을 인자로 전달한 호스트의 기본 실행**입니다. 자동 Hook의 URL 수집·전달 기능 검증이 아닙니다. 기준군은 직전 실측을 재사용했고 조건별 표본은 3회입니다. 문서 전체 읽기·원문 인용 일치·출력 형식은 확인했지만 품질 동등성, 통계적 유의성, 다른 업무의 절감을 보장하지 않습니다.
256
335
 
336
+ ### 중단된 프로세스와 원장 잠금
337
+
338
+ 이 잠금 방식은 Aptly `0.1.2`부터 지원하며 npm `0.1.1`에는 없습니다. JSON 원장의 요청 ID·`unknown`·완료 캐시·호출 수·비용 예약 형식은 유지합니다. 영속 원장에만 Node.js 24 내장 SQLite를 사용하며, 원장 옆의 `ledger.json.lock`은 정상 종료 후에도 남는 잠금 파일입니다. 파일이 있다는 사실만으로 활성 잠금을 뜻하지 않습니다. 새 방식에서는 프로세스 종료 시 OS 잠금이 해제되므로 후속 요청이 같은 원장을 다시 사용할 수 있습니다. 결과가 불명확했던 기존 ID를 재호출하거나 예약 비용을 되돌리지는 않습니다.
339
+
340
+ 원장과 잠금 파일은 하드 링크를 지원하는 로컬 파일시스템의 비공개 디렉터리에 두고, 하나의 원장을 동일한 정규 경로로 사용하십시오. 네트워크 공유·클라우드 동기화 디렉터리·경로 별칭은 지원 범위가 아닙니다. 새 잠금 파일과 SQLite journal을 삭제·교체하거나, 사용 중 다른 DB 도구로 열지 마십시오. 잠금 파일의 나이와 PID만으로 소유자가 종료됐다고 판단하지 않습니다.
341
+
342
+ 이전 버전의 빈 `.lock` 파일은 살아 있는 소유자가 있는지 확인할 수 없어 자동으로 초기화하거나 제거하지 않습니다. 구버전을 포함한 모든 관련 호스트·MCP·원장 접근 프로세스를 정지하고, 모든 writer를 새 버전으로 전환하십시오. 파일이 기존 방식의 잠금임을 확인한 경우에만 그 파일을 별도로 격리한 뒤 같은 JSON 원장 경로로 다시 시작합니다. 원장·`unknown`·비용·완료 결과는 초기화하거나 삭제하지 마십시오. 소유자나 형식을 확신할 수 없으면 차단 상태를 유지하고 조사하십시오.
343
+
257
344
  ## 진단과 개발
258
345
 
259
346
  ```sh