caveat-cli 0.17.8 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -28
- package/dist/{chunk-ZBHCOA6R.js → chunk-ULK7SZG6.js} +75 -94
- package/dist/{chunk-ZBHCOA6R.js.map → chunk-ULK7SZG6.js.map} +1 -1
- package/dist/index.js +835 -372
- package/dist/index.js.map +1 -1
- package/dist/{server-GBVHOF67.js → server-H6MVY5OK.js} +2 -2
- package/package.json +17 -17
- /package/dist/{server-GBVHOF67.js.map → server-H6MVY5OK.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,47 +1,72 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/kitepon
|
|
2
|
+
<img src="https://raw.githubusercontent.com/kitepon/Caveat/main/.github/og.png" alt="Caveat — long-term memory layer for coding agents" width="100%">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# Caveat
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/caveat-cli)
|
|
8
|
-
[](https://github.com/kitepon
|
|
8
|
+
[](https://github.com/kitepon/Caveat/actions/workflows/ci.yml)
|
|
9
|
+
[](https://github.com/kitepon/Caveat/blob/main/LICENSE)
|
|
10
10
|
|
|
11
|
-
> **Stop rediscovering the same trap.** Caveat is a long-term memory layer for Claude Code and
|
|
11
|
+
> **Stop rediscovering the same trap.** Caveat is a long-term memory layer for Claude Code, Codex, and Cursor: record a hard-won external-spec quirk or repo-specific oddity once, and the relevant note surfaces before an AI repeats it.
|
|
12
12
|
|
|
13
|
-
🇯🇵 **日本語版**: [README.ja.md](https://github.com/kitepon
|
|
13
|
+
🇯🇵 **日本語版**: [README.ja.md](https://github.com/kitepon/Caveat/blob/main/README.ja.md)
|
|
14
14
|
|
|
15
15
|
Built and maintained by [Quo](https://x.com/QLyun35332) at [kitepon.dev](https://kitepon.dev/en).
|
|
16
16
|
|
|
17
|
-
**Source / full docs**: [github.com/kitepon
|
|
17
|
+
**Source / full docs**: [github.com/kitepon/Caveat](https://github.com/kitepon/Caveat)
|
|
18
18
|
|
|
19
19
|
## Install
|
|
20
20
|
|
|
21
21
|
```sh
|
|
22
22
|
npm install -g caveat-cli
|
|
23
|
-
caveat init #
|
|
24
|
-
caveat codex-hook install # optional: native Codex hooks
|
|
23
|
+
caveat init # state + available Claude/Codex/Cursor integrations
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
On macOS with Homebrew Node, Caveat installs hook commands through the stable
|
|
28
27
|
`/opt/homebrew/bin/node` symlink when it points at the current Node binary. This
|
|
29
|
-
keeps Claude Code and
|
|
28
|
+
keeps Claude Code, Codex, and Cursor hooks working after Homebrew moves Node between
|
|
30
29
|
`/opt/homebrew/Cellar/node/<version>/...` directories.
|
|
31
30
|
|
|
32
|
-
`caveat init` (idempotent, `--dry-run` supported) does the
|
|
31
|
+
`caveat init` (idempotent, `--dry-run` supported) does the product setup:
|
|
33
32
|
|
|
34
33
|
1. Scaffolds `~/.caveat/own/` (your personal knowledge repo) + `~/.caveat/index/caveat.db`
|
|
35
|
-
2.
|
|
34
|
+
2. Claudeのuser設定へMCPを登録し、既存の環境変数と他の登録を保持
|
|
36
35
|
3. Merges `UserPromptSubmit` / `PostToolUse` / `PostToolUseFailure` / `Stop` hooks into `~/.claude/settings.json` (existing entries preserved, backup written before any change)
|
|
36
|
+
4. Installs product-owned Codex and Cursor hooks when those hosts are available
|
|
37
|
+
|
|
38
|
+
同じ`init`がCodex・Grok・CursorへもMCPを登録します。CodexはCLIまたは設定ディレクトリ、Grok・Cursorは
|
|
39
|
+
設定ディレクトリの存在で導入対象を決めます。`CODEX_HOME` / `GROK_HOME` / `CURSOR_HOME` /
|
|
40
|
+
`CLAUDE_CONFIG_DIR`を尊重し、既存の環境変数・timeout・無効化指定・他の登録を保持します。
|
|
41
|
+
設定変更前のバックアップと読戻しを行い、MCP登録失敗は非0終了します。
|
|
42
|
+
`--skip-codex-hook` / `--skip-cursor-hook`はhookだけを省略します。
|
|
43
|
+
|
|
44
|
+
private remoteの初期化・同期は`caveat init --sync --yes`で完結します。端末でも質問を挟まず、
|
|
45
|
+
公開ミラーは明示しなければ変更しません。新規remoteの作成には認証済みの`gh`が必要です。
|
|
46
|
+
It uses the account already authenticated in `gh`, is idempotent, and exits
|
|
47
|
+
non-zero if the explicitly requested sync fails. Callers do not inspect product
|
|
48
|
+
state or run separate Caveat hook installers around this entry.
|
|
37
49
|
|
|
38
50
|
Opt-out: `--skip-claude`. `caveat uninstall` reverses the Claude Code changes without touching `~/.caveat/`. **No central DB is auto-subscribed** — add knowledge sources explicitly with `caveat community add`.
|
|
39
51
|
|
|
40
|
-
For Codex, run `caveat codex-hook diagnostics` first
|
|
52
|
+
For a targeted Codex repair, run `caveat codex-hook diagnostics` first,
|
|
41
53
|
then `caveat codex-hook install`. It registers Caveat-owned
|
|
42
54
|
`UserPromptSubmit`, `PostToolUse`, and `Stop` entries in `~/.codex/hooks.json`
|
|
43
55
|
and enables Codex's native hook runtime.
|
|
44
56
|
|
|
57
|
+
For a targeted Cursor repair, run `caveat cursor-hook install`. It upserts Caveat-owned
|
|
58
|
+
`beforeSubmitPrompt`, `postToolUse`, `postToolUseFailure`, and `stop` entries
|
|
59
|
+
in `~/.cursor/hooks.json` while preserving unrelated hooks. Use
|
|
60
|
+
`caveat cursor-hook diagnostics` to inspect the installed contract.
|
|
61
|
+
|
|
62
|
+
Automation uses the aggregate product contract instead:
|
|
63
|
+
`caveat factory-diagnostics --json --require-connector cursor`. Its versioned
|
|
64
|
+
schema, top-level `overall.status`, and exit status are the complete gate. The
|
|
65
|
+
output also exposes `connectors.cursor.compatibility_status` for diagnosis,
|
|
66
|
+
but callers do not duplicate Caveat's Cursor event set, command rules, or
|
|
67
|
+
timeout checks. Without `--require-connector cursor`, the v1 aggregate keeps
|
|
68
|
+
its existing Claude/Codex readiness semantics.
|
|
69
|
+
|
|
45
70
|
With either host enabled, Caveat surfaces matching entries at three moments:
|
|
46
71
|
before prompts, after failed tools, and after struggle-heavy sessions. Stop
|
|
47
72
|
reminders are queued for the next context-capable hook tick so the agent's final
|
|
@@ -60,29 +85,38 @@ caveat pull # community pull + re-index everything
|
|
|
60
85
|
caveat serve # http://localhost:4242 read-only portal
|
|
61
86
|
caveat uninstall # reverse `caveat init` Claude integration
|
|
62
87
|
caveat codex-hook diagnostics # inspect Codex hook availability/install state
|
|
88
|
+
caveat factory-diagnostics --json --require-connector cursor
|
|
89
|
+
# machine gate for a host that requires Cursor
|
|
63
90
|
```
|
|
64
91
|
|
|
65
|
-
## Sharing
|
|
66
|
-
|
|
67
|
-
There is no `caveat push` (since v0.7). To share with teammates, use plain git:
|
|
92
|
+
## Sharing: two boundaries, two commands
|
|
68
93
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
94
|
+
- `caveat sync` synchronizes both private and public entries to an authenticated,
|
|
95
|
+
non-anonymously-readable private remote owned by you or your group.
|
|
96
|
+
- `caveat publish` writes only public entries to a separate public mirror. It
|
|
97
|
+
publishes a deterministic AES-256-GCM sealed bundle plus README metadata;
|
|
98
|
+
subscribers decrypt in-process with the configured keyserver.
|
|
72
99
|
|
|
73
|
-
|
|
100
|
+
The publish scan fails closed if private content, an invalid destination, or
|
|
101
|
+
missing keyserver configuration is detected. Trust in a private source is still
|
|
102
|
+
social — subscribers choose which repository owners to trust.
|
|
74
103
|
|
|
75
104
|
## MCP tools (6)
|
|
76
105
|
|
|
77
|
-
|
|
106
|
+
`caveat init`が登録するMCPを通じて、Claude Code・Codex・Grok・Cursorから利用できます。
|
|
78
107
|
|
|
79
108
|
`caveat_search`, `caveat_get`, `caveat_record`, `caveat_update`, `caveat_list_recent`, `caveat_pull`.
|
|
80
109
|
|
|
81
|
-
Claude can autonomously pull subscribed-repo updates (safe, idempotent).
|
|
110
|
+
Claude can autonomously pull subscribed-repo updates (safe, idempotent).
|
|
111
|
+
Recording and updating writes locally; use `caveat sync` for the private
|
|
112
|
+
ownership boundary and `caveat publish` for the public sealed boundary.
|
|
82
113
|
|
|
83
|
-
Codex
|
|
84
|
-
|
|
85
|
-
|
|
114
|
+
Codex and Cursor use native hooks rather than MCP for automatic surfacing. A
|
|
115
|
+
native reminder inspects an entry with
|
|
116
|
+
`caveat show <id> --source <source>`, then updates or creates Markdown in the
|
|
117
|
+
own knowledge repo and runs `caveat index`. Community entries are subscriptions
|
|
118
|
+
and are not edited locally. The optional `codex-sidecar` commands remain
|
|
119
|
+
available for bounded second opinions, review, risk-check, and isolated work.
|
|
86
120
|
|
|
87
121
|
## Pointing at a different knowledge repo
|
|
88
122
|
|
|
@@ -92,21 +126,38 @@ If you want `~/.caveat/own/` to live elsewhere (e.g. a git-tracked directory you
|
|
|
92
126
|
{ "knowledgeRepo": "/absolute/path/to/your/caveats-repo" }
|
|
93
127
|
```
|
|
94
128
|
|
|
129
|
+
## Runtime error diagnostics (explicit opt-in)
|
|
130
|
+
|
|
131
|
+
Local runtime error collection is disabled by default. Enable it in the same
|
|
132
|
+
`~/.caveatrc.json` file while preserving any existing keys:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "runtimeErrors": true }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Use `caveat runtime-errors diagnostics --json` and
|
|
139
|
+
`caveat runtime-errors snapshot --json` to inspect it. The lifecycle commands
|
|
140
|
+
are `ack <cursor>`, `resolve <fingerprint>`, `reopen <fingerprint>`, and
|
|
141
|
+
`compact`; each requires `--json`. A missing key or any value other than the
|
|
142
|
+
boolean `true` keeps collection disabled. Runtime state lives under Caveat's
|
|
143
|
+
own state directory, independently of the knowledge index and host hook files.
|
|
144
|
+
|
|
95
145
|
## Requirements
|
|
96
146
|
|
|
97
147
|
- Node 22.5+ (for built-in `node:sqlite`)
|
|
148
|
+
- WindowsではPowerShell 7(`pwsh.exe`)を使います。エラー収集用ストレージのACL処理も同じ入口です。
|
|
98
149
|
- `git` for `caveat community add` / `caveat community pull`
|
|
99
150
|
- Claude Code installed if you want Claude MCP / hooks integration. Without it, `caveat init --skip-claude` still provisions local state.
|
|
100
151
|
- Codex installed if you want native Codex hooks via `caveat codex-hook install`.
|
|
152
|
+
- Cursor installed if you want native Cursor hooks via `caveat cursor-hook install`.
|
|
101
153
|
|
|
102
154
|
Release install smoke:
|
|
103
155
|
|
|
104
156
|
```sh
|
|
105
|
-
npm
|
|
106
|
-
npm install -g caveat-cli
|
|
157
|
+
npm install -g caveat-cli@latest
|
|
107
158
|
caveat --version
|
|
108
|
-
caveat init
|
|
109
|
-
caveat
|
|
159
|
+
caveat init --sync --yes
|
|
160
|
+
caveat factory-diagnostics --json --require-connector cursor
|
|
110
161
|
```
|
|
111
162
|
|
|
112
163
|
## License
|
|
@@ -5122,10 +5122,10 @@ var require_truncate = __commonJS({
|
|
|
5122
5122
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/truncate.js"(exports2, module2) {
|
|
5123
5123
|
"use strict";
|
|
5124
5124
|
var parse2 = require_parse2();
|
|
5125
|
-
var
|
|
5125
|
+
var constants = require_constants();
|
|
5126
5126
|
var SemVer = require_semver();
|
|
5127
5127
|
var truncate2 = (version, truncation, options2) => {
|
|
5128
|
-
if (!
|
|
5128
|
+
if (!constants.RELEASE_TYPES.includes(truncation)) {
|
|
5129
5129
|
return null;
|
|
5130
5130
|
}
|
|
5131
5131
|
const clonedVersion = cloneInputVersion(version, options2);
|
|
@@ -6174,7 +6174,7 @@ var require_semver2 = __commonJS({
|
|
|
6174
6174
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/index.js"(exports2, module2) {
|
|
6175
6175
|
"use strict";
|
|
6176
6176
|
var internalRe = require_re();
|
|
6177
|
-
var
|
|
6177
|
+
var constants = require_constants();
|
|
6178
6178
|
var SemVer = require_semver();
|
|
6179
6179
|
var identifiers = require_identifiers();
|
|
6180
6180
|
var parse2 = require_parse2();
|
|
@@ -6258,8 +6258,8 @@ var require_semver2 = __commonJS({
|
|
|
6258
6258
|
re: internalRe.re,
|
|
6259
6259
|
src: internalRe.src,
|
|
6260
6260
|
tokens: internalRe.t,
|
|
6261
|
-
SEMVER_SPEC_VERSION:
|
|
6262
|
-
RELEASE_TYPES:
|
|
6261
|
+
SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
|
|
6262
|
+
RELEASE_TYPES: constants.RELEASE_TYPES,
|
|
6263
6263
|
compareIdentifiers: identifiers.compareIdentifiers,
|
|
6264
6264
|
rcompareIdentifiers: identifiers.rcompareIdentifiers
|
|
6265
6265
|
};
|
|
@@ -15237,6 +15237,9 @@ function createKeyserverKeyProvider(opts) {
|
|
|
15237
15237
|
function isWindows(platform = process.platform) {
|
|
15238
15238
|
return platform === "win32";
|
|
15239
15239
|
}
|
|
15240
|
+
function isWindowsEnv(env, platform = process.platform) {
|
|
15241
|
+
return env.OS === "Windows_NT" || isWindows(platform);
|
|
15242
|
+
}
|
|
15240
15243
|
function isPrivateOwnerStat(stat, uid, platform = process.platform) {
|
|
15241
15244
|
return isWindows(platform) || (stat.mode & 63) === 0 && (uid === void 0 || stat.uid === uid);
|
|
15242
15245
|
}
|
|
@@ -15251,7 +15254,7 @@ function normalizePathCase(normalizedPath, platform = process.platform) {
|
|
|
15251
15254
|
}
|
|
15252
15255
|
|
|
15253
15256
|
// ../../packages/core/dist/sync.js
|
|
15254
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync7, realpathSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15257
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync7, readdirSync as readdirSync7, realpathSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15255
15258
|
import { dirname as dirname4, join as join8, resolve } from "node:path";
|
|
15256
15259
|
|
|
15257
15260
|
// ../../packages/core/dist/remoteVisibility.js
|
|
@@ -15459,6 +15462,12 @@ function scaffold(ownDir) {
|
|
|
15459
15462
|
const gitignore = join8(ownDir, ".gitignore");
|
|
15460
15463
|
if (!existsSync8(gitignore)) writeFileSync4(gitignore, KNOWLEDGE_GITIGNORE, "utf-8");
|
|
15461
15464
|
}
|
|
15465
|
+
function removeCanonicalScaffoldBeforeCheckout(ownDir) {
|
|
15466
|
+
const gitignore = join8(ownDir, ".gitignore");
|
|
15467
|
+
if (existsSync8(gitignore) && readFileSync7(gitignore, "utf-8") === KNOWLEDGE_GITIGNORE) {
|
|
15468
|
+
rmSync4(gitignore);
|
|
15469
|
+
}
|
|
15470
|
+
}
|
|
15462
15471
|
async function defaultRemoteBranch(git, url) {
|
|
15463
15472
|
const symref = await git.raw(["ls-remote", "--symref", url, "HEAD"]);
|
|
15464
15473
|
const match = /^ref: refs\/heads\/([^\s]+)\s+HEAD$/m.exec(symref);
|
|
@@ -15498,6 +15507,7 @@ async function initOwnSync(opts) {
|
|
|
15498
15507
|
}
|
|
15499
15508
|
const branch = await defaultRemoteBranch(git, opts.url);
|
|
15500
15509
|
await git.fetch("origin", branch);
|
|
15510
|
+
removeCanonicalScaffoldBeforeCheckout(ownDir);
|
|
15501
15511
|
await git.checkout(["--track", "-B", branch, `origin/${branch}`]);
|
|
15502
15512
|
await reindexAndMark(opts);
|
|
15503
15513
|
return { ownDir, branch, remoteWasEmpty: false };
|
|
@@ -15516,7 +15526,7 @@ function errorMessage2(err) {
|
|
|
15516
15526
|
// ../../packages/core/dist/autoSync.js
|
|
15517
15527
|
import { spawn as spawn2 } from "node:child_process";
|
|
15518
15528
|
import { createHash as createHash4 } from "node:crypto";
|
|
15519
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as
|
|
15529
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync8, renameSync as renameSync3, statSync as statSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
15520
15530
|
import { dirname as dirname5, join as join9 } from "node:path";
|
|
15521
15531
|
var AUTO_SYNC_DEBOUNCE_MS = 15 * 60 * 1e3;
|
|
15522
15532
|
var AUTO_SYNC_RECORD_DEBOUNCE_MS = 60 * 1e3;
|
|
@@ -15536,7 +15546,7 @@ function autoSyncLockPath(caveatHome) {
|
|
|
15536
15546
|
}
|
|
15537
15547
|
function readAutoSyncState(caveatHome) {
|
|
15538
15548
|
try {
|
|
15539
|
-
const value = JSON.parse(
|
|
15549
|
+
const value = JSON.parse(readFileSync8(autoSyncStatePath(caveatHome), "utf-8"));
|
|
15540
15550
|
if (!isAutoSyncState(value)) return null;
|
|
15541
15551
|
return value;
|
|
15542
15552
|
} catch {
|
|
@@ -15888,16 +15898,17 @@ function resolvePaths(caveatHome, knowledgeRepo, userHome) {
|
|
|
15888
15898
|
}
|
|
15889
15899
|
|
|
15890
15900
|
// ../../packages/core/dist/config.js
|
|
15891
|
-
import { existsSync as existsSync11, readFileSync as
|
|
15901
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
15892
15902
|
var DEFAULT_CONFIG = {
|
|
15893
15903
|
knowledgeRepo: "own",
|
|
15894
15904
|
semverKeys: ["driver", "cuda", "node"],
|
|
15895
15905
|
publishTarget: null,
|
|
15896
15906
|
sealedKeyId: "v1",
|
|
15897
|
-
sealedKeyserverUrl: null
|
|
15907
|
+
sealedKeyserverUrl: null,
|
|
15908
|
+
runtimeErrors: false
|
|
15898
15909
|
};
|
|
15899
15910
|
function loadConfig(userConfigPath) {
|
|
15900
|
-
const userCfg = existsSync11(userConfigPath) ? JSON.parse(
|
|
15911
|
+
const userCfg = existsSync11(userConfigPath) ? JSON.parse(readFileSync9(userConfigPath, "utf-8")) : {};
|
|
15901
15912
|
return deepMerge(DEFAULT_CONFIG, userCfg);
|
|
15902
15913
|
}
|
|
15903
15914
|
function ensureUserConfig(userConfigPath) {
|
|
@@ -15906,7 +15917,7 @@ function ensureUserConfig(userConfigPath) {
|
|
|
15906
15917
|
}
|
|
15907
15918
|
}
|
|
15908
15919
|
function writeUserConfigPatch(userConfigPath, patch) {
|
|
15909
|
-
const existing = existsSync11(userConfigPath) ? JSON.parse(
|
|
15920
|
+
const existing = existsSync11(userConfigPath) ? JSON.parse(readFileSync9(userConfigPath, "utf-8")) : {};
|
|
15910
15921
|
writeFileSync6(userConfigPath, `${JSON.stringify({ ...existing, ...patch }, null, 2)}
|
|
15911
15922
|
`, "utf-8");
|
|
15912
15923
|
}
|
|
@@ -16125,7 +16136,19 @@ function reminderSymptomLine(symptomExcerpt) {
|
|
|
16125
16136
|
const excerpt2 = sanitizeReminderDisplay(symptomExcerpt, SYMPTOM_LINE_MAX);
|
|
16126
16137
|
return excerpt2 ? ` \u75C7\u72B6: ${excerpt2}` : null;
|
|
16127
16138
|
}
|
|
16128
|
-
function
|
|
16139
|
+
function detailGuidance(surface) {
|
|
16140
|
+
if (surface === "native-cli") {
|
|
16141
|
+
return "\u8A73\u7D30\u306F `caveat show <id> --source <source>` \u3067\u53D6\u5F97\u3057\u3001documented \u306A\u5BFE\u51E6\u3068 environment \u304C\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304B\u3089\u9069\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002";
|
|
16142
|
+
}
|
|
16143
|
+
return "mcp__caveat__caveat_get \u3067\u8A73\u7D30\u3092\u78BA\u8A8D\u3057\u3001documented \u306A\u5BFE\u51E6\u304C\u3042\u308C\u3070\u9069\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002";
|
|
16144
|
+
}
|
|
16145
|
+
function promptDetailGuidance(surface) {
|
|
16146
|
+
if (surface === "native-cli") {
|
|
16147
|
+
return "\u8A73\u7D30\u306F `caveat show <id> --source <source>` \u3067\u53D6\u5F97\u3002environment \u304C\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304B\u3089\u9069\u7528\u5224\u65AD\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002";
|
|
16148
|
+
}
|
|
16149
|
+
return "\u8A73\u7D30\u306F mcp__caveat__caveat_get \u306B id + source \u3092\u6E21\u3057\u3066\u53D6\u5F97\u3002environment \u304C\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304B\u3089\u9069\u7528\u5224\u65AD\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002";
|
|
16150
|
+
}
|
|
16151
|
+
function toolErrorReminderText(hits, actionSurface = "claude-mcp") {
|
|
16129
16152
|
const lines = [];
|
|
16130
16153
|
lines.push(
|
|
16131
16154
|
`[caveat] \u76F4\u524D\u306E\u30A8\u30E9\u30FC\u306B\u4E00\u81F4\u3059\u308B\u53EF\u80FD\u6027\u306E\u3042\u308B\u65E2\u77E5\u306E\u7F60\u304C ${hits.length} \u4EF6\u3042\u308A\u307E\u3059:`
|
|
@@ -16137,12 +16160,10 @@ function toolErrorReminderText(hits) {
|
|
|
16137
16160
|
if (symptomLine) lines.push(symptomLine);
|
|
16138
16161
|
});
|
|
16139
16162
|
lines.push("");
|
|
16140
|
-
lines.push(
|
|
16141
|
-
"mcp__caveat__caveat_get \u3067\u8A73\u7D30\u3092\u78BA\u8A8D\u3057\u3001documented \u306A\u5BFE\u51E6\u304C\u3042\u308C\u3070\u9069\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002"
|
|
16142
|
-
);
|
|
16163
|
+
lines.push(detailGuidance(actionSurface));
|
|
16143
16164
|
return lines.join("\n");
|
|
16144
16165
|
}
|
|
16145
|
-
function userPromptSubmitReminderText(hits) {
|
|
16166
|
+
function userPromptSubmitReminderText(hits, actionSurface = "claude-mcp") {
|
|
16146
16167
|
const lines = [];
|
|
16147
16168
|
lines.push(
|
|
16148
16169
|
`[caveat] \u3053\u306E\u30D7\u30ED\u30F3\u30D7\u30C8\u306B\u95A2\u9023\u3059\u308B\u53EF\u80FD\u6027\u306E\u3042\u308B\u65E2\u77E5\u306E\u7F60\u304C ${hits.length} \u4EF6\u3042\u308A\u307E\u3059:`
|
|
@@ -16154,16 +16175,14 @@ function userPromptSubmitReminderText(hits) {
|
|
|
16154
16175
|
if (symptomLine) lines.push(symptomLine);
|
|
16155
16176
|
});
|
|
16156
16177
|
lines.push("");
|
|
16157
|
-
lines.push(
|
|
16158
|
-
"\u8A73\u7D30\u306F mcp__caveat__caveat_get \u306B id + source \u3092\u6E21\u3057\u3066\u53D6\u5F97\u3002environment \u304C\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304B\u3089\u9069\u7528\u5224\u65AD\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7121\u95A2\u4FC2\u3068\u5224\u65AD\u3057\u305F\u3089\u7121\u8996\u3057\u3066\u7D9A\u884C\u3067 OK\u3002"
|
|
16159
|
-
);
|
|
16178
|
+
lines.push(promptDetailGuidance(actionSurface));
|
|
16160
16179
|
return lines.join("\n");
|
|
16161
16180
|
}
|
|
16162
16181
|
function shortPath(p2) {
|
|
16163
16182
|
const parts = p2.split(/[\\/]/);
|
|
16164
16183
|
return parts[parts.length - 1] ?? p2;
|
|
16165
16184
|
}
|
|
16166
|
-
function stopReminderText(signals, related) {
|
|
16185
|
+
function stopReminderText(signals, related, actionSurface = "claude-mcp") {
|
|
16167
16186
|
const lines = [];
|
|
16168
16187
|
lines.push("[caveat] \u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u5916\u90E8\u4ED5\u69D8\u306E\u7F60\u306B\u5F53\u305F\u3063\u305F\u53EF\u80FD\u6027\u3092\u793A\u3059\u30B7\u30B0\u30CA\u30EB:");
|
|
16169
16188
|
if (signals.toolFailureCount > 0) {
|
|
@@ -16193,29 +16212,21 @@ function stopReminderText(signals, related) {
|
|
|
16193
16212
|
);
|
|
16194
16213
|
lines.push("");
|
|
16195
16214
|
if (related.length > 0) {
|
|
16196
|
-
lines.push(
|
|
16197
|
-
`\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u5BB9\u3068\u5171\u8D77\u3059\u308B\u65E2\u5B58\u7F60 ${related.length} \u4EF6\uFF08\u95A2\u9023\u304C\u3042\u308C\u3070 mcp__caveat__caveat_update \u3067 last_verified \u3092\u66F4\u65B0 or \u8FFD\u8A18\uFF09:`
|
|
16198
|
-
);
|
|
16215
|
+
lines.push(actionSurface === "native-cli" ? `\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u5BB9\u3068\u5171\u8D77\u3059\u308B\u65E2\u5B58\u7F60 ${related.length} \u4EF6\uFF08\u8A73\u7D30\u306F \`caveat show <id> --source <source>\` \u3067\u78BA\u8A8D\uFF09:` : `\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u5BB9\u3068\u5171\u8D77\u3059\u308B\u65E2\u5B58\u7F60 ${related.length} \u4EF6\uFF08\u95A2\u9023\u304C\u3042\u308C\u3070 mcp__caveat__caveat_update \u3067 last_verified \u3092\u66F4\u65B0 or \u8FFD\u8A18\uFF09:`);
|
|
16199
16216
|
related.forEach((h2, i2) => {
|
|
16200
16217
|
lines.push(reminderHitLine(h2, i2));
|
|
16201
16218
|
});
|
|
16202
16219
|
lines.push("");
|
|
16203
|
-
lines.push(
|
|
16204
|
-
"\u4E0A\u8A18\u3068\u7570\u306A\u308B\u65B0\u898F\u306E\u7F60\u3092\u8E0F\u3093\u3067\u3044\u305F\u3089 mcp__caveat__caveat_record \u3067\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible\uFF08\u73FE\u72B6\u306E\u5236\u7D04\u3067\u306F\u4E0D\u53EF\u80FD\u3068\u5224\u5B9A\u3057\u305F\u7D50\u8AD6\uFF09\u3082\u8A18\u9332\u5BFE\u8C61\u3002"
|
|
16205
|
-
);
|
|
16220
|
+
lines.push(actionSurface === "native-cli" ? "\u95A2\u9023\u3059\u308B own \u30A8\u30F3\u30C8\u30EA\u306F `caveat show <id> --source own` \u304C\u793A\u3059 path \u306E Markdown\u3067 last_verified \u3084\u672C\u6587\u3092\u66F4\u65B0\u3057\u3001`caveat index` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002community \u30A8\u30F3\u30C8\u30EA\u306F\u8CFC\u8AAD\u7269\u306A\u306E\u3067\u76F4\u63A5\u7DE8\u96C6\u3057\u307E\u305B\u3093\u3002\u4E0A\u8A18\u3068\u7570\u306A\u308B\u65B0\u898F\u306E\u7F60\u306F Caveat \u306E own knowledge repo \u3078 Markdown \u3067\u8A18\u9332\u3057\u3001`caveat index` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible\uFF08\u73FE\u72B6\u306E\u5236\u7D04\u3067\u306F\u4E0D\u53EF\u80FD\u3068\u5224\u5B9A\u3057\u305F\u7D50\u8AD6\uFF09\u3082\u8A18\u9332\u5BFE\u8C61\u3002" : "\u4E0A\u8A18\u3068\u7570\u306A\u308B\u65B0\u898F\u306E\u7F60\u3092\u8E0F\u3093\u3067\u3044\u305F\u3089 mcp__caveat__caveat_record \u3067\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible\uFF08\u73FE\u72B6\u306E\u5236\u7D04\u3067\u306F\u4E0D\u53EF\u80FD\u3068\u5224\u5B9A\u3057\u305F\u7D50\u8AD6\uFF09\u3082\u8A18\u9332\u5BFE\u8C61\u3002");
|
|
16206
16221
|
} else {
|
|
16207
|
-
lines.push(
|
|
16208
|
-
"\u65E2\u5B58\u7F60\u306B\u8A72\u5F53\u306A\u3057\u3002\u5916\u90E8\u4ED5\u69D8\u306E\u7F60\u306B\u82E6\u6226\u3057\u3066\u3044\u305F\u306A\u3089 mcp__caveat__caveat_record \u3067\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible \u3082\u8A18\u9332\u5BFE\u8C61\u3002"
|
|
16209
|
-
);
|
|
16222
|
+
lines.push(actionSurface === "native-cli" ? "\u65E2\u5B58\u7F60\u306B\u8A72\u5F53\u306A\u3057\u3002\u5916\u90E8\u4ED5\u69D8\u306E\u7F60\u306B\u82E6\u6226\u3057\u3066\u3044\u305F\u306A\u3089 Caveat \u306E own knowledge repo \u3078 Markdown \u3067\u8A18\u9332\u3057\u3001`caveat index` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible \u3082\u8A18\u9332\u5BFE\u8C61\u3002" : "\u65E2\u5B58\u7F60\u306B\u8A72\u5F53\u306A\u3057\u3002\u5916\u90E8\u4ED5\u69D8\u306E\u7F60\u306B\u82E6\u6226\u3057\u3066\u3044\u305F\u306A\u3089 mcp__caveat__caveat_record \u3067\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002outcome: impossible \u3082\u8A18\u9332\u5BFE\u8C61\u3002");
|
|
16210
16223
|
}
|
|
16211
|
-
lines.push(
|
|
16212
|
-
"\u8A18\u9332\u6642\u306F tool \u8AAC\u660E\u306E\u4E8C\u9805\u57FA\u6E96\u3067 visibility \u3092\u9078\u3076\uFF08public = \u7B2C\u4E09\u8005\u518D\u73FE\u53EF\u80FD / private = repo \u56FA\u6709\uFF09\u3002\u8FF7\u3063\u305F\u3089 private\u3002"
|
|
16213
|
-
);
|
|
16224
|
+
lines.push(actionSurface === "native-cli" ? "\u8A18\u9332\u6642\u306F visibility \u3092\u4E8C\u9805\u57FA\u6E96\u3067\u9078\u3076\uFF08public = \u7B2C\u4E09\u8005\u518D\u73FE\u53EF\u80FD / private = repo \u56FA\u6709\uFF09\u3002\u8FF7\u3063\u305F\u3089 private\u3002" : "\u8A18\u9332\u6642\u306F tool \u8AAC\u660E\u306E\u4E8C\u9805\u57FA\u6E96\u3067 visibility \u3092\u9078\u3076\uFF08public = \u7B2C\u4E09\u8005\u518D\u73FE\u53EF\u80FD / private = repo \u56FA\u6709\uFF09\u3002\u8FF7\u3063\u305F\u3089 private\u3002");
|
|
16214
16225
|
return lines.join("\n");
|
|
16215
16226
|
}
|
|
16216
16227
|
|
|
16217
16228
|
// ../../packages/core/dist/transcriptSignals.js
|
|
16218
|
-
import { existsSync as existsSync12, readFileSync as
|
|
16229
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
|
|
16219
16230
|
var MAX_ERROR_SNIPPETS = 10;
|
|
16220
16231
|
var MAX_ERROR_SNIPPET_LENGTH = 300;
|
|
16221
16232
|
var MAX_SEARCH_QUERIES = 10;
|
|
@@ -16244,7 +16255,7 @@ function readSessionSignals(transcriptPath) {
|
|
|
16244
16255
|
if (!transcriptPath || !existsSync12(transcriptPath)) return null;
|
|
16245
16256
|
let raw;
|
|
16246
16257
|
try {
|
|
16247
|
-
raw =
|
|
16258
|
+
raw = readFileSync10(transcriptPath, "utf-8");
|
|
16248
16259
|
} catch {
|
|
16249
16260
|
return null;
|
|
16250
16261
|
}
|
|
@@ -16325,7 +16336,7 @@ function struggleSearchText(s) {
|
|
|
16325
16336
|
}
|
|
16326
16337
|
|
|
16327
16338
|
// ../../packages/core/dist/codexTranscriptSignals.js
|
|
16328
|
-
import { existsSync as existsSync13, readFileSync as
|
|
16339
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
|
|
16329
16340
|
var MAX_ERROR_SNIPPETS2 = 10;
|
|
16330
16341
|
var MAX_ERROR_SNIPPET_LENGTH2 = 300;
|
|
16331
16342
|
var MAX_SEARCH_QUERIES2 = 10;
|
|
@@ -16393,7 +16404,7 @@ function readCodexSessionSignals(transcriptPath) {
|
|
|
16393
16404
|
if (!transcriptPath || !existsSync13(transcriptPath)) return null;
|
|
16394
16405
|
let raw;
|
|
16395
16406
|
try {
|
|
16396
|
-
raw =
|
|
16407
|
+
raw = readFileSync11(transcriptPath, "utf-8");
|
|
16397
16408
|
} catch {
|
|
16398
16409
|
return null;
|
|
16399
16410
|
}
|
|
@@ -16539,7 +16550,7 @@ function listStale(db, opts = {}) {
|
|
|
16539
16550
|
|
|
16540
16551
|
// ../../packages/core/dist/publishScan.js
|
|
16541
16552
|
import { createHash as createHash5 } from "node:crypto";
|
|
16542
|
-
import { existsSync as existsSync14, readFileSync as
|
|
16553
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
16543
16554
|
import { join as join11, basename as basename2 } from "node:path";
|
|
16544
16555
|
import { homedir as homedir2, userInfo as userInfo2 } from "node:os";
|
|
16545
16556
|
var ALLOW_FILE = ".caveat-publish-allow.json";
|
|
@@ -16771,7 +16782,7 @@ function publishSelfIdentityTokens() {
|
|
|
16771
16782
|
function loadPublishAllow(knowledgeRepo) {
|
|
16772
16783
|
const path = join11(knowledgeRepo, ALLOW_FILE);
|
|
16773
16784
|
if (!existsSync14(path)) return /* @__PURE__ */ new Set();
|
|
16774
|
-
const parsed = JSON.parse(
|
|
16785
|
+
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
16775
16786
|
if (!Array.isArray(parsed.allow)) throw new Error(`${ALLOW_FILE} must contain an "allow" array`);
|
|
16776
16787
|
return new Set(parsed.allow.filter((value) => typeof value === "string" && DIGEST_RE.test(value)));
|
|
16777
16788
|
}
|
|
@@ -16800,7 +16811,7 @@ var PublishScanError = class extends Error {
|
|
|
16800
16811
|
|
|
16801
16812
|
// ../../packages/core/dist/publish.js
|
|
16802
16813
|
import { createHash as createHash6 } from "node:crypto";
|
|
16803
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as
|
|
16814
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync13, readdirSync as readdirSync8, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
16804
16815
|
import { dirname as dirname7, join as join12, relative as relative3 } from "node:path";
|
|
16805
16816
|
|
|
16806
16817
|
// ../../packages/core/dist/visibility.js
|
|
@@ -16819,7 +16830,7 @@ function collectPublishSet(entriesDir) {
|
|
|
16819
16830
|
if (!existsSync15(entriesDir)) return { files, invalid };
|
|
16820
16831
|
for (const path of walkMarkdown(entriesDir)) {
|
|
16821
16832
|
const relPath = relative3(entriesDir, path).replace(/\\/g, "/");
|
|
16822
|
-
const content =
|
|
16833
|
+
const content = readFileSync13(path);
|
|
16823
16834
|
try {
|
|
16824
16835
|
const parsed = parseMarkdown(content.toString("utf-8"));
|
|
16825
16836
|
const visibility = classifyVisibility(parsed.frontmatter.visibility);
|
|
@@ -16874,7 +16885,7 @@ function buildSealedReadme(fileCount, files) {
|
|
|
16874
16885
|
"",
|
|
16875
16886
|
`Public entries: ${fileCount}`,
|
|
16876
16887
|
"",
|
|
16877
|
-
"Caveat: https://github.com/kitepon
|
|
16888
|
+
"Caveat: https://github.com/kitepon/Caveat",
|
|
16878
16889
|
""
|
|
16879
16890
|
];
|
|
16880
16891
|
const showcase = files.filter((f) => f.showcase).sort((a, b2) => Buffer.compare(Buffer.from(a.relPath, "utf-8"), Buffer.from(b2.relPath, "utf-8")));
|
|
@@ -16912,11 +16923,11 @@ function verifySealedMirror(opts) {
|
|
|
16912
16923
|
throw new Error(`publish mirror verification failed:
|
|
16913
16924
|
unexpected sealed mirror tree: ${files.join(", ") || "(empty)"}`);
|
|
16914
16925
|
}
|
|
16915
|
-
const diskReadme =
|
|
16926
|
+
const diskReadme = readFileSync13(join12(opts.mirrorDir, "README.md"), "utf-8");
|
|
16916
16927
|
if (diskReadme !== opts.readme) {
|
|
16917
16928
|
throw new Error("publish mirror verification failed: README.md content changed after generation");
|
|
16918
16929
|
}
|
|
16919
|
-
const diskBundle =
|
|
16930
|
+
const diskBundle = readFileSync13(join12(opts.mirrorDir, BUNDLE_RELPATH));
|
|
16920
16931
|
if (!diskBundle.equals(opts.bundle)) {
|
|
16921
16932
|
throw new Error("publish mirror verification failed: sealed bundle bytes changed after generation");
|
|
16922
16933
|
}
|
|
@@ -17010,8 +17021,8 @@ function readExistingMirror(mirrorDir) {
|
|
|
17010
17021
|
const readmePath = join12(mirrorDir, "README.md");
|
|
17011
17022
|
const bundlePath = join12(mirrorDir, BUNDLE_RELPATH);
|
|
17012
17023
|
return {
|
|
17013
|
-
readme: existsSync15(readmePath) ?
|
|
17014
|
-
bundle: existsSync15(bundlePath) ?
|
|
17024
|
+
readme: existsSync15(readmePath) ? readFileSync13(readmePath, "utf-8") : null,
|
|
17025
|
+
bundle: existsSync15(bundlePath) ? readFileSync13(bundlePath) : null
|
|
17015
17026
|
};
|
|
17016
17027
|
}
|
|
17017
17028
|
async function publishOwn(opts) {
|
|
@@ -17302,7 +17313,7 @@ function boundedCount(value) {
|
|
|
17302
17313
|
// ../../packages/core/dist/runtimeErrors.js
|
|
17303
17314
|
import { spawnSync } from "node:child_process";
|
|
17304
17315
|
import { createHash as createHash7, randomBytes as randomBytes3 } from "node:crypto";
|
|
17305
|
-
import {
|
|
17316
|
+
import { existsSync as existsSync16, lstatSync, mkdirSync as mkdirSync8, readFileSync as readFileSync14, renameSync as renameSync4, rmSync as rmSync6, statSync as statSync7, writeFileSync as writeFileSync9 } from "node:fs";
|
|
17306
17317
|
import { arch as hostArch, homedir as homedir3, platform as hostPlatform } from "node:os";
|
|
17307
17318
|
import { dirname as dirname8, join as join13 } from "node:path";
|
|
17308
17319
|
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
@@ -17310,7 +17321,6 @@ var RUNTIME_ERRORS_SCHEMA = "caveat.runtime_errors.v1";
|
|
|
17310
17321
|
var STATE_VERSION = "1.0";
|
|
17311
17322
|
var MAX_RECORDS = 256;
|
|
17312
17323
|
var RETENTION_MS = 30 * 864e5;
|
|
17313
|
-
var MAX_CONFIG_BYTES = 64 * 1024;
|
|
17314
17324
|
var definitions = {
|
|
17315
17325
|
"CAVEAT.DATABASE_OPEN_FAILED": { component: "database", severity: "high", template: "Caveat database open failed" },
|
|
17316
17326
|
"CAVEAT.INDEX_FAILED": { component: "index", severity: "high", template: "Caveat index operation failed" },
|
|
@@ -17318,7 +17328,8 @@ var definitions = {
|
|
|
17318
17328
|
"CAVEAT.MCP_SERVER_FAILED": { component: "mcp", severity: "high", template: "Caveat MCP server failed" },
|
|
17319
17329
|
"CAVEAT.MCP_TOOL_FAILED": { component: "mcp_tool", severity: "high", template: "Caveat MCP tool handler failed" },
|
|
17320
17330
|
"CAVEAT.CLAUDE_HOOK_FAILED": { component: "claude_hook", severity: "high", template: "Caveat Claude hook failed" },
|
|
17321
|
-
"CAVEAT.CODEX_HOOK_FAILED": { component: "codex_hook", severity: "high", template: "Caveat Codex hook failed" }
|
|
17331
|
+
"CAVEAT.CODEX_HOOK_FAILED": { component: "codex_hook", severity: "high", template: "Caveat Codex hook failed" },
|
|
17332
|
+
"CAVEAT.CURSOR_HOOK_FAILED": { component: "cursor_hook", severity: "high", template: "Caveat Cursor hook failed" }
|
|
17322
17333
|
};
|
|
17323
17334
|
function normalizeOptions(options2 = {}) {
|
|
17324
17335
|
return "env" in options2 || "configPath" in options2 || "storePath" in options2 || "version" in options2 || "isWindows" in options2 ? options2 : { env: options2 };
|
|
@@ -17329,10 +17340,10 @@ var validTime = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) &
|
|
|
17329
17340
|
var validVersion = (v) => typeof v === "string" && /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(v);
|
|
17330
17341
|
var validOs = (v) => typeof v === "string" && ["darwin", "linux", "windows"].includes(v);
|
|
17331
17342
|
var validArch = (v) => typeof v === "string" && ["x64", "arm64", "arm", "ia32"].includes(v);
|
|
17332
|
-
var windows = (env) => env
|
|
17333
|
-
function
|
|
17334
|
-
const home = env.HOME || env.USERPROFILE || homedir3();
|
|
17335
|
-
return
|
|
17343
|
+
var windows = (env) => isWindowsEnv(env, hostPlatform());
|
|
17344
|
+
function runtimeErrorsConfigPath(env = process.env) {
|
|
17345
|
+
const home = windows(env) ? env.USERPROFILE || env.HOME || homedir3() : env.HOME || env.USERPROFILE || homedir3();
|
|
17346
|
+
return join13(home, ".caveatrc.json");
|
|
17336
17347
|
}
|
|
17337
17348
|
function runtimeErrorsStatePath(env = process.env) {
|
|
17338
17349
|
const home = env.HOME || env.USERPROFILE || homedir3();
|
|
@@ -17341,24 +17352,8 @@ function runtimeErrorsStatePath(env = process.env) {
|
|
|
17341
17352
|
function collectionEnabled(options2 = {}) {
|
|
17342
17353
|
const env = options2.env ?? process.env;
|
|
17343
17354
|
try {
|
|
17344
|
-
const path = options2.configPath ??
|
|
17345
|
-
|
|
17346
|
-
const before = lstatSync(path);
|
|
17347
|
-
if (!before.isFile() || before.isSymbolicLink() || before.size > MAX_CONFIG_BYTES) return false;
|
|
17348
|
-
if (isWin) secureWindowsAcl(path, options2.aclRunner);
|
|
17349
|
-
else assertPosix(before, 384);
|
|
17350
|
-
const fd = openSync2(path, constants.O_RDONLY | constants.O_NONBLOCK | (constants.O_NOFOLLOW ?? 0));
|
|
17351
|
-
let text;
|
|
17352
|
-
try {
|
|
17353
|
-
const after = fstatSync(fd);
|
|
17354
|
-
if (before.dev !== after.dev || before.ino !== after.ino || after.size > MAX_CONFIG_BYTES) return false;
|
|
17355
|
-
if (!isWin) assertPosix(after, 384);
|
|
17356
|
-
text = readFileSync13(fd, "utf8");
|
|
17357
|
-
} finally {
|
|
17358
|
-
closeSync2(fd);
|
|
17359
|
-
}
|
|
17360
|
-
const config = JSON.parse(text);
|
|
17361
|
-
return plain(config) && exact(config, ["schema_version", "host", "collection", "reporting"]) && config.schema_version === "1.0" && plain(config.host) && exact(config.host, ["id", "profile"]) && typeof config.host.id === "string" && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(config.host.id) && ["server", "mac", "wsl", "windows-native"].includes(config.host.profile) && plain(config.collection) && exact(config.collection, ["enabled"]) && config.collection.enabled === true && canonicalReporting(config.reporting);
|
|
17355
|
+
const path = options2.configPath ?? runtimeErrorsConfigPath(env);
|
|
17356
|
+
return loadConfig(path).runtimeErrors === true;
|
|
17362
17357
|
} catch {
|
|
17363
17358
|
return false;
|
|
17364
17359
|
}
|
|
@@ -17376,32 +17371,19 @@ function ensureSafeDir(dir, isWin, options2 = {}) {
|
|
|
17376
17371
|
if (isWin) secureWindowsAcl(dir, options2.aclRunner, true, !existed);
|
|
17377
17372
|
else assertPosix(s, 448);
|
|
17378
17373
|
}
|
|
17379
|
-
|
|
17380
|
-
|
|
17381
|
-
if (value.endpoint !== void 0) {
|
|
17382
|
-
if (typeof value.endpoint !== "string" || value.endpoint.length > 2048) return false;
|
|
17383
|
-
try {
|
|
17384
|
-
if (!["http:", "https:"].includes(new URL(value.endpoint).protocol)) return false;
|
|
17385
|
-
} catch {
|
|
17386
|
-
return false;
|
|
17387
|
-
}
|
|
17388
|
-
}
|
|
17389
|
-
if (value.credential_file !== void 0 && (typeof value.credential_file !== "string" || value.credential_file.length < 1 || value.credential_file.length > 4096)) return false;
|
|
17390
|
-
return !value.enabled || value.endpoint !== void 0 && value.credential_file !== void 0;
|
|
17391
|
-
}
|
|
17392
|
-
var WINDOWS_ACL_VERIFY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value;$acl=if($isDir){[System.IO.Directory]::GetAccessControl($p)}else{[System.IO.File]::GetAccessControl($p)};$owner=$acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value;if($owner -ne $sid){exit 41};$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));if($rules.Count -ne 1){exit 42};$r=$rules[0];if($r.IdentityReference.Value -ne $sid -or $r.AccessControlType -ne 'Allow' -or $r.IsInherited -or ($r.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl){exit 43}`;
|
|
17393
|
-
var WINDOWS_ACL_APPLY = String.raw`$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;$acl=if($isDir){New-Object System.Security.AccessControl.DirectorySecurity}else{New-Object System.Security.AccessControl.FileSecurity};$acl.SetAccessRuleProtection($true,$false);$flags=if($isDir){[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'}else{[System.Security.AccessControl.InheritanceFlags]::None};$rule=New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl',$flags,[System.Security.AccessControl.PropagationFlags]::None,[System.Security.AccessControl.AccessControlType]::Allow);$acl.SetOwner($sid);$acl.AddAccessRule($rule);if($isDir){[System.IO.Directory]::SetAccessControl($p,$acl)}else{[System.IO.File]::SetAccessControl($p,$acl)};` + WINDOWS_ACL_VERIFY;
|
|
17374
|
+
var WINDOWS_ACL_VERIFY = String.raw`$ErrorActionPreference='Stop';$p=$env:CAVEAT_ACL_PATH;$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value;$acl=Get-Acl -LiteralPath $p;$owner=$acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value;if($owner -ne $sid){exit 41};$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));if($rules.Count -ne 1){exit 42};$r=$rules[0];if($r.IdentityReference.Value -ne $sid -or $r.AccessControlType -ne 'Allow' -or $r.IsInherited -or ($r.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl){exit 43}`;
|
|
17375
|
+
var WINDOWS_ACL_APPLY = String.raw`$ErrorActionPreference='Stop';$p=$env:CAVEAT_ACL_PATH;$isDir=$env:CAVEAT_ACL_DIRECTORY -eq '1';$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;$acl=if($isDir){New-Object System.Security.AccessControl.DirectorySecurity}else{New-Object System.Security.AccessControl.FileSecurity};$acl.SetAccessRuleProtection($true,$false);$flags=if($isDir){[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'}else{[System.Security.AccessControl.InheritanceFlags]::None};$rule=New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl',$flags,[System.Security.AccessControl.PropagationFlags]::None,[System.Security.AccessControl.AccessControlType]::Allow);$acl.SetOwner($sid);$acl.AddAccessRule($rule);Set-Acl -LiteralPath $p -AclObject $acl;` + WINDOWS_ACL_VERIFY;
|
|
17394
17376
|
var WINDOWS_ACL_TIMEOUT_MS = 3e4;
|
|
17395
17377
|
function runWindowsAcl(path, directory, apply) {
|
|
17396
|
-
const result = spawnSync("
|
|
17378
|
+
const result = spawnSync("pwsh.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", apply ? WINDOWS_ACL_APPLY : WINDOWS_ACL_VERIFY], { env: { ...process.env, CAVEAT_ACL_PATH: path, CAVEAT_ACL_DIRECTORY: directory ? "1" : "0" }, encoding: "utf-8", timeout: WINDOWS_ACL_TIMEOUT_MS, windowsHide: true });
|
|
17397
17379
|
if (result.error !== void 0) throw Error(`store_unsafe: powershell spawn ${result.error.code ?? result.error.message}`);
|
|
17398
17380
|
if (result.status !== 0) throw Error(`store_unsafe: powershell exit=${result.status} signal=${result.signal ?? "none"} stderr=${(result.stderr ?? "").replace(/\s+/g, " ").trim().slice(0, 400) || "(empty)"}`);
|
|
17399
17381
|
}
|
|
17400
17382
|
function secureWindowsAcl(path, runner, directory = false, apply = false) {
|
|
17401
17383
|
try {
|
|
17402
17384
|
(runner ?? runWindowsAcl)(path, directory, apply);
|
|
17403
|
-
} catch {
|
|
17404
|
-
throw Error("store_unsafe");
|
|
17385
|
+
} catch (cause) {
|
|
17386
|
+
throw Error("store_unsafe", { cause });
|
|
17405
17387
|
}
|
|
17406
17388
|
}
|
|
17407
17389
|
function assertPosix(info, mode) {
|
|
@@ -17431,7 +17413,7 @@ function validate(store) {
|
|
|
17431
17413
|
function readStore(path, isWin, options2 = {}) {
|
|
17432
17414
|
if (!existsSync16(path)) return empty();
|
|
17433
17415
|
ensureSafeFile(path, isWin, options2);
|
|
17434
|
-
const value = JSON.parse(
|
|
17416
|
+
const value = JSON.parse(readFileSync14(path, "utf8"));
|
|
17435
17417
|
validate(value);
|
|
17436
17418
|
return value;
|
|
17437
17419
|
}
|
|
@@ -17744,7 +17726,7 @@ function formatYmd(d) {
|
|
|
17744
17726
|
}
|
|
17745
17727
|
|
|
17746
17728
|
// ../../packages/core/dist/update.js
|
|
17747
|
-
import { readFileSync as
|
|
17729
|
+
import { readFileSync as readFileSync15, statSync as statSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
17748
17730
|
import { join as join15 } from "node:path";
|
|
17749
17731
|
var IMMUTABLE_KEYS = /* @__PURE__ */ new Set([
|
|
17750
17732
|
"id",
|
|
@@ -17765,7 +17747,7 @@ function updateEntry(id, patch, opts) {
|
|
|
17765
17747
|
}
|
|
17766
17748
|
const relPath = row.path;
|
|
17767
17749
|
const filePath = join15(opts.entriesRoot, relPath);
|
|
17768
|
-
const raw =
|
|
17750
|
+
const raw = readFileSync15(filePath, "utf-8");
|
|
17769
17751
|
const parsed = parseMarkdown(raw);
|
|
17770
17752
|
if (patch.frontmatter) {
|
|
17771
17753
|
for (const key of Object.keys(patch.frontmatter)) {
|
|
@@ -17936,7 +17918,6 @@ export {
|
|
|
17936
17918
|
isPrivateOwnerStat,
|
|
17937
17919
|
powershellCallPrefix,
|
|
17938
17920
|
nodeExecutableNames,
|
|
17939
|
-
SyncError,
|
|
17940
17921
|
syncOwn,
|
|
17941
17922
|
KNOWLEDGE_GITIGNORE,
|
|
17942
17923
|
initOwnSync,
|
|
@@ -18005,4 +17986,4 @@ strip-bom-string/index.js:
|
|
|
18005
17986
|
js-yaml/dist/js-yaml.mjs:
|
|
18006
17987
|
(*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
|
|
18007
17988
|
*/
|
|
18008
|
-
//# sourceMappingURL=chunk-
|
|
17989
|
+
//# sourceMappingURL=chunk-ULK7SZG6.js.map
|