loki-mode 9.27.3 → 9.28.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/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v9.27.3
6
+ # Loki Mode v9.28.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
470
470
 
471
471
  ---
472
472
 
473
- **v9.27.3 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v9.28.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9.27.3
1
+ 9.28.0
@@ -849,9 +849,19 @@ loki_config_generate_schema() {
849
849
  # Container keys are not reported: in {"dashboard":{"port":1}} the key
850
850
  # "dashboard" is a parent of the mapped "dashboard.port", never a typo itself.
851
851
  # A leaf is what a user actually mistypes.
852
+ # Exit status is the SIGNAL, not just the stdout:
853
+ # 0 checked; any unknown keys are on stdout (empty stdout = genuinely clean)
854
+ # 2 COULD NOT CHECK (no usable parser). Callers must NOT read this as clean.
855
+ #
856
+ # The earlier version returned 0 on both, so `config validate` printed "OK" and
857
+ # exit 0 for a YAML file full of bogus keys on a host with no parser. That is an
858
+ # affirmative false assertion of validity -- the exact false green this project
859
+ # exists to prevent, shipped by me in v9.27.2 under the wrong belief that a
860
+ # quiet no-op was "correct degradation". Silence is only honest if the caller
861
+ # knows it means "unmeasured".
852
862
  loki_config_unknown_keys() {
853
863
  local file="$1" fmt="$2"
854
- command -v python3 >/dev/null 2>&1 || return 0
864
+ command -v python3 >/dev/null 2>&1 || return 2
855
865
 
856
866
  # YAML needs a parser. The rest of this file reaches for yq first, so do the
857
867
  # same: convert to JSON via yq and let the JSON walk below handle it. That
@@ -861,10 +871,10 @@ loki_config_unknown_keys() {
861
871
  # missing parser must not invent a verdict.
862
872
  local scratch_json=""
863
873
  if [ "$fmt" = "yaml" ] && ! python3 -c "import yaml" >/dev/null 2>&1; then
864
- command -v yq >/dev/null 2>&1 || return 0
865
- scratch_json="$(mktemp "${TMPDIR:-/tmp}/loki-cfg-uk.XXXXXX")" || return 0
874
+ command -v yq >/dev/null 2>&1 || return 2
875
+ scratch_json="$(mktemp "${TMPDIR:-/tmp}/loki-cfg-uk.XXXXXX")" || return 2
866
876
  if ! yq eval -o=json '.' "$file" > "$scratch_json" 2>/dev/null; then
867
- rm -f "$scratch_json"; return 0
877
+ rm -f "$scratch_json"; return 2
868
878
  fi
869
879
  file="$scratch_json"; fmt="json"
870
880
  fi
@@ -941,6 +951,10 @@ for u in unknown:
941
951
  loki_config_validate_file() {
942
952
  local path="$1"
943
953
  local rc=0
954
+ # Declared HERE, before the unknown-key case block that sets it. An earlier
955
+ # draft declared it after that block, so `local` reset it to 0 and the flag
956
+ # could never fire -- the INCOMPLETE verdict would have been dead code.
957
+ local _uk_unmeasured=0
944
958
 
945
959
  if [ -z "$path" ] || [ ! -e "$path" ]; then
946
960
  printf 'loki: config validate: file not found: %s\n' "$path" >&2
@@ -1019,7 +1033,19 @@ loki_config_validate_file() {
1019
1033
  case "$fmt" in
1020
1034
  (json|yaml)
1021
1035
  local unknown_keys
1022
- unknown_keys="$(loki_config_unknown_keys "$path" "$fmt")" || unknown_keys=""
1036
+ local _uk_rc=0
1037
+ unknown_keys="$(loki_config_unknown_keys "$path" "$fmt")" || _uk_rc=$?
1038
+ if [ "$_uk_rc" -eq 2 ]; then
1039
+ # Unmeasured, and said so. This is NOT a pass: the file may be
1040
+ # full of typos nobody looked for. Reported on stderr and the
1041
+ # final verdict is downgraded from OK to INCOMPLETE below, so a
1042
+ # CI job gating on exit 0 does not read "we could not check" as
1043
+ # "we checked and it was fine".
1044
+ unknown_keys=""
1045
+ _uk_unmeasured=1
1046
+ printf 'loki: config validate: UNKNOWN-KEY CHECK SKIPPED for %s -- no usable %s parser (need python3 with pyyaml, or yq). Unrecognized keys were NOT looked for.\n' \
1047
+ "$path" "$fmt" >&2
1048
+ fi
1023
1049
  if [ -n "$unknown_keys" ]; then
1024
1050
  local ukey
1025
1051
  while IFS= read -r ukey; do
@@ -1072,7 +1098,15 @@ UNKNOWN_KEYS
1072
1098
  fi
1073
1099
  done <<< "$pairs"
1074
1100
 
1075
- if [ "$rc" = 0 ]; then
1101
+ if [ "$rc" = 0 ] && [ "${_uk_unmeasured:-0}" = "1" ]; then
1102
+ # Everything that COULD be checked passed, but a check was skipped. Say
1103
+ # exactly that. "OK" here would claim a completeness the run does not
1104
+ # have. Exit 0 is kept deliberately: nothing was found wrong, and this
1105
+ # command has no documented tiered contract to break (docs/exit-codes.md
1106
+ # does not list `config validate`). The distinction lives in the words,
1107
+ # which is where a human reads it, and in the stderr line above.
1108
+ printf 'loki: config validate: INCOMPLETE -- %s (checks that ran passed; unknown-key check was skipped)\n' "$path"
1109
+ elif [ "$rc" = 0 ]; then
1076
1110
  printf 'loki: config validate: OK -- %s\n' "$path"
1077
1111
  fi
1078
1112
  return "$rc"
package/autonomy/loki CHANGED
@@ -14528,13 +14528,39 @@ cmd_logs() {
14528
14528
  esac
14529
14529
  done
14530
14530
 
14531
- local log_file="$LOKI_DIR/logs/session.log"
14532
-
14533
- if [ ! -f "$log_file" ]; then
14534
- echo -e "${YELLOW}No log file found at $log_file${NC}"
14531
+ # Resolve the log the runner ACTUALLY writes.
14532
+ #
14533
+ # This read a logs/session.log path that nothing in the tree writes (other
14534
+ # readers of it exist in web-app/ and api-examples/, all equally dead). So
14535
+ # `loki logs`, the
14536
+ # most natural "what is it doing?" command, reported "No log file found"
14537
+ # while the real logs sat in that same directory. run.sh:22409 writes
14538
+ # .loki/logs/autonomy-YYYYMMDD.log per day, plus agent.log for the dashboard.
14539
+ #
14540
+ # Newest dated log first; agent.log as the fallback. Both are listed in the
14541
+ # not-found message so the user can see where we looked rather than being
14542
+ # told a single wrong path.
14543
+ local log_dir="$LOKI_DIR/logs"
14544
+ local log_file=""
14545
+ if [ -d "$log_dir" ]; then
14546
+ # `|| log_file=""` is load-bearing: under `set -euo pipefail`, ls exits 2
14547
+ # when the glob matches nothing and pipefail propagates it, aborting the
14548
+ # function before the agent.log fallback and before the not-found message.
14549
+ # Without it, a host with agent.log but no dated log exits 1 in SILENCE --
14550
+ # a worse failure than the wrong-path bug this replaced.
14551
+ log_file="$(ls -1t "$log_dir"/autonomy-*.log 2>/dev/null | head -1)" || log_file=""
14552
+ [ -n "$log_file" ] || { [ -f "$log_dir/agent.log" ] && log_file="$log_dir/agent.log"; }
14553
+ fi
14554
+
14555
+ if [ -z "$log_file" ] || [ ! -f "$log_file" ]; then
14556
+ echo -e "${YELLOW}No log file found in $log_dir${NC}"
14557
+ echo -e "${DIM}Looked for: autonomy-YYYYMMDD.log (newest), then agent.log${NC}"
14558
+ echo -e "${DIM}Logs are written once a run starts: loki start <spec>${NC}"
14535
14559
  exit 0
14536
14560
  fi
14537
14561
 
14562
+ echo -e "${DIM}Log: $log_file${NC}"
14563
+
14538
14564
  if [ "$follow" = true ]; then
14539
14565
  echo -e "${BOLD}Following logs (Ctrl+C to stop)${NC}"
14540
14566
  echo ""
@@ -27732,13 +27758,26 @@ if last_n > 0:
27732
27758
 
27733
27759
  # --- budget status (read-time; warn at 80%, exceeded at 100%) ------------
27734
27760
  budget_limit = None
27761
+ budget_used_recorded = None
27735
27762
  budget_file = os.path.join(loki_dir, "metrics", "budget.json")
27736
27763
  if os.path.isfile(budget_file):
27737
27764
  try:
27738
27765
  bd = json.load(open(budget_file))
27739
27766
  budget_limit = bd.get("limit") or bd.get("budget_limit")
27767
+ # Read the RECORDED spend too. This block took only the cap and then
27768
+ # overwrote spend with the current run's figure, which is None when no
27769
+ # iteration has a measured cost -- so it fell back to 0.0 and printed
27770
+ # "Used: $0.00 ... Status: OK" over a file that said
27771
+ # "budget_used": 0.7992, "exceeded": true, while `loki status` showed
27772
+ # 160%. The --json surface asserted "exceeded": false, which is what
27773
+ # automation gates on. Three other readers (loki:5791, :6284, :28458)
27774
+ # already read budget_used; this was the one divergent reader.
27775
+ _bu = bd.get("budget_used")
27776
+ if _bu is not None:
27777
+ budget_used_recorded = float(_bu)
27740
27778
  except Exception:
27741
27779
  budget_limit = None
27780
+ budget_used_recorded = None
27742
27781
  if budget_limit is None and budget_limit_env:
27743
27782
  try:
27744
27783
  budget_limit = float(budget_limit_env)
@@ -27750,7 +27789,14 @@ if budget_limit is not None:
27750
27789
  except (TypeError, ValueError):
27751
27790
  budget_limit = None
27752
27791
 
27753
- budget_used = current_cost if isinstance(current_cost, (int, float)) else 0.0
27792
+ # Prefer the recorded cumulative spend; fall back to the current run only when
27793
+ # the state file carries no figure. Never silently substitute 0.0 for "unknown".
27794
+ if isinstance(budget_used_recorded, (int, float)):
27795
+ budget_used = budget_used_recorded
27796
+ elif isinstance(current_cost, (int, float)):
27797
+ budget_used = current_cost
27798
+ else:
27799
+ budget_used = 0.0
27754
27800
  status = "none"
27755
27801
  percent_used = None
27756
27802
  remaining = None
package/autonomy/run.sh CHANGED
@@ -158,7 +158,13 @@
158
158
  # Human Intervention (Auto-Claude pattern):
159
159
  # PAUSE file: touch .loki/PAUSE - pauses after current session
160
160
  # HUMAN_INPUT.md: echo "instructions" > .loki/HUMAN_INPUT.md
161
- # STOP file: touch .loki/STOP - stops immediately
161
+ # STOP file: touch .loki/STOP - graceful; read at the TOP of each
162
+ # iteration, so a STOP written mid-dispatch waits for that
163
+ # provider call to return (bounded by
164
+ # LOKI_PROVIDER_CALL_TIMEOUT, default 7200s). It said
165
+ # "stops immediately", which was false. For an immediate
166
+ # stop use `loki stop` (process-group SIGTERM, 1s grace,
167
+ # then SIGKILL). See docs/stop-latency.md.
162
168
  # Ctrl+C (once): Pauses execution, shows options
163
169
  # Ctrl+C (twice): Exits immediately
164
170
  #
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "9.27.3"
10
+ __version__ = "9.28.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -5,10 +5,15 @@ fetched URL. Items that research proposed but that turned out to be **already
5
5
  shipped** are listed at the bottom under "Not items" with the evidence, because
6
6
  a plan that re-builds working code is worse than a shorter plan.
7
7
 
8
- There are **seven** real items, not ten. Three of the research's candidates were
8
+ There are **eight** real items, not ten. Three of the research's candidates were
9
9
  already implemented, and two more are architecturally unavailable to Loki as
10
10
  designed. Padding to ten would mean inventing work.
11
11
 
12
+ Items 1, 2 and 7 shipped in v9.27.0-v9.27.3. Items 3, 4 and 9 shipped in
13
+ v9.28.0. Item 8 (a flaky trust suite) and item 10 (a hard command blocklist,
14
+ designed but not built) are OPEN with their reasons stated, rather than quietly
15
+ closed by loosening an assertion or shipping a claim we cannot keep.
16
+
12
17
  ---
13
18
 
14
19
  ## What the market actually rewards
@@ -83,25 +88,28 @@ which is a much cheaper fix.
83
88
 
84
89
  ---
85
90
 
86
- ## 3. Publish a measured kill-switch latency
87
-
88
- **Status: mechanism exists, number does not.**
89
-
90
- `check_human_intervention()` (`autonomy/run.sh`) implements PAUSE/STOP/INPUT.
91
- There is no stated termination window anywhere in `docs/` (measured: zero
92
- matches for "termination window" or "kill switch").
91
+ ## 3. Stop latency -- SHIPPED v9.28.0, and the premise was inverted
93
92
 
94
- An enterprise buyer asks "how fast can I stop it?" Factory answers with a number.
95
- "There is a stop signal" is not an answer.
93
+ **Status: published in `docs/stop-latency.md`.**
96
94
 
97
- **Do:** measure worst-case latency from signal to process exit across the bash
98
- and Bun routes, publish the number, and add a test that fails if it regresses
99
- past the published bound.
95
+ The premise of this item was backwards. `loki stop` is NOT slow: it kills the
96
+ whole process group with SIGTERM, a 1 second grace, then SIGKILL
97
+ (`autonomy/loki`, `_stop_group_by_pgid_files`), and that bound does not depend
98
+ on what the run was doing.
100
99
 
101
- **Care:** publish the measured worst case, not the median. A number we beat 50%
102
- of the time is worse than no number.
100
+ What was slow is the mechanism the product itself recommended.
101
+ `autonomy/run.sh:161` told users `touch .loki/STOP - stops immediately`. That
102
+ was false: the STOP file is read only at the top of an iteration
103
+ (`check_human_intervention` at `:25149`, called from the single site `:22301`),
104
+ so a STOP written mid-dispatch waits for the provider call to return, bounded by
105
+ `LOKI_PROVIDER_CALL_TIMEOUT` (default 7200s). The docs pointed at the two-hour
106
+ path and called it immediate.
103
107
 
104
- ---
108
+ Shipped: the false "stops immediately" claim is corrected in place,
109
+ `docs/stop-latency.md` publishes both numbers with their derivations, and the
110
+ Bun route's provider call now honors `LOKI_PROVIDER_CALL_TIMEOUT` -- it
111
+ previously passed no timeout at all, leaving that route's STOP path with **no
112
+ upper bound**.
105
113
 
106
114
  ## 4. Close the config-diagnostic gap for the remaining format
107
115
 
@@ -113,14 +121,18 @@ GitHub ubuntu-24.04 runner, and the fallback was verified against a stand-in
113
121
  honouring both invocation shapes the real `yq` is called with, so CI and any
114
122
  Linux host with either parser get full detection.
115
123
 
116
- The residual gap is narrow: a host with **neither** pyyaml nor `yq` (a stock
117
- macOS dev machine) gets no YAML detection. It degrades quietly, which is correct
118
- -- a missing parser must never invent a verdict -- but silently.
124
+ **CORRECTED, and closed in v9.28.0.** An earlier revision of this item called
125
+ the no-parser path "quiet degradation, which is correct". That was wrong, and
126
+ reproducing it settled the matter: with no parser the command printed
127
+ `config validate: OK` and exit 0 for a YAML file full of bogus keys. Silence in
128
+ the helper is fine; the CALLER turning that silence into an affirmative `OK` was
129
+ an assertion of validity nobody had checked, which is the exact false green this
130
+ project exists to prevent.
119
131
 
120
- **Do:** state the dependency in `loki config validate --help` so the gap is
121
- visible rather than silent. Vendoring a YAML scanner is not worth it for one
122
- host shape that already has a documented fallback available via `brew install
123
- yq`.
132
+ The verdict is now `INCOMPLETE` with a stderr line naming the skipped check, and
133
+ the helper reports "could not check" as a distinct status rather than an empty
134
+ result indistinguishable from "checked, nothing found". Guarded by
135
+ `tests/test-config-unknown-keys.sh` case 5d.
124
136
 
125
137
  ---
126
138
 
@@ -186,6 +198,66 @@ than assume the author's host. That is a review habit, not a script.
186
198
 
187
199
  ---
188
200
 
201
+ ## 8. Fix the flaky assurance-tail suite (OPEN, not yet fixed)
202
+
203
+ **Status: mechanism identified, not reproduced locally, deliberately not patched.**
204
+
205
+ `tests/test-review-assurance-tail.sh` has failed CI twice on unrelated commits
206
+ (v9.26.3 and v9.27.1), each costing a release cycle. Three different assertions
207
+ failed across the two incidents:
208
+
209
+ - `semantic shard FAIL: calls=3 (expected 4)`
210
+ - `valid structured requirements coverage did not pass`
211
+ - `requirements-forged-pass-error escaped parent-bound result publication`
212
+
213
+ They share a mechanism: the suite drives **real background subshells** (`sleep 30`,
214
+ `&`) and asserts **exact provider-call counts** (`= "1"`, `= "4"`) while also
215
+ testing that a FAIL *cancels* sibling lineages. On a 4-way-sharded runner the
216
+ cancellation can land before the last dispatch is logged, so the count races.
217
+
218
+ The suite already anticipates contention: `REVIEW_TIMEOUT_SCALE` is 4x when
219
+ `LOKI_TEST_SHARD` is set, and CI does set it (`.github/workflows/test.yml:149`).
220
+ So the timeout budget is **not** the binding constraint -- the exact-equality
221
+ call counts are.
222
+
223
+ **Why it is not patched here.** Both incidents were settled by a rerun on the
224
+ identical SHA (green both times), which proves flake and diff-innocence without
225
+ touching a fail-closed trust suite. It did not reproduce locally across six runs
226
+ including shard-scaled and CPU-loaded ones. Relaxing an exact count on a theory
227
+ would weaken a gate that deliberately distinguishes a LOST shard from a
228
+ CANCELLED one.
229
+
230
+ **Do:** make the timing deterministic rather than the assertion looser -- have
231
+ each dispatch log its intent *before* the call rather than after, so the count is
232
+ stable regardless of when cancellation lands. That changes the contract the suite
233
+ guards, so it needs its own cycle with the expected counts re-derived.
234
+
235
+ ---
236
+
237
+ ## 9. Enforcement claims in buyer-facing docs -- SHIPPED v9.28.0
238
+
239
+ The source was scrupulously honest and the docs were not.
240
+ `autonomy/run.sh:515` states `LOKI_ALLOWED_PATHS` "Does NOT restrict
241
+ provider-driven agent writes"; `check_command_allowed` is "intentionally NOT
242
+ called" with zero callers. Meanwhile `wiki/Enterprise-Features.md` listed both
243
+ as production security controls and `docs/certification/answer-key.md` marked
244
+ "restricts which directories agents can modify" as the **correct exam answer**.
245
+ Nine buyer-facing files, zero caveats.
246
+
247
+ All nine now carry a `SANDBOX-SCOPED` note saying what is enforced (2 mount-time
248
+ call sites in `autonomy/sandbox.sh`, and one for operator-typed
249
+ `loki sandbox run` argv), what is not, and that both enforce nothing unless
250
+ `LOKI_SANDBOX_MODE=true`. `tests/test-enforcement-doc-honesty.sh` guards it with
251
+ marker-presence rather than phrase-absence, because a grep for "restrict" near
252
+ the variable name fires on the caveat itself.
253
+
254
+ Two errors in my own brief were caught while planning: it is 2 path-enforcement
255
+ call sites, not 4 (I had counted the definition and a comment), and a
256
+ pre-existing answer-key letter mismatch (key said A, quiz option was B) was
257
+ fixed at the same time.
258
+
259
+ ---
260
+
189
261
  ## Not items (research proposed these; they are already shipped)
190
262
 
191
263
  - **Signed receipts default-off is a moat gated behind an env var.** The receipt
@@ -201,12 +273,45 @@ than assume the author's host. That is a review habit, not a script.
201
273
  - **A headless exec contract with documented exit codes.** Already exists via
202
274
  `LOKI_DURABLE_STATE=1`; see item 2, which is the real (smaller) gap.
203
275
 
204
- ## Architecturally unavailable, and worth saying so
205
-
206
- - **Per-command risk tiers** and a **hard command blocklist** ("cannot be
207
- bypassed by approval", per Factory's docs). `autonomy/run.sh:515` documents
208
- that `LOKI_ALLOWED_PATHS` "does NOT restrict provider-driven agent writes
209
- (run.sh never sees them)". You cannot classify a command you never observe.
210
- The only honest form is a sandbox-boundary blocklist, which is a different and
211
- much larger piece of work. Attempting a partial version would ship a security
212
- claim we cannot keep.
276
+ ## 10. Hard command blocklist (OPEN, designed, not built)
277
+
278
+ **CORRECTION.** This section previously listed a hard blocklist as
279
+ "architecturally unavailable". That was too pessimistic. It is unavailable in
280
+ `run.sh`, which never observes agent commands -- but a design review found a
281
+ boundary where it IS enforceable, and the honest scope is narrower than Factory
282
+ states for their own.
283
+
284
+ What the review established:
285
+
286
+ - **Seccomp cannot do it.** `autonomy/seccomp-sandbox.json` allows `execve`
287
+ unconditionally, and seccomp-bpf filters on register values: `execve`'s
288
+ pathname is a userspace pointer a filter cannot dereference. Any proposal to
289
+ "add blocked commands to seccomp" is not implementable.
290
+ - **A PATH shim cannot do it.** Defeated by an absolute path, by `env -i`, or by
291
+ resetting PATH. That is precisely the class Factory claims to defeat.
292
+ - **A read-only bind-mount over the resolved binary inode CAN.** The mount is
293
+ decided on the host before the container exists, and cannot be undone from
294
+ inside: `--cap-drop=ALL` (no `CAP_SYS_ADMIN`), `no-new-privileges`, non-root
295
+ user, and the seccomp profile denies `umount`. Because it targets an inode, no
296
+ string is matched, so `bash -c`, absolute paths, quoting and command
297
+ substitution all converge on the same blocked inode. That is a stronger claim
298
+ than argv parsing, not a weaker one.
299
+
300
+ **The scoping finding that makes this honest.** `loki sandbox` has three modes,
301
+ and only `docker` supports it. `docker sandbox create` (Docker Desktop microVM
302
+ mode) takes no mount flags, and worktree mode has no container at all -- and
303
+ auto-detect prefers Docker Desktop first. So the guarantee must be paired with
304
+ **fail-closed refusal to start** in every unsupported mode, or it becomes the
305
+ same overstatement this release just spent its time removing.
306
+
307
+ Also worth stating plainly, which Factory's docs elide: blocking a program does
308
+ not remove the capability. With the default bridge network an agent can fetch a
309
+ replacement binary. `LOKI_SANDBOX_NETWORK=none` removes the capability.
310
+
311
+ **Do:** implement as `LOKI_BLOCKLIST_COMMANDS` (a new key -- the existing
312
+ `LOKI_BLOCKED_COMMANDS` is an advisory substring filter with different
313
+ semantics), with the adversarial test matrix and a SKIP-not-PASS rule when
314
+ Docker is unavailable. Design is complete; the build is a separate cycle.
315
+
316
+ - **Per-command risk tiers** remain out of reach for the same original reason:
317
+ you cannot classify a command you never observe.
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v9.27.3
5
+ **Version:** v9.28.0
6
6
 
7
7
  ---
8
8
 
@@ -161,8 +161,8 @@ Loki Mode provides several security controls for enterprise environments:
161
161
  | Variable | Default | Description |
162
162
  |----------|---------|-------------|
163
163
  | `LOKI_SANDBOX_MODE` | `false` | Run in Docker sandbox for isolation |
164
- | `LOKI_ALLOWED_PATHS` | (all) | Comma-separated paths agents can modify |
165
- | `LOKI_BLOCKED_COMMANDS` | `rm -rf /` | Comma-separated blocked shell commands |
164
+ | `LOKI_ALLOWED_PATHS` | (all) | SANDBOX-SCOPED: host paths the sandbox may mount writable. Does NOT restrict agent writes. |
165
+ | `LOKI_BLOCKED_COMMANDS` | `rm -rf /,dd if=,mkfs,...` | SANDBOX-SCOPED: blocked `loki sandbox run` argv. Does NOT filter agent-issued commands. |
166
166
  | `LOKI_MAX_PARALLEL_AGENTS` | `10` | Limit concurrent agent spawning |
167
167
  | `LOKI_STAGED_AUTONOMY` | `false` | Require approval before execution |
168
168
  | `LOKI_PROMPT_INJECTION` | `false` | Allow prompt injection via `HUMAN_INPUT.md` (disabled by default for security) |
@@ -106,7 +106,14 @@ Limit which directories agents can modify:
106
106
  export LOKI_ALLOWED_PATHS=/workspace/src,/workspace/tests
107
107
  ```
108
108
 
109
- Agents will only be able to write to the specified directories.
109
+ SANDBOX-SCOPED. This restricts which host directories the Docker sandbox
110
+ bind-mounts writable (`autonomy/sandbox.sh:1222`, and `:1315` for a custom
111
+ `--mount`). It does NOT restrict writes the AI provider agent makes inside
112
+ the workspace, because `autonomy/run.sh` never observes those commands.
113
+ Requires `LOKI_SANDBOX_MODE=true` (default `false`); with sandbox mode off
114
+ this variable enforces nothing. Real containment for agent activity is the
115
+ Docker sandbox itself: cap-drop, seccomp, read-only mounts, and optional
116
+ `LOKI_SANDBOX_NETWORK=none`.
110
117
 
111
118
  ### Command Blocking
112
119
 
@@ -85,9 +85,14 @@ D) Maximum 5 council members can vote
85
85
 
86
86
  ---
87
87
 
88
- **Question 10:** How do you restrict which directories agents can modify?
88
+ **Question 10:** Which variable restricts the host paths the Docker sandbox
89
+ will bind-mount writable?
89
90
 
90
91
  A) `LOKI_READ_ONLY_PATHS=/etc,/usr`
91
92
  B) `LOKI_ALLOWED_PATHS=/workspace/src,/workspace/tests`
92
93
  C) `LOKI_SANDBOX_PATHS=/safe/dir`
93
94
  D) `LOKI_WRITE_DIRS=src,tests`
95
+
96
+ _SANDBOX-SCOPED: `LOKI_ALLOWED_PATHS` governs which host paths the Docker
97
+ sandbox bind-mounts writable. It does not restrict writes the agent makes
98
+ inside the workspace, and it enforces nothing unless `LOKI_SANDBOX_MODE=true`._
@@ -68,7 +68,7 @@ This file contains answers for all module quizzes and the final certification ex
68
68
  | 7 | B | The session auto-pauses when budget is exceeded |
69
69
  | 8 | B | `LOKI_TLS_CERT` and `LOKI_TLS_KEY` environment variables |
70
70
  | 9 | A | Stagnation limit flags when N iterations pass with no git changes |
71
- | 10 | A | `LOKI_ALLOWED_PATHS` restricts which directories agents can modify |
71
+ | 10 | B | SANDBOX-SCOPED: `LOKI_ALLOWED_PATHS` restricts which host paths the Docker sandbox bind-mounts writable (`autonomy/sandbox.sh:1222`). It does NOT restrict agent writes inside the workspace. |
72
72
 
73
73
  ---
74
74
 
@@ -365,13 +365,18 @@ D) Maximum 5 council members can vote
365
365
 
366
366
  ---
367
367
 
368
- **Question 40:** How do you restrict which directories agents can modify?
368
+ **Question 40:** Which variable restricts the host paths the Docker sandbox
369
+ will bind-mount writable?
369
370
 
370
371
  A) `LOKI_ALLOWED_PATHS=/workspace/src,/workspace/tests`
371
372
  B) `LOKI_READ_ONLY_PATHS=/etc,/usr`
372
373
  C) `LOKI_SANDBOX_PATHS=/safe/dir`
373
374
  D) `LOKI_WRITE_DIRS=src,tests`
374
375
 
376
+ _SANDBOX-SCOPED: `LOKI_ALLOWED_PATHS` governs which host paths the Docker
377
+ sandbox bind-mounts writable. It does not restrict writes the agent makes
378
+ inside the workspace, and it enforces nothing unless `LOKI_SANDBOX_MODE=true`._
379
+
375
380
  ---
376
381
 
377
382
  ## Section 5: Troubleshooting (Questions 41-50)
@@ -0,0 +1,76 @@
1
+ # Stop latency
2
+
3
+ How fast can you stop a run. Every number here is derived from the source cited
4
+ beside it. Numbers marked MEASURED are enforced by `tests/test-stop-latency.sh`;
5
+ numbers marked DERIVED come from a documented timeout default and have not been
6
+ sat through end to end.
7
+
8
+ The short version: **`loki stop` is the supported mechanism and is bounded at
9
+ about 1 second. `touch .loki/STOP` is graceful, not immediate, and on the
10
+ default runner its worst case is 2 hours.** The product used to say the opposite.
11
+
12
+ ## The supported stop
13
+
14
+ ```bash
15
+ loki stop
16
+ ```
17
+
18
+ **Worst case: about 1 second to SIGKILL. MEASURED.** `loki stop` signals the
19
+ run's whole process group: SIGTERM, a 1 second grace, then SIGKILL
20
+ (`autonomy/loki`, `_stop_group_by_pgid_files`). The provider subprocess and its
21
+ tool children die with the orchestrator. **This bound does not depend on what
22
+ the run was doing when you issued it** -- that timeout-independence is the
23
+ actual property worth relying on, and it is what the test asserts.
24
+
25
+ From the dashboard Stop button the bound is larger: `_killpg_project`
26
+ (`dashboard/server.py`) sends SIGTERM, polls for up to 5 seconds, then SIGKILL,
27
+ and a confirming reaper sweep follows it. Treat the dashboard button as
28
+ seconds, not sub-second, and prefer `loki stop` in automation.
29
+
30
+ ## `touch .loki/STOP` is graceful, not immediate
31
+
32
+ The STOP file is a cooperative signal. The runner reads it at the **top of each
33
+ iteration**, before dispatching to the provider, and never during a provider
34
+ call: `check_human_intervention` (`autonomy/run.sh:25149`) is called from
35
+ exactly one site, `autonomy/run.sh:22301`. A STOP file written one second after
36
+ a dispatch is not observed until that provider call returns.
37
+
38
+ **Worst case on the bash runner: 7200 seconds plus iteration teardown. DERIVED**
39
+ from `LOKI_PROVIDER_CALL_TIMEOUT`, which defaults to 7200 (`autonomy/run.sh:880`).
40
+ Note that `LOKI_PROVIDER_IDLE_TIMEOUT` (default 120) does **not** lower this: the
41
+ deadline helper resets its activity clock on every output chunk, so a provider
42
+ that streams normally never trips the idle path.
43
+
44
+ Two places where the STOP file **is** fast, because the loop is already polling:
45
+
46
+ - during a pause (`handle_pause`): about 1 second, the poll interval
47
+ - during a retry backoff: one tick, since the wait loop rereads STOP each tick
48
+
49
+ Use `.loki/STOP` when you want the run to finish its current iteration and stop
50
+ cleanly. Use `loki stop` when you need it to stop now.
51
+
52
+ ## Lowering the graceful bound
53
+
54
+ Set `LOKI_PROVIDER_CALL_TIMEOUT` to the longest single provider call you are
55
+ willing to wait through. The STOP-file worst case is that value plus a few
56
+ seconds of teardown. Lowering it below what a real iteration needs will cut off
57
+ useful work, so this is a stop-latency versus throughput trade, not a free win.
58
+
59
+ ## Scope, and one place we are not at parity
60
+
61
+ These numbers cover the default bash runner. `docs/exit-codes.md` documents
62
+ exit-code parity between the bash and Bun (`LOKI_SDK_LOOP=1`) runners. **Stop
63
+ latency is not at that parity**, and saying so is more useful than implying it:
64
+
65
+ - The Bun runner records no process-group id, so `loki stop` reaches the runner
66
+ and its direct provider child but may leave the provider's own tool
67
+ subprocesses running. Prefer the bash route where you need a guaranteed
68
+ whole-tree kill.
69
+
70
+ Closed in v9.28.0: the Bun provider call previously passed no timeout at all,
71
+ so its STOP-file path had **no upper bound**. It now honors
72
+ `LOKI_PROVIDER_CALL_TIMEOUT` like the bash route
73
+ (`loki-ts/src/runner/providers.ts`), using the SIGTERM-then-SIGKILL escalation
74
+ `shellRun` already implemented.
75
+
76
+ `loki stop` remains the supported mechanism on both routes.
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var St=Object.create;var{getPrototypeOf:yt,defineProperty:jG,getOwnPropertyNames:bt}=Object;var ft=Object.prototype.hasOwnProperty;function _t($){return this[$]}var vt,ht,gt=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?vt??=new WeakMap:ht??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?St(yt($)):{};let J=X||!$||!$.__esModule?jG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of bt($))if(!ft.call(J,q))jG(J,q,{get:_t.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var mt=($)=>$;function ut($,X){this[$]=mt.bind(null,X)}var B1=($,X)=>{for(var Q in X)jG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:ut.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var YR={};B1(YR,{lokiDir:()=>h0,homeLokiDir:()=>HQ,findRepoRootForVersion:()=>AG,REPO_ROOT:()=>L1});import{resolve as h2,dirname as LG}from"path";import{fileURLToPath as dt}from"url";import{existsSync as Zq}from"fs";import{homedir as pt}from"os";function ct(){let $=VR;for(let X=0;X<6;X++){if(Zq(h2($,"VERSION"))&&Zq(h2($,"autonomy/run.sh")))return $;let Q=LG($);if(Q===$)break;$=Q}return h2(VR,"..","..","..")}function AG($){let X=$;for(let Q=0;Q<6;Q++){if(Zq(h2(X,"VERSION"))&&Zq(h2(X,"autonomy/run.sh")))return X;let z=LG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function HQ(){return h2(pt(),".loki")}var VR,L1;var k1=s(()=>{VR=LG(dt(import.meta.url));L1=ct()});import{readFileSync as lt}from"fs";import{resolve as it,dirname as at}from"path";import{fileURLToPath as ot}from"url";function j9(){if(n3!==null)return n3;let $="9.27.3";if(typeof $==="string"&&$.length>0)return n3=$,n3;try{let X=at(ot(import.meta.url)),Q=AG(X);n3=lt(it(Q,"VERSION"),"utf-8").trim()}catch{n3="unknown"}return n3}var n3=null;var Kq=s(()=>{k1()});var GR={};B1(GR,{runOrThrow:()=>Ue,run:()=>$1,readStreamCapped:()=>Jq,commandVersion:()=>We,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>WR});async function Jq($,X=WR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function $1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([Jq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Ue($,X={}){let Q=await $1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=He($),Q=await $1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function He($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function We($,X="--version"){if(!await g5($))return null;let z=await $1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var WR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Ge?"":$}var Ge,p0,$5,q1,L61,A1,f1,m5,r;var t7=s(()=>{Ge=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),q1=g2("\x1B[1;33m"),L61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),r=g2("\x1B[0m")});import{existsSync as De}from"fs";async function Z2(){if(GQ!==void 0)return GQ;let $="/opt/homebrew/bin/python3.12";if(De($))return GQ=$,$;let X=await g5("python3.12");if(X)return GQ=X,X;let Q=await g5("python3");return GQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return $1([Q,"-c",$],X)}var GQ;var m2=s(()=>{y8()});var yR={};B1(yR,{runStatus:()=>oe});import{existsSync as u5,readFileSync as A9,readdirSync as RR,statSync as IR}from"fs";import{resolve as A5,basename as ge}from"path";import{homedir as me}from"os";function wR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function PR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Vq/X);if(Z>Vq)Z=Vq;let K=Vq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=q1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=wR($),Y=wR(X);return` ${f1}${Q}${r} ${J}[${q}]${r} ${z}% (${V} / ${Y})`}async function de(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${r}
2
+ var St=Object.create;var{getPrototypeOf:yt,defineProperty:jG,getOwnPropertyNames:bt}=Object;var ft=Object.prototype.hasOwnProperty;function _t($){return this[$]}var vt,ht,gt=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?vt??=new WeakMap:ht??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?St(yt($)):{};let J=X||!$||!$.__esModule?jG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of bt($))if(!ft.call(J,q))jG(J,q,{get:_t.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var mt=($)=>$;function ut($,X){this[$]=mt.bind(null,X)}var B1=($,X)=>{for(var Q in X)jG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:ut.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var YR={};B1(YR,{lokiDir:()=>h0,homeLokiDir:()=>HQ,findRepoRootForVersion:()=>AG,REPO_ROOT:()=>L1});import{resolve as h2,dirname as LG}from"path";import{fileURLToPath as dt}from"url";import{existsSync as Zq}from"fs";import{homedir as pt}from"os";function ct(){let $=VR;for(let X=0;X<6;X++){if(Zq(h2($,"VERSION"))&&Zq(h2($,"autonomy/run.sh")))return $;let Q=LG($);if(Q===$)break;$=Q}return h2(VR,"..","..","..")}function AG($){let X=$;for(let Q=0;Q<6;Q++){if(Zq(h2(X,"VERSION"))&&Zq(h2(X,"autonomy/run.sh")))return X;let z=LG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function HQ(){return h2(pt(),".loki")}var VR,L1;var k1=s(()=>{VR=LG(dt(import.meta.url));L1=ct()});import{readFileSync as lt}from"fs";import{resolve as it,dirname as at}from"path";import{fileURLToPath as ot}from"url";function j9(){if(n3!==null)return n3;let $="9.28.0";if(typeof $==="string"&&$.length>0)return n3=$,n3;try{let X=at(ot(import.meta.url)),Q=AG(X);n3=lt(it(Q,"VERSION"),"utf-8").trim()}catch{n3="unknown"}return n3}var n3=null;var Kq=s(()=>{k1()});var GR={};B1(GR,{runOrThrow:()=>Ue,run:()=>$1,readStreamCapped:()=>Jq,commandVersion:()=>We,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>WR});async function Jq($,X=WR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function $1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([Jq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Ue($,X={}){let Q=await $1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=He($),Q=await $1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function He($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function We($,X="--version"){if(!await g5($))return null;let z=await $1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var WR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Ge?"":$}var Ge,p0,$5,q1,L61,A1,f1,m5,r;var t7=s(()=>{Ge=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),q1=g2("\x1B[1;33m"),L61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),r=g2("\x1B[0m")});import{existsSync as De}from"fs";async function Z2(){if(GQ!==void 0)return GQ;let $="/opt/homebrew/bin/python3.12";if(De($))return GQ=$,$;let X=await g5("python3.12");if(X)return GQ=X,X;let Q=await g5("python3");return GQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return $1([Q,"-c",$],X)}var GQ;var m2=s(()=>{y8()});var yR={};B1(yR,{runStatus:()=>oe});import{existsSync as u5,readFileSync as A9,readdirSync as RR,statSync as IR}from"fs";import{resolve as A5,basename as ge}from"path";import{homedir as me}from"os";function wR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function PR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Vq/X);if(Z>Vq)Z=Vq;let K=Vq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=q1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=wR($),Y=wR(X);return` ${f1}${Q}${r} ${J}[${q}]${r} ${z}% (${V} / ${Y})`}async function de(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${r}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
@@ -1115,7 +1115,7 @@ Please migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resour
1115
1115
  `+" ".repeat(X))},"\t":{"\n":Array(200).fill(0).map(($,X)=>`
1116
1116
  `+"\t".repeat(X)),"\r":Array(200).fill(0).map(($,X)=>"\r"+"\t".repeat(X)),"\r\n":Array(200).fill(0).map(($,X)=>`\r
1117
1117
  `+"\t".repeat(X))}};(function($){$.DEFAULT={allowTrailingComma:!1}})(jh||(jh={}));(function($){$[$.None=0]="None",$[$.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",$[$.UnexpectedEndOfString=2]="UnexpectedEndOfString",$[$.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",$[$.InvalidUnicode=4]="InvalidUnicode",$[$.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",$[$.InvalidCharacter=6]="InvalidCharacter"})(Lh||(Lh={}));(function($){$[$.OpenBraceToken=1]="OpenBraceToken",$[$.CloseBraceToken=2]="CloseBraceToken",$[$.OpenBracketToken=3]="OpenBracketToken",$[$.CloseBracketToken=4]="CloseBracketToken",$[$.CommaToken=5]="CommaToken",$[$.ColonToken=6]="ColonToken",$[$.NullKeyword=7]="NullKeyword",$[$.TrueKeyword=8]="TrueKeyword",$[$.FalseKeyword=9]="FalseKeyword",$[$.StringLiteral=10]="StringLiteral",$[$.NumericLiteral=11]="NumericLiteral",$[$.LineCommentTrivia=12]="LineCommentTrivia",$[$.BlockCommentTrivia=13]="BlockCommentTrivia",$[$.LineBreakTrivia=14]="LineBreakTrivia",$[$.Trivia=15]="Trivia",$[$.Unknown=16]="Unknown",$[$.EOF=17]="EOF"})(Ah||(Ah={}));(function($){$[$.InvalidSymbol=1]="InvalidSymbol",$[$.InvalidNumberFormat=2]="InvalidNumberFormat",$[$.PropertyNameExpected=3]="PropertyNameExpected",$[$.ValueExpected=4]="ValueExpected",$[$.ColonExpected=5]="ColonExpected",$[$.CommaExpected=6]="CommaExpected",$[$.CloseBraceExpected=7]="CloseBraceExpected",$[$.CloseBracketExpected=8]="CloseBracketExpected",$[$.EndOfFileExpected=9]="EndOfFileExpected",$[$.InvalidCommentToken=10]="InvalidCommentToken",$[$.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",$[$.UnexpectedEndOfString=12]="UnexpectedEndOfString",$[$.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",$[$.InvalidUnicode=14]="InvalidUnicode",$[$.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",$[$.InvalidCharacter=16]="InvalidCharacter"})(Ch||(Ch={}));f$=typeof performance==="object"&&performance&&typeof performance.now==="function"?performance:Date,co=new Set,VC=typeof process==="object"&&!!process?process:{},{AbortController:lH,AbortSignal:Th}=globalThis;if(typeof lH>"u"){Th=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(Q,z){this._onabort.push(z)}},lH=class{constructor(){X()}signal=new Th;abort(Q){if(this.signal.aborted)return;this.signal.reason=Q,this.signal.aborted=!0;for(let z of this.signal._onabort)z(Q);this.signal.onabort?.(Q)}};let $=VC.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",X=()=>{if(!$)return;$=!1,lo("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",X)}}vM1=Symbol("type");hK=class hK extends Array{constructor($){super($);this.fill(0)}};zF=class zF{#$;#X;#Q;#z;#K;#U;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#V;#Y;#q;#Z;#J;#G;#W;#H;#B;#M;#N;#O;#C;#L;#A;#D;#T;static unsafeExposeInternals($){return{starts:$.#C,ttls:$.#L,sizes:$.#O,keyMap:$.#q,keyList:$.#Z,valList:$.#J,next:$.#G,prev:$.#W,get head(){return $.#H},get tail(){return $.#B},free:$.#M,isBackgroundFetch:(X)=>$.#j(X),backgroundFetch:(X,Q,z,Z)=>$.#g(X,Q,z,Z),moveToTail:(X)=>$.#h(X),indexes:(X)=>$.#w(X),rindexes:(X)=>$.#P(X),isStale:(X)=>$.#F(X)}}get max(){return this.#$}get maxSize(){return this.#X}get calculatedSize(){return this.#Y}get size(){return this.#V}get fetchMethod(){return this.#K}get memoMethod(){return this.#U}get dispose(){return this.#Q}get disposeAfter(){return this.#z}constructor($){let{max:X=0,ttl:Q,ttlResolution:z=1,ttlAutopurge:Z,updateAgeOnGet:K,updateAgeOnHas:J,allowStale:q,dispose:V,disposeAfter:Y,noDisposeOnSet:U,noUpdateTTL:H,maxSize:W=0,maxEntrySize:G=0,sizeCalculation:N,fetchMethod:M,memoMethod:A,noDeleteOnFetchRejection:j,noDeleteOnStaleGet:B,allowStaleOnFetchRejection:L,allowStaleOnFetchAbort:C,ignoreFetchAbort:F}=$;if(X!==0&&!F3(X))throw TypeError("max option must be a nonnegative integer");let I=X?io(X):Array;if(!I)throw Error("invalid max value: "+X);if(this.#$=X,this.#X=W,this.maxEntrySize=G||this.#X,this.sizeCalculation=N,this.sizeCalculation){if(!this.#X&&!this.maxEntrySize)throw TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!=="function")throw TypeError("sizeCalculation set to non-function")}if(A!==void 0&&typeof A!=="function")throw TypeError("memoMethod must be a function if defined");if(this.#U=A,M!==void 0&&typeof M!=="function")throw TypeError("fetchMethod must be a function if specified");if(this.#K=M,this.#D=!!M,this.#q=new Map,this.#Z=Array(X).fill(void 0),this.#J=Array(X).fill(void 0),this.#G=new I(X),this.#W=new I(X),this.#H=0,this.#B=0,this.#M=t$.create(X),this.#V=0,this.#Y=0,typeof V==="function")this.#Q=V;if(typeof Y==="function")this.#z=Y,this.#N=[];else this.#z=void 0,this.#N=void 0;if(this.#A=!!this.#Q,this.#T=!!this.#z,this.noDisposeOnSet=!!U,this.noUpdateTTL=!!H,this.noDeleteOnFetchRejection=!!j,this.allowStaleOnFetchRejection=!!L,this.allowStaleOnFetchAbort=!!C,this.ignoreFetchAbort=!!F,this.maxEntrySize!==0){if(this.#X!==0){if(!F3(this.#X))throw TypeError("maxSize must be a positive integer if specified")}if(!F3(this.maxEntrySize))throw TypeError("maxEntrySize must be a positive integer if specified");this.#v()}if(this.allowStale=!!q,this.noDeleteOnStaleGet=!!B,this.updateAgeOnGet=!!K,this.updateAgeOnHas=!!J,this.ttlResolution=F3(z)||z===0?z:1,this.ttlAutopurge=!!Z,this.ttl=Q||0,this.ttl){if(!F3(this.ttl))throw TypeError("ttl must be a positive integer if specified");this.#R()}if(this.#$===0&&this.ttl===0&&this.#X===0)throw TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#$&&!this.#X){if(Wn0("LRU_CACHE_UNBOUNDED"))co.add("LRU_CACHE_UNBOUNDED"),lo("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning","LRU_CACHE_UNBOUNDED",zF)}}getRemainingTTL($){return this.#q.has($)?1/0:0}#R(){let $=new hK(this.#$),X=new hK(this.#$);this.#L=$,this.#C=X,this.#b=(Z,K,J=f$.now())=>{if(X[Z]=K!==0?J:0,$[Z]=K,K!==0&&this.ttlAutopurge){let q=setTimeout(()=>{if(this.#F(Z))this.#y(this.#Z[Z],"expire")},K+1);if(q.unref)q.unref()}},this.#I=(Z)=>{X[Z]=$[Z]!==0?f$.now():0},this.#E=(Z,K)=>{if($[K]){let J=$[K],q=X[K];if(!J||!q)return;Z.ttl=J,Z.start=q,Z.now=Q||z();let V=Z.now-q;Z.remainingTTL=J-V}};let Q=0,z=()=>{let Z=f$.now();if(this.ttlResolution>0){Q=Z;let K=setTimeout(()=>Q=0,this.ttlResolution);if(K.unref)K.unref()}return Z};this.getRemainingTTL=(Z)=>{let K=this.#q.get(Z);if(K===void 0)return 0;let J=$[K],q=X[K];if(!J||!q)return 1/0;let V=(Q||z())-q;return J-V},this.#F=(Z)=>{let K=X[Z],J=$[Z];return!!J&&!!K&&(Q||z())-K>J}}#I=()=>{};#E=()=>{};#b=()=>{};#F=()=>!1;#v(){let $=new hK(this.#$);this.#Y=0,this.#O=$,this.#x=(X)=>{this.#Y-=$[X],$[X]=0},this.#f=(X,Q,z,Z)=>{if(this.#j(Q))return 0;if(!F3(z))if(Z){if(typeof Z!=="function")throw TypeError("sizeCalculation must be a function");if(z=Z(Q,X),!F3(z))throw TypeError("sizeCalculation return invalid (expect positive integer)")}else throw TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return z},this.#k=(X,Q,z)=>{if($[X]=Q,this.#X){let Z=this.#X-$[X];while(this.#Y>Z)this.#S(!0)}if(this.#Y+=$[X],z)z.entrySize=Q,z.totalCalculatedSize=this.#Y}}#x=($)=>{};#k=($,X,Q)=>{};#f=($,X,Q,z)=>{if(Q||z)throw TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#w({allowStale:$=this.allowStale}={}){if(this.#V)for(let X=this.#B;;){if(!this.#_(X))break;if($||!this.#F(X))yield X;if(X===this.#H)break;else X=this.#W[X]}}*#P({allowStale:$=this.allowStale}={}){if(this.#V)for(let X=this.#H;;){if(!this.#_(X))break;if($||!this.#F(X))yield X;if(X===this.#B)break;else X=this.#G[X]}}#_($){return $!==void 0&&this.#q.get(this.#Z[$])===$}*entries(){for(let $ of this.#w())if(this.#J[$]!==void 0&&this.#Z[$]!==void 0&&!this.#j(this.#J[$]))yield[this.#Z[$],this.#J[$]]}*rentries(){for(let $ of this.#P())if(this.#J[$]!==void 0&&this.#Z[$]!==void 0&&!this.#j(this.#J[$]))yield[this.#Z[$],this.#J[$]]}*keys(){for(let $ of this.#w()){let X=this.#Z[$];if(X!==void 0&&!this.#j(this.#J[$]))yield X}}*rkeys(){for(let $ of this.#P()){let X=this.#Z[$];if(X!==void 0&&!this.#j(this.#J[$]))yield X}}*values(){for(let $ of this.#w())if(this.#J[$]!==void 0&&!this.#j(this.#J[$]))yield this.#J[$]}*rvalues(){for(let $ of this.#P())if(this.#J[$]!==void 0&&!this.#j(this.#J[$]))yield this.#J[$]}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find($,X={}){for(let Q of this.#w()){let z=this.#J[Q],Z=this.#j(z)?z.__staleWhileFetching:z;if(Z===void 0)continue;if($(Z,this.#Z[Q],this))return this.get(this.#Z[Q],X)}}forEach($,X=this){for(let Q of this.#w()){let z=this.#J[Q],Z=this.#j(z)?z.__staleWhileFetching:z;if(Z===void 0)continue;$.call(X,Z,this.#Z[Q],this)}}rforEach($,X=this){for(let Q of this.#P()){let z=this.#J[Q],Z=this.#j(z)?z.__staleWhileFetching:z;if(Z===void 0)continue;$.call(X,Z,this.#Z[Q],this)}}purgeStale(){let $=!1;for(let X of this.#P({allowStale:!0}))if(this.#F(X))this.#y(this.#Z[X],"expire"),$=!0;return $}info($){let X=this.#q.get($);if(X===void 0)return;let Q=this.#J[X],z=this.#j(Q)?Q.__staleWhileFetching:Q;if(z===void 0)return;let Z={value:z};if(this.#L&&this.#C){let K=this.#L[X],J=this.#C[X];if(K&&J){let q=K-(f$.now()-J);Z.ttl=q,Z.start=Date.now()}}if(this.#O)Z.size=this.#O[X];return Z}dump(){let $=[];for(let X of this.#w({allowStale:!0})){let Q=this.#Z[X],z=this.#J[X],Z=this.#j(z)?z.__staleWhileFetching:z;if(Z===void 0||Q===void 0)continue;let K={value:Z};if(this.#L&&this.#C){K.ttl=this.#L[X];let J=f$.now()-this.#C[X];K.start=Math.floor(Date.now()-J)}if(this.#O)K.size=this.#O[X];$.unshift([Q,K])}return $}load($){this.clear();for(let[X,Q]of $){if(Q.start){let z=Date.now()-Q.start;Q.start=f$.now()-z}this.set(X,Q.value,Q)}}set($,X,Q={}){if(X===void 0)return this.delete($),this;let{ttl:z=this.ttl,start:Z,noDisposeOnSet:K=this.noDisposeOnSet,sizeCalculation:J=this.sizeCalculation,status:q}=Q,{noUpdateTTL:V=this.noUpdateTTL}=Q,Y=this.#f($,X,Q.size||0,J);if(this.maxEntrySize&&Y>this.maxEntrySize){if(q)q.set="miss",q.maxEntrySizeExceeded=!0;return this.#y($,"set"),this}let U=this.#V===0?void 0:this.#q.get($);if(U===void 0){if(U=this.#V===0?this.#B:this.#M.length!==0?this.#M.pop():this.#V===this.#$?this.#S(!1):this.#V,this.#Z[U]=$,this.#J[U]=X,this.#q.set($,U),this.#G[this.#B]=U,this.#W[U]=this.#B,this.#B=U,this.#V++,this.#k(U,Y,q),q)q.set="add";V=!1}else{this.#h(U);let H=this.#J[U];if(X!==H){if(this.#D&&this.#j(H)){H.__abortController.abort(Error("replaced"));let{__staleWhileFetching:W}=H;if(W!==void 0&&!K){if(this.#A)this.#Q?.(W,$,"set");if(this.#T)this.#N?.push([W,$,"set"])}}else if(!K){if(this.#A)this.#Q?.(H,$,"set");if(this.#T)this.#N?.push([H,$,"set"])}if(this.#x(U),this.#k(U,Y,q),this.#J[U]=X,q){q.set="replace";let W=H&&this.#j(H)?H.__staleWhileFetching:H;if(W!==void 0)q.oldValue=W}}else if(q)q.set="update"}if(z!==0&&!this.#L)this.#R();if(this.#L){if(!V)this.#b(U,z,Z);if(q)this.#E(q,U)}if(!K&&this.#T&&this.#N){let H=this.#N,W;while(W=H?.shift())this.#z?.(...W)}return this}pop(){try{while(this.#V){let $=this.#J[this.#H];if(this.#S(!0),this.#j($)){if($.__staleWhileFetching)return $.__staleWhileFetching}else if($!==void 0)return $}}finally{if(this.#T&&this.#N){let $=this.#N,X;while(X=$?.shift())this.#z?.(...X)}}}#S($){let X=this.#H,Q=this.#Z[X],z=this.#J[X];if(this.#D&&this.#j(z))z.__abortController.abort(Error("evicted"));else if(this.#A||this.#T){if(this.#A)this.#Q?.(z,Q,"evict");if(this.#T)this.#N?.push([z,Q,"evict"])}if(this.#x(X),$)this.#Z[X]=void 0,this.#J[X]=void 0,this.#M.push(X);if(this.#V===1)this.#H=this.#B=0,this.#M.length=0;else this.#H=this.#G[X];return this.#q.delete(Q),this.#V--,X}has($,X={}){let{updateAgeOnHas:Q=this.updateAgeOnHas,status:z}=X,Z=this.#q.get($);if(Z!==void 0){let K=this.#J[Z];if(this.#j(K)&&K.__staleWhileFetching===void 0)return!1;if(!this.#F(Z)){if(Q)this.#I(Z);if(z)z.has="hit",this.#E(z,Z);return!0}else if(z)z.has="stale",this.#E(z,Z)}else if(z)z.has="miss";return!1}peek($,X={}){let{allowStale:Q=this.allowStale}=X,z=this.#q.get($);if(z===void 0||!Q&&this.#F(z))return;let Z=this.#J[z];return this.#j(Z)?Z.__staleWhileFetching:Z}#g($,X,Q,z){let Z=X===void 0?void 0:this.#J[X];if(this.#j(Z))return Z;let K=new lH,{signal:J}=Q;J?.addEventListener("abort",()=>K.abort(J.reason),{signal:K.signal});let q={signal:K.signal,options:Q,context:z},V=(N,M=!1)=>{let{aborted:A}=K.signal,j=Q.ignoreFetchAbort&&N!==void 0;if(Q.status)if(A&&!M){if(Q.status.fetchAborted=!0,Q.status.fetchError=K.signal.reason,j)Q.status.fetchAbortIgnored=!0}else Q.status.fetchResolved=!0;if(A&&!j&&!M)return U(K.signal.reason);let B=W;if(this.#J[X]===W)if(N===void 0)if(B.__staleWhileFetching)this.#J[X]=B.__staleWhileFetching;else this.#y($,"fetch");else{if(Q.status)Q.status.fetchUpdated=!0;this.set($,N,q.options)}return N},Y=(N)=>{if(Q.status)Q.status.fetchRejected=!0,Q.status.fetchError=N;return U(N)},U=(N)=>{let{aborted:M}=K.signal,A=M&&Q.allowStaleOnFetchAbort,j=A||Q.allowStaleOnFetchRejection,B=j||Q.noDeleteOnFetchRejection,L=W;if(this.#J[X]===W){if(!B||L.__staleWhileFetching===void 0)this.#y($,"fetch");else if(!A)this.#J[X]=L.__staleWhileFetching}if(j){if(Q.status&&L.__staleWhileFetching!==void 0)Q.status.returnedStale=!0;return L.__staleWhileFetching}else if(L.__returned===L)throw N},H=(N,M)=>{let A=this.#K?.($,Z,q);if(A&&A instanceof Promise)A.then((j)=>N(j===void 0?void 0:j),M);K.signal.addEventListener("abort",()=>{if(!Q.ignoreFetchAbort||Q.allowStaleOnFetchAbort){if(N(void 0),Q.allowStaleOnFetchAbort)N=(j)=>V(j,!0)}})};if(Q.status)Q.status.fetchDispatched=!0;let W=new Promise(H).then(V,Y),G=Object.assign(W,{__abortController:K,__staleWhileFetching:Z,__returned:void 0});if(X===void 0)this.set($,G,{...q.options,status:void 0}),X=this.#q.get($);else this.#J[X]=G;return G}#j($){if(!this.#D)return!1;let X=$;return!!X&&X instanceof Promise&&X.hasOwnProperty("__staleWhileFetching")&&X.__abortController instanceof lH}async fetch($,X={}){let{allowStale:Q=this.allowStale,updateAgeOnGet:z=this.updateAgeOnGet,noDeleteOnStaleGet:Z=this.noDeleteOnStaleGet,ttl:K=this.ttl,noDisposeOnSet:J=this.noDisposeOnSet,size:q=0,sizeCalculation:V=this.sizeCalculation,noUpdateTTL:Y=this.noUpdateTTL,noDeleteOnFetchRejection:U=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:H=this.allowStaleOnFetchRejection,ignoreFetchAbort:W=this.ignoreFetchAbort,allowStaleOnFetchAbort:G=this.allowStaleOnFetchAbort,context:N,forceRefresh:M=!1,status:A,signal:j}=X;if(!this.#D){if(A)A.fetch="get";return this.get($,{allowStale:Q,updateAgeOnGet:z,noDeleteOnStaleGet:Z,status:A})}let B={allowStale:Q,updateAgeOnGet:z,noDeleteOnStaleGet:Z,ttl:K,noDisposeOnSet:J,size:q,sizeCalculation:V,noUpdateTTL:Y,noDeleteOnFetchRejection:U,allowStaleOnFetchRejection:H,allowStaleOnFetchAbort:G,ignoreFetchAbort:W,status:A,signal:j},L=this.#q.get($);if(L===void 0){if(A)A.fetch="miss";let C=this.#g($,L,B,N);return C.__returned=C}else{let C=this.#J[L];if(this.#j(C)){let D=Q&&C.__staleWhileFetching!==void 0;if(A){if(A.fetch="inflight",D)A.returnedStale=!0}return D?C.__staleWhileFetching:C.__returned=C}let F=this.#F(L);if(!M&&!F){if(A)A.fetch="hit";if(this.#h(L),z)this.#I(L);if(A)this.#E(A,L);return C}let I=this.#g($,L,B,N),T=I.__staleWhileFetching!==void 0&&Q;if(A){if(A.fetch=F?"stale":"refresh",T&&F)A.returnedStale=!0}return T?I.__staleWhileFetching:I.__returned=I}}async forceFetch($,X={}){let Q=await this.fetch($,X);if(Q===void 0)throw Error("fetch() returned undefined");return Q}memo($,X={}){let Q=this.#U;if(!Q)throw Error("no memoMethod provided to constructor");let{context:z,forceRefresh:Z,...K}=X,J=this.get($,K);if(!Z&&J!==void 0)return J;let q=Q($,J,{options:K,context:z});return this.set($,q,K),q}get($,X={}){let{allowStale:Q=this.allowStale,updateAgeOnGet:z=this.updateAgeOnGet,noDeleteOnStaleGet:Z=this.noDeleteOnStaleGet,status:K}=X,J=this.#q.get($);if(J!==void 0){let q=this.#J[J],V=this.#j(q);if(K)this.#E(K,J);if(this.#F(J)){if(K)K.get="stale";if(!V){if(!Z)this.#y($,"expire");if(K&&Q)K.returnedStale=!0;return Q?q:void 0}else{if(K&&Q&&q.__staleWhileFetching!==void 0)K.returnedStale=!0;return Q?q.__staleWhileFetching:void 0}}else{if(K)K.get="hit";if(V)return q.__staleWhileFetching;if(this.#h(J),z)this.#I(J);return q}}else if(K)K.get="miss"}#m($,X){this.#W[X]=$,this.#G[$]=X}#h($){if($!==this.#B){if($===this.#H)this.#H=this.#G[$];else this.#m(this.#W[$],this.#G[$]);this.#m(this.#B,$),this.#B=$}}delete($){return this.#y($,"delete")}#y($,X){let Q=!1;if(this.#V!==0){let z=this.#q.get($);if(z!==void 0)if(Q=!0,this.#V===1)this.#u(X);else{this.#x(z);let Z=this.#J[z];if(this.#j(Z))Z.__abortController.abort(Error("deleted"));else if(this.#A||this.#T){if(this.#A)this.#Q?.(Z,$,X);if(this.#T)this.#N?.push([Z,$,X])}if(this.#q.delete($),this.#Z[z]=void 0,this.#J[z]=void 0,z===this.#B)this.#B=this.#W[z];else if(z===this.#H)this.#H=this.#G[z];else{let K=this.#W[z];this.#G[K]=this.#G[z];let J=this.#G[z];this.#W[J]=this.#W[z]}this.#V--,this.#M.push(z)}}if(this.#T&&this.#N?.length){let z=this.#N,Z;while(Z=z?.shift())this.#z?.(...Z)}return Q}clear(){return this.#u("delete")}#u($){for(let X of this.#P({allowStale:!0})){let Q=this.#J[X];if(this.#j(Q))Q.__abortController.abort(Error("deleted"));else{let z=this.#Z[X];if(this.#A)this.#Q?.(Q,z,$);if(this.#T)this.#N?.push([Q,z,$])}}if(this.#q.clear(),this.#J.fill(void 0),this.#Z.fill(void 0),this.#L&&this.#C)this.#L.fill(0),this.#C.fill(0);if(this.#O)this.#O.fill(0);if(this.#H=0,this.#B=0,this.#M.length=0,this.#Y=0,this.#V=0,this.#T&&this.#N){let X=this.#N,Q;while(Q=X?.shift())this.#z?.(...Q)}}};Dh=new so,sW=Object.assign(function($,X=!0){if(!$)return null;let Q=$.length>Gn0?oo($,X):Dh.parse($,X);return Q.ok?Q.value:null},{cache:Dh.cache});Nn0=new no;YC=["low","medium","high","xhigh","max"],ZF=[{path:["allowManagedPermissionRulesOnly"],restrictive:!0},{path:["allowManagedHooksOnly"],restrictive:!0},{path:["allowManagedMcpServersOnly"],restrictive:!0},{path:["enforceAvailableModels"],restrictive:!0},{path:["disableAllHooks"],restrictive:!0},{path:["secDefault"],restrictive:!0},{path:["disableClaudeAiConnectors"],restrictive:!0},{path:["disableCommandPluginSources"],restrictive:!0},{path:["disableSideloadFlags"],restrictive:!0},{path:["disableSkillShellExecution"],restrictive:!0},{path:["disableRemoteControl"],restrictive:!0},{path:["disableAgentView"],restrictive:!0},{path:["disableWorkflows"],restrictive:!0},{path:["disableArtifact"],restrictive:!0},{path:["disableBundledSkills"],restrictive:!0},{path:["fastModePerSessionOptIn"],restrictive:!0},{path:["isolatePeerMachines"],restrictive:!0},{path:["strictPluginOnlyCustomization"],restrictive:!0},{path:["disableAutoMode"],restrictive:"disable"},{path:["disableDeepLinkRegistration"],restrictive:"disable"},{path:["permissions","disableBypassPermissionsMode"],restrictive:"disable"},{path:["permissions","disableAutoMode"],restrictive:"disable"},{path:["permissions","blockReadsOutsideWorkingDirectories"],restrictive:!0},{path:["autoMode","classifyAllShell"],restrictive:!0},...[],{path:["worktree","bgIsolation"],restrictive:"worktree"},{path:["enableArtifact"],restrictive:!1},{path:["enableWorkflows"],restrictive:!1},{path:["syncClaudeAiSkills"],restrictive:!1},{path:["syncClaudeAiPlugins"],restrictive:!1},{path:["useAutoModeDuringPlan"],restrictive:!1},{path:["skipDangerousModePermissionPrompt"],restrictive:!1},{path:["skipAutoPermissionPrompt"],restrictive:!1},{path:["enableAllProjectMcpServers"],restrictive:!1},{path:["channelsEnabled"],restrictive:!1},{path:["skipWebFetchPreflight"],restrictive:!1},{path:["skipWorkflowUsageWarning"],restrictive:!1},{path:["autoUploadSessions"],restrictive:!1},{path:["remoteControlAtStartup"],restrictive:!1},{path:["remoteTools","allowUnattendedServing"],restrictive:!1},{path:["autoContinueAtUsageLimit"],restrictive:!1},...[],{path:["attribution","sessionUrl"],restrictive:!1},{path:["crossSessionInbound"],restrictive:["refuse","hold"]},{path:["remoteControl","shareHostProfile"],restrictive:["off","basic"]},{path:["modelProposedGoals"],restrictive:["disabled","alwaysAsk"]},{path:["maxEffortLevel"],restrictive:YC},{path:["feedbackDrafts"],restrictive:"off"},{path:["askUserQuestionTimeout"],restrictive:"never"},{path:["dialogExpiry"],restrictive:"never"},{path:["sandbox","enabled"],restrictive:!0},{path:["sandbox","failIfUnavailable"],restrictive:!0},{path:["sandbox","autoAllowBashIfSandboxed"],restrictive:!1},{path:["sandbox","allowUnsandboxedCommands"],restrictive:!1},{path:["sandbox","enableWeakerNestedSandbox"],restrictive:!1},{path:["sandbox","enableWeakerNetworkIsolation"],restrictive:!1},{path:["sandbox","allowAppleEvents"],restrictive:!1},{path:["sandbox","network","allowManagedDomainsOnly"],restrictive:!0},{path:["sandbox","network","strictAllowlist"],restrictive:!0},{path:["sandbox","network","allowAllUnixSockets"],restrictive:!1},{path:["sandbox","network","allowLocalBinding"],restrictive:!1},{path:["sandbox","filesystem","allowManagedReadPathsOnly"],restrictive:!0},{path:["sandbox","filesystem","disabled"],restrictive:!1},{path:["sandbox","credentials","allowPlaintextInject"],restrictive:!1},{path:["sandbox","credentials","sigv4","streaming"],restrictive:"deny"},{path:["sandbox","credentials","sigv4","presigned"],restrictive:"deny"},{path:["sandbox","credentials","sigv4","sigv4a"],restrictive:"deny"}];UC=jn0,AK={};r8(AK,{default:()=>JF});ro=typeof AK=="object"&&AK&&!AK.nodeType&&AK,Fh=ro&&typeof cE=="object"&&cE&&!cE.nodeType&&cE,Ln0=Fh&&Fh.exports===ro,Rh=Ln0?e4.Buffer:void 0,Ih=Rh?Rh.allocUnsafe:void 0;JF=An0;qF=Cn0;to=Tn0;eo=Dn0,wh=Object.create,Fn0=function(){function $(){}return function(X){if(!j4(X))return{};if(wh)return wh(X);$.prototype=X;var Q=new $;return $.prototype=void 0,Q}}(),Rn0=Fn0;$s=In0;Pn0=wn0,xn0=Function.prototype,kn0=Object.prototype,Xs=xn0.toString,Sn0=kn0.hasOwnProperty,yn0=Xs.call(Object);Qs=bn0;HC=fn0;tX=_n0;hn0=vn0;mn0=gn0;un0=zs;pn0=dn0,Ph=Math.max;Zs=cn0;in0=ln0,an0=!VH?_T:function($,X){return VH($,"toString",{configurable:!0,enumerable:!1,value:in0(X),writable:!0})},on0=an0,rn0=Date.now;en0=tn0,$r0=en0(on0),Ks=$r0;Qr0=Xr0;Zr0=zr0;Jr0=Kr0,qr0=Jr0(function($,X,Q,z){un0($,X,Q,z)}),i8=qr0;Yr0=Vr0;Hr0=Ur0;Gr0=Wr0;Nr0=Br0;Or0=Mr0,jr0=Object.prototype,Lr0=jr0.hasOwnProperty;Cr0=Ar0;Dr0=Tr0,Fr0=/\w*$/;Ir0=Rr0,Eh=p7?p7.prototype:void 0,xh=Eh?Eh.valueOf:void 0;Pr0=wr0;sr0=or0;tr0=rr0,kh=Z9&&Z9.isMap,er0=kh?IT(kh):tr0,$t0=er0;zt0=Qt0,Sh=Z9&&Z9.isSet,Zt0=Sh?IT(Sh):zt0,Kt0=Zt0,d1={};d1[Js]=d1[Yt0]=d1[Ct0]=d1[Tt0]=d1[Ut0]=d1[Ht0]=d1[Dt0]=d1[Ft0]=d1[Rt0]=d1[It0]=d1[wt0]=d1[Bt0]=d1[Nt0]=d1[Vs]=d1[Mt0]=d1[Ot0]=d1[jt0]=d1[Lt0]=d1[Pt0]=d1[Et0]=d1[xt0]=d1[kt0]=!0;d1[Wt0]=d1[qs]=d1[At0]=!1;St0=yU;bt0=yt0;_t0=ft0;ht0=vt0,gt0=Object.prototype,mt0=gt0.hasOwnProperty;dt0=ut0;ct0=pt0,yh=p7?p7.isConcatSpreadable:void 0;it0=lt0;at0=Ys;st0=ot0;Us=nt0,$e0=Us(function($,X){var Q={};if($==null)return Q;var z=!1;if(X=fT(X,function(K){return K=gX(K,$),z||(z=K.length>1),K}),tX($,QF($),Q),z)Q=St0(Q,rt0|tt0|et0,ct0);var Z=X.length;while(Z--)dt0(Q,X[Z]);return Q}),nW=$e0;Qe0=Xe0,ze0=Us(function($,X){return $==null?{}:Qe0($,X)}),bU=ze0;AJ();Ve0=qe0;VF=Ye0,Ue0=q0(()=>l({allowedDomains:K0(P()).optional(),deniedDomains:K0(P()).optional().describe("Domains that are always blocked, even if matched by allowedDomains. Supports the same wildcard syntax as allowedDomains. Merged from all settings sources regardless of allowManagedDomainsOnly."),strictAllowlist:$0().optional().describe("When true, the sandbox runtime deterministically denies hosts not in allowedDomains instead of prompting. "+"Enforced for sandboxed commands only \u2014 in-process tools such as WebFetch are not gated by this setting. "+"Only honored from user, managed/policy, or CLI (--settings) settings \u2014 "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored."),allowManagedDomainsOnly:$0().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),allowUnixSockets:K0(P()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),allowAllUnixSockets:$0().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),allowLocalBinding:$0().optional(),allowMachLookup:K0(P().refine(($)=>!($.endsWith("*")?$.slice(0,-1):$).includes("*"),{message:'Wildcards are only allowed as a single trailing "*" (e.g., "com.example.*" or "*" for all services).'})).optional().describe('macOS only: Additional XPC/Mach service names to allow looking up. Supports trailing-wildcard prefix matching (e.g., "com.apple.coresimulator.*"). Needed for tools that communicate via XPC such as the iOS Simulator or Playwright.'),httpProxyPort:S0().optional(),socksProxyPort:S0().optional(),tlsTerminate:l({caCertPath:P().min(1).optional(),caKeyPath:P().min(1).optional()}).optional().describe("[EXPERIMENTAL] Enable in-process TLS termination so the per-request filter can see HTTPS request bodies. Provide a CA cert+key, or omit both to have sandbox-runtime generate an ephemeral one for the session. On native Windows an ephemeral CA cannot pass the sandbox trust check, so omitting the paths uses a persistent CA managed by the sandbox runtime (set up and trusted via /sandbox install); configured paths are passed to the sandbox runtime verbatim, which rejects a bad or incomplete pair at sandbox initialization. "+"Only honored from user, managed/policy, or CLI (`--settings`) settings \u2014 project settings "+"(.claude/settings.json and .claude/settings.local.json) are ignored.")}).optional()),He0=q0(()=>l({allowWrite:K0(P()).optional().describe("Additional paths to allow writing within the sandbox. Merged with paths from Edit(...) allow permission rules."),denyWrite:K0(P()).optional().describe("Additional paths to deny writing within the sandbox. Merged with paths from Edit(...) deny permission rules."),denyRead:K0(P()).optional().describe("Additional paths to deny reading within the sandbox. Merged with paths from Read(...) deny permission rules."),allowRead:K0(P()).optional().describe("Paths to re-allow reading within denyRead regions. Takes precedence over denyRead for matching paths."),allowManagedReadPathsOnly:$0().optional().describe("When true (set in managed settings), only allowRead paths from policySettings are used."),disabled:$0().optional().describe("macOS and Linux/WSL only: skip filesystem isolation entirely while keeping network and seccomp isolation. Ignored on native Windows, where the sandboxed process runs as a separate user with no inherent rights, so skipping the filesystem rules would "+"withhold every access grant rather than loosen them \u2014 filesystem isolation stays on there. "+"Sandboxed commands get unrestricted read/write access to the host filesystem; network egress is still confined to network.allowedDomains. Intended for deployments whose goal is egress control rather than filesystem containment. Does not change Bash prompting: sandbox.autoAllowBashIfSandboxed is independent and still defaults to true, so set it to false to keep prompting for sandboxed commands. Drops the read protection from filesystem.denyRead and credentials.files deny entries for sandboxed commands, since both are enforced by the filesystem layer this turns off; credentials.files mask entries (sentinel binds) and credentials.envVars deny/mask are unaffected. "+"Only honored from user, managed/policy, or CLI (`--settings`) settings \u2014 "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored. If managed settings configure sandbox.filesystem at all, or list any sandbox.credentials.files deny entry, only managed settings can set this: an admin who deployed filesystem restrictions must not have them switched off by a user-writable file. (sandbox.credentials.envVars and credentials.files mask entries "+"do not pin it \u2014 env scrubbing and sentinel binds are independent of the filesystem "+"layer and survive this setting.) When unset, filesystem isolation stays on.")}).optional());WC=q0(()=>a1(Bs,l({path:P().min(1).describe("Path to a credential file or directory. Same resolution as sandbox.filesystem.* paths: absolute, ~ expanded, or relative to the settings file root (project root for project settings, ~/.claude for user settings)."),mode:A0(["deny","mask"]).describe("Access mode for this path. `deny` blocks reads inside the sandbox; `mask` shows sandboxed commands a sentinel-substituted copy (whole-file, or only the spans captured by `extract`) and the "+"host proxy swaps sentinel\u2192real on egress to `injectHosts`. "+"On macOS and Windows `mask` currently degrades to `deny`."),extract:P().optional().describe("Optional regex for structured masking when mode is `mask`. Applied globally to the file; capture group 1 of each match is a credential value, and only those captured spans are replaced "+"with sentinels \u2014 the rest of the file is preserved so a tool "+"that parses it (.netrc, JSON, YAML) still succeeds. Without `extract`, the entire file content is replaced with one sentinel (whole-file masking, suited to single-secret files). If the regex matches nothing, behavior is governed by `onExtractNoMatch` (default `warn`). Accepted but ignored for `deny`."),onExtractNoMatch:A0(["warn","deny","error"]).optional().describe("What to do when `extract` matches nothing in the file \u2014 or, "+"with `decode`, when no candidate survives verification. `warn` (default) emits a stderr warning and leaves the file readable as-is inside the sandbox (fail-open, for credentials that may be legitimately absent); `deny` degrades the entry to "+"mode `deny` so the file is unreadable (fail-closed) \u2014 under "+"`sandbox.filesystem.disabled` it is treated as `error`, since read-denies are dropped in that mode; `error` aborts at sandbox setup so nothing runs until the config is fixed. Only meaningful when mode is `mask` and `extract` or `decode` is set; accepted but ignored otherwise."),decode:A0(["jwt"]).optional().describe("Optional encoded-credential format for `mask` mode. `jwt`: candidates are located with a built-in JWT regex (or the explicit `extract` pattern, if set), verified to actually be JWTs before masking, and replaced with a structurally valid fake JWT so client-side token parsing inside the sandbox keeps working. If no candidate verifies, behavior is governed by `onExtractNoMatch` (default `warn`). Accepted but ignored for `deny`."),maskClaims:K0(P()).optional().describe("Names of top-level payload claims to mask inside each decoded value, instead of replacing the whole token. Each named claim present with a string value gets its own sentinel and the token is rebuilt around the modified payload; all other claims are preserved so a tool that decodes the token and reads a non-secret claim keeps working. Requires `decode`. If no named claim matches in any verified token, behavior is governed by `onExtractNoMatch` (default `warn`). Only meaningful when mode is `mask`; accepted but ignored for `deny`."),maskDuplicates:$0().optional().describe("If true, verbatim occurrences of each captured credential value outside the regex-matched spans are also replaced with the "+"corresponding sentinel \u2014 for a secret repeated where the regex "+"does not reach (e.g. pasted into a comment). Matches raw substrings, so short or common values may corrupt unrelated content; intended for long, high-entropy secrets. Defaults to false. Only meaningful when mode is `mask` and `extract` or `decode` is set; accepted but ignored otherwise."),injectHosts:K0(P()).optional().describe("Optional narrowing of where the proxy substitutes this credential. Only meaningful when mode is `mask`; accepted but ignored for `deny`. If unset, defaults to "+"`network.allowedDomains` \u2014 the credential is injected at "+"every reachable host. Each entry must be reachable via `network.allowedDomains` (sandbox-runtime validates this).")}).superRefine(($,X)=>{if($.mode==="mask"&&$.path.endsWith("/"))X.addIssue({code:s4.custom,path:["path"],message:'Credential mode "mask" applies to a single file, not a directory. List the specific credential file(s), or use "deny" for the directory.'});if($.mode==="mask"&&$.extract!==void 0)Gs($.extract,X);if($.mode==="mask"&&$.maskClaims!==void 0)Ws($.maskClaims,$.decode,X)}))),GC=q0(()=>a1(Bs,l({name:gK().describe("Environment variable name."),mode:A0(["deny","mask"]).describe("Access mode for this environment variable. `deny` unsets the variable for sandboxed commands; `mask` shows sandboxed commands a sentinel value and the "+"host proxy swaps sentinel\u2192real on egress to `injectHosts`."),extract:P().optional().describe("Optional regex for structured masking when mode is `mask`. Applied globally to the value; capture group 1 of each match is a credential value, and only those captured spans are "+"replaced with sentinels \u2014 the rest of the value is preserved "+"so a tool that parses it (a `DATABASE_URL` connection string, a composite `KEY:SECRET` pair) still succeeds inside the sandbox. Without `extract`, the entire value is replaced with one sentinel (whole-value masking, suited to bare tokens). If the regex matches nothing, behavior is governed by `onExtractNoMatch` (default `warn`). Cannot be combined with `decode` (the decode path never consults it). Accepted but ignored for `deny`."),onExtractNoMatch:A0(["warn","deny","error"]).optional().describe("What to do when `extract` matches nothing in the value. `warn` (default) emits a stderr warning and lets the variable pass through unmasked (fail-open, for credentials that may be legitimately absent); `deny` unsets the variable inside the sandbox (fail-closed); `error` aborts at sandbox setup so nothing runs until the config is fixed. Only meaningful when mode is `mask` and `extract` is set without `decode`. On a mask entry with `decode`, the runtime takes the decode path and never consults this field, so a fail-closed setting "+"cannot be honored \u2014 `deny` and `error` are rejected there; "+"only `warn` is accepted. In all other shapes the field is accepted but ignored."),decode:A0(["jwt"]).optional().describe("Optional encoded-credential format for `mask` mode. `jwt`: the variable's whole value is verified to actually be a JWT and replaced with a structurally valid fake JWT so client-side token parsing inside the sandbox keeps working; the proxy swaps the whole fake token on egress. If the value does not verify, the variable is left unmasked with a stderr warning "+"(fail-open). Cannot be combined with `extract` \u2014 the decode "+"path never consults it. Accepted but ignored for `deny`."),maskClaims:K0(P()).optional().describe("Names of top-level payload claims to mask inside the decoded value, instead of replacing the whole token. Each named claim present with a string value gets its own sentinel and the token is rebuilt around the modified payload; all other claims are preserved so claim-reading clients keep working. Requires `decode`. If no named claim matches, the variable is left unmasked with a stderr warning (fail-open). Only meaningful when mode is `mask`; accepted but ignored for `deny`."),injectHosts:K0(P()).optional().describe("Optional narrowing of where the proxy substitutes this credential. Only meaningful when mode is `mask`; accepted but ignored for `deny`. If unset, defaults to "+"`network.allowedDomains` \u2014 the credential is injected at "+"every reachable host. Each entry must be reachable via `network.allowedDomains` (sandbox-runtime validates this).")}).superRefine(($,X)=>{if($.mode==="mask"&&$.extract!==void 0)Gs($.extract,X);if($.mode==="mask"&&$.maskClaims!==void 0)Ws($.maskClaims,$.decode,X);if($.mode==="mask"&&$.decode!==void 0&&$.extract!==void 0)X.addIssue({code:s4.custom,path:["extract"],message:"extract cannot be combined with decode on an env entry \u2014 the runtime takes the decode path (whole-value JWT verification) and never consults extract, silently disabling the structured masking. Remove one of the two."});if($.mode==="mask"&&$.decode!==void 0&&($.onExtractNoMatch==="deny"||$.onExtractNoMatch==="error"))X.addIssue({code:s4.custom,path:["onExtractNoMatch"],message:"onExtractNoMatch cannot be honored on an env entry with decode \u2014 the runtime takes the decode path (which is unconditionally fail-open on verify failure) and never consults extract or onExtractNoMatch. Remove onExtractNoMatch, or drop decode to use extract-based masking (whose no-match handling does honor it)."})}))),mK=["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SESSION_TOKEN"],BC=q0(()=>l({accessKeyIdVar:gK().describe("Name of the masked env var holding the AWS access key id."),secretAccessKeyVar:gK().describe("Name of the masked env var holding the AWS secret access key."),sessionTokenVar:gK().optional().describe("Optional name of the masked env var holding the AWS session token (temporary credentials). When set, the proxy sends the real token as x-amz-security-token on re-signed requests and adds it to the signed header set if the client did not.")}).superRefine(($,X)=>{let Q=new Map;for(let[z,Z]of[["accessKeyIdVar",$.accessKeyIdVar],["secretAccessKeyVar",$.secretAccessKeyVar],["sessionTokenVar",$.sessionTokenVar]]){if(Z===void 0)continue;let K=Q.get(Z);if(K!==void 0)X.addIssue({code:s4.custom,path:[z],message:`${z} names the same env var ('${Z}') as ${K} \u2014 each pair member must be a distinct variable.`});else Q.set(Z,z)}})),We0=q0(()=>{let $=A0(["deny","passthrough"]);return l({streaming:$.optional().describe("Policy for aws-chunked streaming uploads (x-amz-content-sha256: STREAMING-*): per-chunk signatures chain off the seed signature, so re-signing would require rewriting the body. `deny` (default) fails closed with a 403; `passthrough` forwards the request unre-signed (the upstream will reject its signature)."),presigned:$.optional().describe("Policy for presigned URLs (X-Amz-Algorithm/X-Amz-Signature in the query, no Authorization header): the signature lives in the URL itself. `deny` (default) or `passthrough`."),sigv4a:$.optional().describe("Policy for SigV4A (AWS4-ECDSA-P256-SHA256) asymmetric signatures: there is no shared-key HMAC to recompute. `deny` (default) or `passthrough`.")})}),Ge0=q0(()=>l({files:K0(WC()).optional().describe("Credential files or directories to protect. `deny` blocks reads inside the sandbox; `mask` substitutes a sentinel inside the sandbox (whole-file, or per-`extract` capture) and injects the real value at the proxy. On macOS and Windows `mask` degrades to `deny`."),envVars:K0(GC()).optional().describe("Environment variables to protect. `deny` unsets the variable for sandboxed commands; `mask` substitutes a sentinel inside the sandbox and injects the real value at the proxy."),allowPlaintextInject:$0().optional().describe("Allow sentinel\u2192real substitution on the plain-HTTP proxy path. "+"Defaults to false: without TLS termination the upstream identity is unverified and the credential travels in cleartext. Set only for trusted-network test fixtures. Only honored from user, managed/policy, or CLI (`--settings`) "+"settings \u2014 project settings (.claude/settings.json and "+".claude/settings.local.json) are ignored."),awsPairs:K0(BC()).optional().describe("Explicit groupings of masked env vars into AWS credential pairs for SigV4 re-signing, for non-standard variable names. The conventional AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN trio is paired automatically when masked. Only honored from user, managed/policy, or CLI (`--settings`) "+"settings \u2014 project settings (.claude/settings.json and "+".claude/settings.local.json) are ignored. A member is only usable when its env var is forwarded as a whole-value `mask` entry (an entry carrying `extract` or `decode` does not "+"qualify \u2014 re-signing needs the whole real value). A pair "+"whose key id or secret member is unusable never re-signs: it is dropped, unless it names a conventional AWS variable, in which case it is forwarded as an inert suppressor so implicit auto-pairing stays overridden. A pair whose ONLY unusable member is the session token still re-signs, without an x-amz-security-token (temporary-credential requests fail upstream until the entry is fixed)."),sigv4:We0().optional().describe("Policies for AWS SigV4 request shapes the proxy cannot re-sign (streaming, presigned, sigv4a) when they reference a masked credential pair: `deny` (default) or `passthrough`. Only honored from user, managed/policy, or CLI (`--settings`) "+"settings \u2014 project settings (.claude/settings.json and "+".claude/settings.local.json) are ignored.")}).superRefine(($,X)=>{let Q=new Set;for(let[z,Z]of($?.awsPairs??[]).entries()){let K=[["accessKeyIdVar",Z.accessKeyIdVar],["secretAccessKeyVar",Z.secretAccessKeyVar],["sessionTokenVar",Z.sessionTokenVar]],J=new Set;for(let[q,V]of K){if(V===void 0)continue;if(Q.has(V))X.addIssue({code:s4.custom,path:["awsPairs",z,q],message:`"${V}" appears in more than one awsPairs slot (within or across pairs) \u2014 each variable can fill exactly one slot.`});J.add(V)}for(let q of J)Q.add(q)}}).optional()),Ms=q0(()=>l({enabled:$0().optional(),failIfUnavailable:$0().optional().describe("Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed-settings deployments that require sandboxing as a hard gate."),autoAllowBashIfSandboxed:$0().optional(),allowUnsandboxedCommands:$0().optional().describe("Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. Default: true."),network:Ue0(),filesystem:He0(),credentials:Ge0(),ignoreViolations:R0(P(),K0(P())).optional(),enableWeakerNestedSandbox:$0().optional(),enableWeakerNetworkIsolation:$0().optional().describe("macOS only: Allow access to com.apple.trustd.agent in the sandbox. Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates when using httpProxyPort with a MITM proxy and custom CA. "+"**Reduces security** \u2014 opens a potential data exfiltration vector through the trustd service. Default: false"),allowAppleEvents:$0().optional().describe("macOS only: Allow sandboxed commands to send Apple Events (and look up the appleeventsd Mach service). Needed for `open`, `osascript`, and browser-based auth flows that open URLs. "+"**Removes code-execution isolation** \u2014 sandboxed commands can launch other applications "+"unsandboxed with no user prompt, and can script running apps (e.g. Terminal) subject to the user's per-app TCC automation consent. "+"Only honored from user, managed/policy, or CLI (--settings) settings \u2014 "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored. Default: false"),excludedCommands:K0(P()).optional(),ripgrep:l({command:P(),args:K0(P()).optional()}).optional().describe("Custom ripgrep configuration for bundled ripgrep support. "+"Only honored from user, managed/policy, or CLI (--settings) settings \u2014 "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored."),bwrapPath:a1(($)=>typeof $==="string"&&bh($)?$:void 0,P()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the bwrap (bubblewrap) binary. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings."),socatPath:a1(($)=>typeof $==="string"&&bh($)?$:void 0,P()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the socat binary used for the sandbox network proxy. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings.")}).passthrough()),_h=new Set(["disableAllHooks"]);Ne0=["allowedMcpServers","deniedMcpServers","allowManagedMcpServersOnly","disabledMcpjsonServers","allowManagedHooksOnly","allowedHttpHookUrls","strictKnownMarketplaces","allowedMarketplaces","blockedMarketplaces","strictPluginOnlyCustomization","availableModels","enforceAvailableModels"];Os=["CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX","CLAUDE_CODE_USE_FOUNDRY","CLAUDE_CODE_USE_ANTHROPIC_AWS","CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD","CLAUDE_CODE_USE_MANTLE","CLAUDE_CODE_USE_GATEWAY","ANTHROPIC_FOUNDRY_RESOURCE","ANTHROPIC_VERTEX_PROJECT_ID","ANTHROPIC_AWS_WORKSPACE_ID","ANTHROPIC_GOOGLE_CLOUD_PROJECT","ANTHROPIC_GOOGLE_CLOUD_LOCATION","ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID","CLOUD_ML_REGION"],hh=["CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_ANTHROPIC_AWS","CLAUDE_CODE_USE_MANTLE"],Le0=["OTEL_LOG_RAW_API_BODIES","OTEL_LOG_USER_PROMPTS","OTEL_LOG_ASSISTANT_RESPONSES","OTEL_LOG_TOOL_CONTENT","OTEL_LOG_TOOL_DETAILS","OTEL_LOGS_EXPORTER","ENABLE_BETA_TRACING_DETAILED","BETA_TRACING_ENDPOINT","ANT_OTEL_LOGS_EXPORTER"],Ae0=[gh,`ANT_${gh}`],Ce0={apiKeyHelper:["ANTHROPIC_BASE_URL","_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL"],awsAuthRefresh:[...hh,"ANTHROPIC_BEDROCK_BASE_URL","ANTHROPIC_AWS_BASE_URL","ANTHROPIC_BEDROCK_MANTLE_BASE_URL"],awsCredentialExport:[...hh,"ANTHROPIC_BEDROCK_BASE_URL","ANTHROPIC_AWS_BASE_URL","ANTHROPIC_BEDROCK_MANTLE_BASE_URL"],gcpAuthRefresh:["CLAUDE_CODE_USE_VERTEX","CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD","ANTHROPIC_VERTEX_BASE_URL","ANTHROPIC_GOOGLE_CLOUD_BASE_URL"]},Te0=["CLAUDE_CODE_MEMORY_API_BASE_URL","CLAUDE_CODE_MEMORY_API_TOKEN"],js=["ANTHROPIC_BASE_URL","_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL","ANTHROPIC_BEDROCK_BASE_URL","ANTHROPIC_VERTEX_BASE_URL","ANTHROPIC_FOUNDRY_BASE_URL","ANTHROPIC_AWS_BASE_URL","ANTHROPIC_GOOGLE_CLOUD_BASE_URL","ANTHROPIC_BEDROCK_MANTLE_BASE_URL","CLAUDE_CODE_ARTIFACTS_API_BASE_URL","CLAUDE_CODE_ARTIFACTS_API_TOKEN","CLAUDE_CODE_ARTIFACT_ASSET_BASE_URL","CLAUDE_CODE_ARTIFACT_LIVE_BASE_URL","CLAUDE_CODE_ARTIFACT_SYNC_BASE_URL","CLAUDE_CODE_ARTIFACT_VIEWER_BASE_URL",...Te0],De0=[{endpoint:"ANTHROPIC_BASE_URL",companions:["_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_BEDROCK_BASE_URL",selection:"CLAUDE_CODE_USE_BEDROCK",companions:["CLAUDE_CODE_SKIP_BEDROCK_AUTH","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_VERTEX_BASE_URL",selection:"CLAUDE_CODE_USE_VERTEX",companions:["CLAUDE_CODE_SKIP_VERTEX_AUTH","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_FOUNDRY_BASE_URL",selection:"CLAUDE_CODE_USE_FOUNDRY",companions:["CLAUDE_CODE_SKIP_FOUNDRY_AUTH","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_AWS_BASE_URL",selection:"CLAUDE_CODE_USE_ANTHROPIC_AWS",companions:["CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_GOOGLE_CLOUD_BASE_URL",selection:"CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD",companions:["CLAUDE_CODE_SKIP_ANTHROPIC_GOOGLE_CLOUD_AUTH","ANTHROPIC_CUSTOM_HEADERS"]},{endpoint:"ANTHROPIC_BEDROCK_MANTLE_BASE_URL",selection:"CLAUDE_CODE_USE_MANTLE",companions:["CLAUDE_CODE_SKIP_MANTLE_AUTH","ANTHROPIC_CUSTOM_HEADERS"]}],pM1=g3(De0.flatMap(($)=>[$.endpoint,...$.companions])),Ls=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","CLAUDE_CODE_OAUTH_TOKEN","AWS_BEARER_TOKEN_BEDROCK","ANTHROPIC_FOUNDRY_API_KEY","ANTHROPIC_FOUNDRY_AUTH_TOKEN","ANTHROPIC_AWS_API_KEY"],Fe0=["CLAUDE_CODE_SKIP_BEDROCK_AUTH","CLAUDE_CODE_SKIP_VERTEX_AUTH","CLAUDE_CODE_SKIP_FOUNDRY_AUTH","CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH","CLAUDE_CODE_SKIP_ANTHROPIC_GOOGLE_CLOUD_AUTH","CLAUDE_CODE_SKIP_MANTLE_AUTH"],As=["ANTHROPIC_MODEL","ANTHROPIC_DEFAULT_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_FABLE_MODEL_NAME","ANTHROPIC_DEFAULT_FABLE_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME","ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_OPUS_MODEL_NAME","ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_SONNET_MODEL_NAME","ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_SMALL_FAST_MODEL","ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION","CLAUDE_CODE_SUBAGENT_MODEL","CLAUDE_CODE_3P_PROBE_WROTE_SONNET_DEFAULT","CLAUDE_CODE_3P_PROBE_WROTE_OPUS_DEFAULT"],Cs=["ANTHROPIC_CUSTOM_MODEL_OPTION","ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION","ANTHROPIC_CUSTOM_MODEL_OPTION_NAME","ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES"],Re0=["CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR","CLAUDE_CODE_GATEWAY_TOKEN_FILE_DESCRIPTOR","CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR","CLAUDE_CODE_WEBSOCKET_AUTH_FILE_DESCRIPTOR"],cM1=["CLAUDE_CODE_OAUTH_TOKEN",...Re0,"CLAUDE_CODE_ARTIFACTS_API_TOKEN","CLAUDE_CODE_SLACK_TAG_TOKEN","CLAUDE_CODE_HFI_BEARER_TOKEN","CLAUDE_BRIDGE_OAUTH_TOKEN","CLAUDE_TRUSTED_DEVICE_TOKEN","AGENT_PROXY_AUTH_TOKEN","CLAUDE_CODE_MCP_SERVE_AUTH_TOKEN","CLAUDE_BG_AUTH_SNAPSHOT_PATH","CLAUDE_BG_SOCKET_TOKENS_PATH","CLAUDE_BG_RV_AUTH","CLAUDE_BG_PTY_AUTH","CLAUDE_BG_CLAIM_AUTH"],Ie0=["AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_SESSION_TOKEN"],Ts=[...Ie0,"AWS_PROFILE","AWS_CONFIG_FILE","AWS_SHARED_CREDENTIALS_FILE","GOOGLE_APPLICATION_CREDENTIALS","GOOGLE_CLOUD_PROJECT"],Ds=["AWS_CONTAINER_CREDENTIALS_FULL_URI","AWS_CONTAINER_CREDENTIALS_RELATIVE_URI","AWS_CONTAINER_AUTHORIZATION_TOKEN","AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE","AWS_EC2_METADATA_SERVICE_ENDPOINT","AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE","AWS_WEB_IDENTITY_TOKEN_FILE","AWS_ROLE_ARN"],Fs=["GCE_METADATA_HOST","GCE_METADATA_ROOT","GCE_METADATA_IP","METADATA_SERVER_DETECTION"],lM1=new Set(["CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST",...Os,...js,...Ls,...Fe0,"CLAUDE_CODE_HOST_AUTH_ENV_VAR","CLAUDE_CODE_SDK_HAS_HOST_AUTH_REFRESH","CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS","CLAUDE_CODE_HOST_CREDS_FILE",...Ts,"GCLOUD_PROJECT","GOOGLE_CLOUD_QUOTA_PROJECT",...Fs,...Ds,"AWS_REGION","AWS_DEFAULT_REGION",...As,"ANTHROPIC_BEDROCK_SERVICE_TIER","ANTHROPIC_BEDROCK_REGION_PREFIX","CLAUDE_CODE_CERT_STORE","DISABLE_GROWTHBOOK","CLAUDE_CODE_AUTO_MODE_MODEL","CLAUDE_CODE_BG_CLASSIFIER_MODEL","CLAUDE_CONTEXT_COLLAPSE_MODEL","CLAUDE_CODE_SUBAGENT_MODEL_FORCE",...Cs]),we0=["apiKeyHelper","awsAuthRefresh","awsCredentialExport","fileSuggestion","gcpAuthRefresh","otelHeadersHelper","processWrapper","policyHelpers","proxyAuthHelper","statusLine","subagentStatusLine"],Rs=["bwrapPath","ripgrep","socatPath"],Pe0=["allowAppleEvents","credentials","enableWeakerNestedSandbox","enableWeakerNetworkIsolation","filesystem.disabled","network.allowAllUnixSockets","network.allowMachLookup","network.allowUnixSockets","network.httpProxyPort","network.socksProxyPort","network.tlsTerminate"],Ee0=new Set(["ANTHROPIC_BEDROCK_REGION_PREFIX","ANTHROPIC_BEDROCK_SERVICE_TIER","ANTHROPIC_CUSTOM_MODEL_OPTION","ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION","ANTHROPIC_CUSTOM_MODEL_OPTION_NAME","ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_FABLE_MODEL_NAME","ANTHROPIC_DEFAULT_FABLE_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME","ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_OPUS_MODEL_NAME","ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION","ANTHROPIC_DEFAULT_SONNET_MODEL_NAME","ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES","ANTHROPIC_FOUNDRY_API_KEY","ANTHROPIC_MODEL","ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION","ANTHROPIC_SMALL_FAST_MODEL","AWS_DEFAULT_REGION","AWS_PROFILE","AWS_REGION","BASH_DEFAULT_TIMEOUT_MS","BASH_MAX_OUTPUT_LENGTH","BASH_MAX_TIMEOUT_MS","CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR","CLAUDE_CODE_API_KEY_HELPER_TTL_MS","CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS","CLAUDE_CODE_DISABLE_TERMINAL_TITLE","CLAUDE_CODE_ENABLE_AUTO_MODE","CLAUDE_CODE_ENABLE_DESIGN_SYNC","CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL","CLAUDE_CODE_ENABLE_TELEMETRY","CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS","CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL","CLAUDE_CODE_MAX_OUTPUT_TOKENS","CLAUDE_CODE_SKIP_BEDROCK_AUTH","CLAUDE_CODE_SKIP_FOUNDRY_AUTH","CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH","CLAUDE_CODE_SKIP_ANTHROPIC_GOOGLE_CLOUD_AUTH","CLAUDE_CODE_SKIP_MANTLE_AUTH","CLAUDE_CODE_SKIP_VERTEX_AUTH","CLAUDE_CODE_SUBAGENT_MODEL","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_FOUNDRY","CLAUDE_CODE_USE_ANTHROPIC_AWS","CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD","CLAUDE_CODE_USE_GATEWAY","CLAUDE_CODE_USE_MANTLE","CLAUDE_CODE_USE_POWERSHELL_TOOL","CLAUDE_CODE_USE_VERTEX","DISABLE_AUTOUPDATER","DISABLE_BUG_COMMAND","DISABLE_COST_WARNINGS","DISABLE_FEEDBACK_COMMAND","DISABLE_GROWTHBOOK","DISABLE_INSTALLATION_CHECKS","DISABLE_UPDATES","ENABLE_TOOL_SEARCH","MAX_MCP_OUTPUT_TOKENS","MAX_THINKING_TOKENS","MCP_CONNECT_TIMEOUT_MS","MCP_TIMEOUT","MCP_TOOL_TIMEOUT","OTEL_EXPORTER_OTLP_COMPRESSION","OTEL_EXPORTER_OTLP_HEADERS","OTEL_EXPORTER_OTLP_LOGS_COMPRESSION","OTEL_EXPORTER_OTLP_LOGS_HEADERS","OTEL_EXPORTER_OTLP_LOGS_PROTOCOL","OTEL_EXPORTER_OTLP_METRICS_COMPRESSION","OTEL_EXPORTER_OTLP_METRICS_HEADERS","OTEL_EXPORTER_OTLP_METRICS_PROTOCOL","OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE","OTEL_EXPORTER_OTLP_PROTOCOL","OTEL_EXPORTER_OTLP_TRACES_COMPRESSION","OTEL_EXPORTER_OTLP_TRACES_HEADERS","OTEL_EXPORTER_OTLP_TRACES_PROTOCOL","OTEL_LOG_ASSISTANT_RESPONSES","OTEL_LOG_TOOL_CONTENT","OTEL_LOG_TOOL_DETAILS","OTEL_LOG_USER_PROMPTS","OTEL_LOGS_EXPORT_INTERVAL","OTEL_LOGS_EXPORTER","OTEL_METRIC_EXPORT_INTERVAL","OTEL_METRICS_EXPORTER","OTEL_METRICS_INCLUDE_ACCOUNT_UUID","OTEL_METRICS_INCLUDE_ENTRYPOINT","OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES","OTEL_METRICS_INCLUDE_SESSION_ID","OTEL_METRICS_INCLUDE_VERSION","OTEL_RESOURCE_ATTRIBUTES","OTEL_SERVICE_NAME","OTEL_TRACES_EXPORT_INTERVAL","OTEL_TRACES_EXPORTER","USE_BUILTIN_RIPGREP","VERTEX_REGION_CLAUDE_3_5_HAIKU","VERTEX_REGION_CLAUDE_3_5_SONNET","VERTEX_REGION_CLAUDE_3_7_SONNET","VERTEX_REGION_CLAUDE_4_0_OPUS","VERTEX_REGION_CLAUDE_4_0_SONNET","VERTEX_REGION_CLAUDE_4_1_OPUS","VERTEX_REGION_CLAUDE_4_5_OPUS","VERTEX_REGION_CLAUDE_4_6_OPUS","VERTEX_REGION_CLAUDE_4_7_OPUS","VERTEX_REGION_CLAUDE_4_8_OPUS","VERTEX_REGION_CLAUDE_5_OPUS","VERTEX_REGION_CLAUDE_FABLE_5","VERTEX_REGION_CLAUDE_FABLE_5_1","VERTEX_REGION_CLAUDE_4_5_SONNET","VERTEX_REGION_CLAUDE_4_6_SONNET","VERTEX_REGION_CLAUDE_5_SONNET","VERTEX_REGION_CLAUDE_HAIKU_4_5","CLAUDE_AUTOCOMPACT_PCT_OVERRIDE","CLAUDE_CODE_AUTO_COMPACT_WINDOW","CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT","CLAUDE_CODE_MAX_CONTEXT_TOKENS","DISABLE_AUTO_COMPACT","DISABLE_COMPACT","CLAUDE_CODE_ALWAYS_ENABLE_EFFORT","CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING","CLAUDE_CODE_DISABLE_FAST_MODE","CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP","CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK","CLAUDE_CODE_DISABLE_THINKING","CLAUDE_CODE_EFFORT_LEVEL","CLAUDE_CODE_PROMPT_CACHE_TTL","CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL","DISABLE_INTERLEAVED_THINKING","DISABLE_PROMPT_CACHING","DISABLE_PROMPT_CACHING_FABLE","DISABLE_PROMPT_CACHING_HAIKU","DISABLE_PROMPT_CACHING_OPUS","DISABLE_PROMPT_CACHING_SONNET","ENABLE_PROMPT_CACHING_1H","ENABLE_PROMPT_CACHING_1H_BEDROCK","FALLBACK_FOR_ALL_PRIMARY_MODELS","FORCE_PROMPT_CACHING_5M","CLAUDE_AUTO_BACKGROUND_TASKS","CLAUDE_CODE_DISABLE_ADVISOR_TOOL","CLAUDE_CODE_DISABLE_AGENT_VIEW","CLAUDE_CODE_DISABLE_ARTIFACT","CLAUDE_CODE_DISABLE_BACKGROUND_TASKS","CLAUDE_CODE_DISABLE_BUNDLED_SKILLS","CLAUDE_CODE_DISABLE_CRON","CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS","CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY","CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING","CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND","CLAUDE_CODE_DISABLE_MEMORY_RO_UNSAVED_NOTICE","CLAUDE_CODE_DISABLE_WORKFLOWS","CLAUDE_CODE_ENABLE_AWAY_SUMMARY","CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING","CLAUDE_CODE_ENABLE_FUNCTION_HOOKS","CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION","CLAUDE_CODE_ENABLE_TASKS","CLAUDE_CODE_FORK_SUBAGENT","CLAUDE_CODE_PLAN_MODE_REQUIRED","DISABLE_DOCTOR_COMMAND","DISABLE_EXTRA_USAGE_COMMAND","DISABLE_INSTALL_GITHUB_APP_COMMAND","DISABLE_LOGIN_COMMAND","DISABLE_LOGOUT_COMMAND","DISABLE_UPGRADE_COMMAND","CLAUDE_AX_SCREEN_READER","CLAUDE_CODE_ACCESSIBILITY","CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN","CLAUDE_CODE_DISABLE_MOUSE","CLAUDE_CODE_DISABLE_MOUSE_CLICKS","CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL","CLAUDE_CODE_FORCE_STRIKETHROUGH","CLAUDE_CODE_HIDE_CWD","CLAUDE_CODE_NATIVE_CURSOR","CLAUDE_CODE_NO_FLICKER","CLAUDE_CODE_SCROLL_SPEED","CLAUDE_CODE_SYNTAX_HIGHLIGHT","API_TIMEOUT_MS","CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS","CLAUDE_CODE_COORDINATOR_WORKER_CHECKIN_SECONDS","CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS","CLAUDE_CODE_GLOB_TIMEOUT_SECONDS","CLAUDE_CODE_MAX_RETRIES","CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION","CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY","CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION","CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS","CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT","CLAUDE_CODE_TEAM_TEARDOWN_PARK_TIMEOUT_MS","CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS","CLAUDE_STREAM_IDLE_TIMEOUT_MS","MAX_STRUCTURED_OUTPUT_RETRIES","MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE","MCP_SERVER_CONNECTION_BATCH_SIZE","SLASH_COMMAND_TOOL_CHAR_BUDGET","TASK_MAX_OUTPUT_LENGTH","MCP_CONNECTION_NONBLOCKING","CLAUDE_ENABLE_BYTE_WATCHDOG","CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK","CLAUDE_ENABLE_STREAM_WATCHDOG"]),xe0=new Set(["API_FORCE_IDLE_TIMEOUT","CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC","DISABLE_ERROR_REPORTING","DISABLE_TELEMETRY","DO_NOT_TRACK"]),ke0=new Set(["ENABLE_BETA_TRACING_DETAILED","OTEL_LOG_RAW_API_BODIES"]),Se0=/auth|key|token|cookie|secret|credential|session|signature|passw|jwt|assertion|cert|oidc|org|tenant|account|project|workspace|user|email|identity|principal|consumer|client|host|url|base|target|upstream|endpoint|proxy|forward|route|fallback|override|apigw|x-goog-|l5d-|bypass|guardrail|amz|x-ms-|azureml|extra-parameters|envoy|helicone|litellm|cf-aig|cf-access|beta|version/;be0=/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;rW=["acceptEdits","auto","bypassPermissions","default","dontAsk","plan"],_e0=[...rW],ve0=_e0;aM1=`Cannot set permission mode: must be one of ${rW.join(", ")}`,oM1={dangerousRemoval:{bypassImmune:!0,classifierRouted:!0},backgroundOperator:{bypassImmune:!1,classifierRouted:!0},suspiciousWindowsPath:{bypassImmune:!1,classifierRouted:!0},isolatePeerMachines:{bypassImmune:!0,classifierRouted:!1},restrictedMode:{bypassImmune:!0,classifierRouted:!1},outsideReadsBlocked:{bypassImmune:!0,classifierRouted:!1},...{}},he0=["auto","iterm2","terminal_bell","iterm2_with_bell","kitty","ghostty","notifications_disabled"],ge0=["normal","vim"],me0=["auto","12-hour","24-hour","24-hour-utc"],ue0=["auto","tmux","iterm2","in-process"],de0=["dark","light","light-daltonized","dark-daltonized","light-ansi","dark-ansi"],pe0=["auto",...de0],ce0=["auto","alwaysAsk","disabled"],ae0=String.raw`\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-[^}]*)?\}`;sM1=q0(()=>A0(["local","user","project","dynamic","enterprise","claudeai","managed","agent"])),nM1=q0(()=>A0(["stdio","sse","sse-ide","http","ws","sdk"])),eX=q0(()=>G0("comms").optional().catch(void 0)),c3=q0(()=>S0().int().positive()),Ps=q0(()=>S0().int().positive().optional().catch(void 0).describe("@internal CCR backend wire hint; folded into timeout at parse."));ne0=q0(()=>l({type:G0("stdio").optional(),command:P().min(1,"Command cannot be empty"),args:K0(P()).default([]),env:R0(P(),P()).optional(),timeout:c3().optional(),alwaysLoad:$0().optional(),role:eX()})),re0=q0(()=>$0()),xs=q0(()=>l({clientId:P().optional(),callbackPort:S0().int().positive().optional(),authServerMetadataUrl:P().url().startsWith("https://",{message:"authServerMetadataUrl must use https://"}).optional(),scopes:P().min(1).optional(),xaa:re0().optional()})),ks=q0(()=>l({name:P(),permission_policy:A0(["always_allow","always_ask","always_deny"]).optional()})),Ss=q0(()=>l({type:G0("sse"),url:P(),headers:R0(P(),P()).optional(),headersHelper:P().optional(),oauth:xs().optional(),timeout:c3().optional(),request_timeout_ms:Ps(),tools:K0(ks()).optional(),alwaysLoad:$0().optional(),discoveryCache:$0().optional(),role:eX(),toolPermissions:R0(P(),UF()).optional()}).transform(Es)),te0=q0(()=>l({type:G0("sse-ide"),url:P(),ideName:P(),ideRunningInWindows:$0().optional(),timeout:c3().optional(),alwaysLoad:$0().optional(),role:eX()})),ee0=q0(()=>l({type:G0("ws-ide"),url:P(),ideName:P(),authToken:P().optional(),ideRunningInWindows:$0().optional(),timeout:c3().optional(),alwaysLoad:$0().optional(),role:eX()})),ys=q0(()=>l({type:A0(["http","streamable-http"]).transform(()=>"http"),url:P(),headers:R0(P(),P()).optional(),headersHelper:P().optional(),oauth:xs().optional(),timeout:c3().optional(),request_timeout_ms:Ps(),tools:K0(ks()).optional(),alwaysLoad:$0().optional(),discoveryCache:$0().optional(),role:eX(),toolPermissions:R0(P(),UF()).optional()}).transform(Es)),$01=["command","args","env","headersHelper"],X01=new Set(["http","streamable-http","sse"]),Q01=/[\p{Cc}\p{Cf}\u2028\u2029]/u,z01=/[\p{Cc}\p{Cf}\u2028\u2029]/gu;_s=q0(()=>R0(P(),Y1()).check(($)=>{let X=(z,Z)=>{$.issues.push({code:"custom",path:z,message:Z,input:$.value})};for(let z of $01)if(Object.hasOwn($.value,z))X([z],`"${z}" is not allowed in managed settings: only http/sse URL servers can be delivered this way, and a managed settings document must not name a program to run`);if(!X01.has($.value.type))X(["type"],'managed settings can only deliver "http" or "sse" servers');let Q=$.value.url;if(typeof Q==="string"&&!Z01(Q))X(["url"],"managed settings servers must use a valid https:// url");for(let[z,Z,K]of fs($.value))if(Q01.test(Z))X(z.split("."),"contains control or invisible format characters (in a key or a value); a managed settings document must not be able to print escape sequences");else if(!K&&oe0(Z))X(z.split("."),"${VAR} references are not expanded in managed settings; use a literal value (a managed settings document must not read the user's environment)")}).pipe(c0([ys(),Ss()])));K01=q0(()=>l({type:G0("ws"),url:P(),headers:R0(P(),P()).optional(),headersHelper:P().optional(),timeout:c3().optional(),alwaysLoad:$0().optional(),role:eX()})),J01=q0(()=>l({type:G0("sdk"),name:P(),timeout:c3().optional(),alwaysLoad:$0().optional()})),UF=q0(()=>A0(["allow","ask","blocked"])),q01=q0(()=>l({type:G0("claudeai-proxy"),url:P(),id:P(),displayName:P().optional(),iconUrl:P().optional(),timeout:c3().optional(),alwaysLoad:$0().optional(),toolPermissions:R0(P(),UF()).optional(),stateless:$0().optional(),cachedInitResponse:R0(P(),Y1()).nullish(),discoverSupport:A0(["supported","legacy","unknown"]).optional().catch(void 0),cachedDiscoverResponse:R0(P(),Y1()).nullish(),eligible:$0().nullish(),ineligibleReason:P().nullish(),enterpriseManaged:$0().optional()})),NC=q0(()=>c0([ne0(),Ss(),te0(),ee0(),ys(),K01(),J01(),q01()])),rM1=q0(()=>l({mcpServers:R0(P(),NC())})),tM1=m3()==="macos"?"\u23FA":"\u25CF",eM1=q0(()=>a1(YF,A0(ve0))),$O1=q0(()=>a1(YF,A0(rW))),W01=new Set(["metadata.google.internal","metadata.goog","metadata","instance-data","instance-data.ec2.internal","ip6-localhost","ip6-loopback","localhost.localdomain","localhost4","localhost4.localdomain4","localhost6","localhost6.localdomain6"]),mh=new Set(["100.100.100.200","168.63.129.16","192.0.0.192"]);O01=["bash","powershell"],VK=q0(()=>P().optional().describe('Permission rule syntax to filter when this hook runs (e.g., "Bash(git *)"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.'));HF=q0(()=>{let{BashCommandHookSchema:$,PromptHookSchema:X,AgentHookSchema:Q,HttpHookSchema:z,McpToolHookSchema:Z}=j01();return dW("type",[$,X,Q,z,Z])}),ms=q0(()=>l({matcher:P().optional().describe('String pattern to match (e.g. tool names like "Write")'),hooks:K0(HF()).describe("List of hooks to execute when the matcher matches")})),iH=q0(()=>Ql0(A0(W9),K0(ms())));C01=new Set,T01=new Set(["mcpServers","managedMcpServers","lspServers","pluginConfigs","enabledPlugins","extraKnownMarketplaces","env","skillOverrides","modelSettings"]),D01=new Set(["metadata","mcpServers","lspServers"]),zO1=new Set([...D01,"experimental"]);tW=new Set(["PreToolUse","PermissionRequest"]);ZO1=[`git@${VX}:`,`ssh://git@${VX}/`],KO1=[`https://${VX}`,`https://${VX}/`,VX],JO1=`users.noreply.${VX}`,R01=/[:/\\?#@\s]/;qO1=ao(function($){let X=I01($);while(X.startsWith("www."))X=X.slice(4);return X},($)=>$,50);P01=/\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]|\x1b[\]PX^_][^\x1b\x07]*(?:\x07|\x1b\\)/g;b01=/(?<![^\s\p{P}])\p{M}+/gu;is=/[^\x20-\x7E]| {4,}/;_01=new Set(["claude-community","claude-plugins-community","healthcare"]),v01=new Set(["claude-code-marketplace","claude-code-plugins","claude-plugins-official","anthropic-marketplace","anthropic-plugins","agent-skills","anthropic-agent-skills","life-sciences","knowledge-work-plugins","claude-for-legal","claude-for-financial-services","financial-services-plugins","first-party-plugins","claude-tag-plugins"]),as=new Set([...v01,..._01]),h01=/(?:official[^a-z0-9]*(anthropic|claude)|(?:anthropic|claude)[^a-z0-9]*official|^(?:anthropic|claude)[^a-z0-9]*(marketplace|plugins|official))/i,g01=/[^\u0020-\u007E]/;r4=q0(()=>P().startsWith("./")),q9=q0(()=>r4().endsWith(".json")),ch=q0(()=>c0([G0("."),r4()])),lh=q0(()=>c0([r4().refine(($)=>$.endsWith(".mcpb")||$.endsWith(".dxt"),{message:"MCPB file path must end with .mcpb or .dxt"}).describe("Path to MCPB file relative to plugin root"),P().url().refine(($)=>$.endsWith(".mcpb")||$.endsWith(".dxt"),{message:"MCPB URL must end with .mcpb or .dxt"}).describe("URL to MCPB file")])),OC=q0(()=>r4().endsWith(".md")),jC=q0(()=>c0([OC(),r4()])),os={inline:"--plugin-dir session plugins",builtin:"built-in plugins","skills-dir":"plugins auto-loaded from .claude/skills/",synced:"plugins synced from your claude.ai account"};ss=q0(()=>P().min(1,"Marketplace must have a name").refine(($)=>!$.includes(" "),{message:'Marketplace name cannot contain spaces. Use kebab-case (e.g., "my-marketplace")'}).refine(($)=>!Kn.test($),{message:"Marketplace name cannot contain control or bidirectional-formatting characters"}).refine(($)=>!$.includes("/")&&!$.includes("\\")&&!$.includes("..")&&$!==".",{message:'Marketplace name cannot contain path separators (/ or \\), ".." sequences, or be "."'}).refine(($)=>!m01($),{message:"Marketplace name impersonates an official Anthropic/Claude marketplace"}).superRefine(($,X)=>{let Q=$.toLowerCase();if(!u01(Q))return;X.addIssue({code:"custom",message:`Marketplace name "${Q}" is reserved for ${os[Q]}`})})),eW=q0(()=>P().min(1,"Plugin name cannot be empty").refine(($)=>!$.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).refine(($)=>!Kn.test($),{message:"Plugin name cannot contain control or bidirectional-formatting characters"})),NF=q0(()=>l({name:P().min(1,"Author name cannot be empty").describe("Display name of the plugin author or organization"),email:P().optional().describe("Contact email for support or feedback"),url:P().optional().describe("Website, GitHub profile, or organization URL")})),d01=q0(()=>l({$schema:P().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:eW().describe("Unique identifier for the plugin, used for namespacing (prefer kebab-case)"),displayName:P().optional().describe('Human-readable name shown in UI (e.g., "GitHub Utils"). Falls back to `name` when omitted. Unlike `name`, may contain spaces and any casing; not used for namespacing or lookup.'),version:P().optional().describe("Semantic version (e.g., 1.2.3) following semver.org specification"),description:P().optional().describe("Brief, user-facing explanation of what the plugin provides"),author:NF().optional().describe("Information about the plugin creator or maintainer"),homepage:P().url().optional().describe("Plugin homepage or documentation URL"),repository:P().optional().describe("Source code repository URL"),license:P().optional().describe("SPDX license identifier (e.g., MIT, Apache-2.0)"),keywords:K0(P()).optional().describe("Tags for plugin discovery and categorization"),defaultEnabled:$0().optional().describe("Whether the plugin starts enabled when the user has no explicit enabled/disabled setting for it (default: true). Explicit enabledPlugins values always win, and a plugin required by an enabled dependent is enabled regardless of this value."),dependencies:K0(g11()).optional().describe(`Plugins that must be enabled for this plugin to function. Bare names (no "@marketplace") are resolved against the declaring plugin's own marketplace.`),metadata:a1(($)=>o1($)?$:void 0,R0(P(),Y1()).optional()).describe("Free-form metadata for the plugin author's own use (e.g. entitlement or catalog fields). Preserved on the parsed manifest but not read by Claude Code.")})),VO1=q0(()=>l({description:P().optional().describe("Brief, user-facing explanation of what these hooks provide"),hooks:tA(()=>iH()).optional().describe("The hooks provided by the plugin, in the same format as the one used for settings"),modules:K0(P()).max(p01,{message:"hooks.json `modules` names one hooks module per plugin; a second entry is refused"}).optional().describe("The hooks module: one path, relative to this hooks.json, of a module exporting register(on). What it hooks and calls is read from its source before it loads; `claude plugin validate` shows the result."),surface:P().min(1).optional().describe("The surface module: one path, relative to this hooks.json, of a module whose exports draw the hooks module's `Client` elements on a surface, without `$`. Loaded beside the hooks module; meaningless without one.")}).refine(($)=>$.hooks!==void 0||($.modules?.length??0)>0,{message:"hooks.json must have `hooks` (the hook matchers) or `modules` (hooks modules), or both"}).refine(($)=>$.surface===void 0||($.modules?.length??0)>0,{message:"hooks.json `surface` names the surface module of a hooks module; without `modules` there is nothing to draw its Clients"})),c01=q0(()=>l({hooks:c0([q9().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),tA(()=>iH()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)"),K0(c0([q9().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),tA(()=>iH()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)")]))])})),l01=q0(()=>l({source:jC().optional().describe("Path to command markdown file, relative to plugin root"),content:P().optional().describe("Inline markdown content for the command"),description:P().optional().describe("Command description override"),argumentHint:P().optional().describe('Hint for command arguments (e.g., "[file]")'),model:P().optional().describe("Default model for this command"),allowedTools:K0(P()).optional().describe("Tools allowed when command runs")}).refine(($)=>$.source&&!$.content||!$.source&&$.content,{message:'Command must have either "source" (file path) or "content" (inline markdown), but not both'})),i01=q0(()=>l({commands:c0([jC().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded \u2014 list its files here if you want both."),K0(jC().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded \u2014 list its files here if you want both.")).describe("List of command file or skill directory paths. When set, the commands/ directory is not auto-loaded."),R0(P(),l01()).describe('Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., "about" \u2192 "/plugin:about")')])})),a01=q0(()=>l({agents:c0([OC().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded \u2014 list its files here if you want both."),K0(OC().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded \u2014 list its files here if you want both.")).describe("List of agent file paths. When set, the agents/ directory is not auto-loaded.")])})),o01=q0(()=>l({skills:c0([ch().describe('Path to a skill directory, relative to the plugin root ("." / "./" denote the plugin root itself). Loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring a specific subdirectory replaces the skills/ scan).'),K0(ch().describe('Path to a skill directory, relative to the plugin root ("." / "./" denote the plugin root itself).')).describe("List of skill directory paths, loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring specific subdirectories replaces the skills/ scan).")])})),s01=q0(()=>c0([P(),K0(P())])),ns=q0(()=>l({outputStyles:c0([r4().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded \u2014 list its files here if you want both."),K0(r4().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded \u2014 list its files here if you want both.")).describe("List of output-style directory or file paths. When set, the output-styles/ directory is not auto-loaded.")])})),n01=q0(()=>P().max(64).regex(/^[a-z][a-z0-9_-]*$/,"must match ^[a-z][a-z0-9_-]*$")),t01=q0(()=>l({id:n01(),remote:P().max(256).regex(/^(npm:[@a-z0-9/._-]+(@[a-z0-9._+-]+)?|github:[\w.-]+\/[\w.-]+@[\w./-]+#.+\.js)$/,"must be npm:<pkg>[@ver] or github:<owner>/<repo>@<ref>#<path>.js").optional(),integrity:P().max(512).regex(/^sha(256|384|512)-[A-Za-z0-9+/=]+$/,"must be SRI form: sha256-, sha384-, or sha512-<base64>").optional()}).strict()),e01=q0(()=>l({syntaxHighlighting:l({hljsLanguages:K0(t01()).max(r01)}).strict()})),rs=q0(()=>l({themes:c0([r4().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded \u2014 list its files here if you want both."),K0(r4().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded \u2014 list its files here if you want both.")).describe("List of theme directory or file paths. When set, the themes/ directory is not auto-loaded.")])})),$11=q0(()=>l({})),ih=q0(()=>P().min(1)),X11=q0(()=>P().min(2).refine(($)=>$.startsWith("."),{message:'File extensions must start with dot (e.g., ".ts", not "ts")'})),Q11=q0(()=>l({mcpServers:c0([q9().describe("MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)"),lh().describe("Path or URL to MCPB file containing MCP server configuration"),R0(P(),NC()).describe("MCP server configurations keyed by server name"),K0(c0([q9().describe("Path to MCP servers configuration file"),lh().describe("Path or URL to MCPB file"),R0(P(),NC()).describe("Inline MCP server configurations")])).describe("Array of MCP server configurations (paths, MCPB files, or inline definitions)")])})),ts=q0(()=>l({type:A0(["string","number","boolean","directory","file"]).describe("Type of the configuration value"),title:P().describe("Human-readable label shown in the config dialog"),description:P().describe("Help text shown beneath the field in the config dialog"),required:$0().optional().describe("If true, validation fails when this field is empty"),default:c0([P(),S0(),$0(),K0(P())]).optional().describe("Default value used when the user provides nothing"),multiple:$0().optional().describe("For string type: allow an array of strings"),sensitive:$0().optional().describe("If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json"),min:S0().optional().describe("Minimum value (number type only)"),max:S0().optional().describe("Maximum value (number type only)")}).strict()),z11=q0(()=>l({userConfig:R0(P().regex(/^[A-Za-z_]\w*$/,"Option keys must be valid identifiers (letters, digits, underscore; no leading digit) \u2014 they become CLAUDE_PLUGIN_OPTION_<KEY> env vars in hooks"),ts()).optional().describe("User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage. Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Keep sensitive value counts small.")})),Z11=q0(()=>l({channels:K0(l({server:P().min(1).describe("Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers."),displayName:P().optional().describe('Human-readable name shown in the config dialog title (e.g., "Telegram"). Defaults to the server name.'),userConfig:R0(P(),ts()).optional().describe("Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.")}).strict()).describe("Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.")})),ah=q0(()=>ya({command:P().min(1).refine(($)=>{if($.includes(" ")&&!$.startsWith("/"))return!1;return!0},{message:"Command should not contain spaces. Use args array for arguments."}).describe('Command to execute the LSP server (e.g., "typescript-language-server")'),args:K0(ih()).optional().describe("Command-line arguments to pass to the server"),extensionToLanguage:R0(X11(),ih()).refine(($)=>Object.keys($).length>0,{message:"extensionToLanguage must have at least one mapping"}).describe("Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping."),transport:A0(["stdio","socket"]).default("stdio").describe("Communication transport mechanism"),env:R0(P(),P()).optional().describe("Environment variables to set when starting the server"),initializationOptions:Y1().optional().describe("Initialization options passed to the server during initialization"),settings:Y1().optional().describe("Settings passed to the server via workspace/didChangeConfiguration"),workspaceFolder:P().optional().describe("Workspace folder path to use for the server"),startupTimeout:S0().int().positive().optional().describe("Maximum time to wait for server startup (milliseconds)"),shutdownTimeout:S0().int().positive().optional().describe("Maximum time to wait for graceful shutdown (milliseconds)"),restartOnCrash:$0().optional().describe("Whether to restart the server if it crashes"),maxRestarts:S0().int().nonnegative().optional().describe("Maximum number of restart attempts before giving up"),diagnostics:$0().optional().describe("Whether to push publishDiagnostics into the agent context after edits. Set to false to keep LSP navigation (goToDefinition, hover, etc.) but suppress automatic diagnostic injection. Defaults to true.")})),K11=q0(()=>ya({name:P().min(1).describe("Identifier for this monitor, unique within the plugin. Used to dedupe so re-arming (plugin reload, repeat skill invoke) does not spawn duplicates."),command:P().min(1).describe('Shell command to run as a persistent background monitor. Each stdout line is delivered to the model as a <task_notification> event; the process runs for the session lifetime. ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, ${CLAUDE_PROJECT_DIR}, ${user_config.*}, and ${ENV_VAR} are substituted. Runs in the session cwd \u2014 prefix with `cd "${CLAUDE_PLUGIN_ROOT}" && ` if the script needs its own directory.'),description:P().min(1).describe("Short human-readable description of what is being monitored (shown in task panel and notification summary)."),when:c0([G0("always"),P().startsWith("on-skill-invoke:").refine(($)=>$.length>16,{message:"on-skill-invoke: must specify a skill name"})]).default("always").describe('Arm trigger. "always" arms at session start and on plugin reload. "on-skill-invoke:<skill>" arms the first time that skill is dispatched (via Skill tool or slash command).')})),J11=q0(()=>K0(K11()).refine(($)=>new Set($.map((X)=>X.name)).size===$.length,{message:"Monitor names must be unique within a plugin"})),es=q0(()=>l({monitors:c0([q9().describe("Path to a JSON file containing the monitors array, relative to the plugin root"),J11()]).describe("Background watch scripts the host arms as persistent Monitor tasks (unsandboxed, same trust tier as hooks) so plugins need not instruct the model to arm them. When omitted, monitors/monitors.json at the plugin root is loaded if present.")})),q11=q0(()=>l({lspServers:c0([q9().describe("Path to .lsp.json configuration file relative to plugin root"),R0(P(),ah()).describe("LSP server configurations keyed by server name"),K0(c0([q9().describe("Path to LSP configuration file"),R0(P(),ah()).describe("Inline LSP server configurations")])).describe("Array of LSP server configurations (paths or inline definitions)")])})),$n=q0(()=>P().refine(($)=>!$.includes("..")&&!$.includes("//"),"Package name cannot contain path traversal patterns").refine(($)=>{let X=/^@[a-z0-9][a-z0-9-._]*\/[a-z0-9][a-z0-9-._]*$/,Q=/^[a-z0-9][a-z0-9-._]*$/;return X.test($)||Q.test($)},"Invalid npm package name format")),V11=/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9_-])?$/,Y11=/^[0-9a-f]{64}$/,H11=q0(()=>l({sha256:P().regex(Y11)}));G11=q0(()=>l({binaries:Y1().transform(W11).describe("sha256-pinned files to fetch into bin/ at install time, keyed by basename (target triple encoded in the name)")})),B11=q0(()=>l({settings:R0(P(),Y1()).optional().describe("Settings to merge into the user settings while this plugin is enabled. Only the documented allowlisted keys are applied.")})),N11=q0(()=>l({experimental:a1(($)=>o1($)?$:void 0,l({...rs().partial().shape,...e01().partial().shape,...es().partial().shape,...ns().partial().shape,evals:s01().optional().describe("Directory of eval cases for the plugin evaluation harness, relative to the plugin root (default: evals/). A list is accepted; its first entry is the case directory.")}).passthrough().optional().describe("Components whose manifest shape may change without a deprecation cycle. Move a key out of here once it is promoted to stable."))})),M11=q0(()=>l({...d01().shape,...c01().partial().shape,...i01().partial().shape,...a01().partial().shape,...o01().partial().shape,...ns().partial().shape,...rs().partial().shape,...$11().shape,...Z11().partial().shape,...Q11().partial().shape,...q11().partial().shape,...es().partial().shape,...B11().partial().shape,...z11().partial().shape,...G11().partial().shape,...N11().partial().shape})),O11=new Set(["url","github","git","npm","file","directory","skills-dir","hostPattern","pathPattern","settings"]),uK=q0(()=>dW("source",[l({source:G0("url"),url:P().url().describe("Direct URL to marketplace.json file"),headers:R0(P(),P()).optional().describe("Custom HTTP headers (e.g., for authentication)"),headersHelper:BF().optional().describe("Command that prints a JSON object of HTTP headers (e.g. a short-lived auth token). Its output overrides `headers` and, like `headers`, is inherited by same-origin archive downloads from this marketplace. Runs from a fixed directory (the Claude config home, never the session's), so give a bare command found via PATH or an absolute path; it is re-run on later refreshes of this marketplace.")}),l({source:G0("github"),repo:P().describe('GitHub repository in owner/repo format. ONLY in the managed-settings policy lists (strictKnownMarketplaces / blockedMarketplaces) the owner-wildcard form "owner/*" matches every repository under exactly that owner. Everywhere else (marketplace add, extraKnownMarketplaces, known_marketplaces.json) the value '+"must name a single repository \u2014 a wildcard is taken literally and fails to clone."),ref:P().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:P().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:K0(P()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:$0().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),l({source:G0("git"),url:P().describe("Full git repository URL"),ref:P().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:P().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:K0(P()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:$0().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),l({source:G0("npm"),package:$n().describe("NPM package containing marketplace.json")}),l({source:G0("file"),path:P().describe("Local file path to marketplace.json")}),l({source:G0("directory"),path:P().describe("Local directory containing .claude-plugin/marketplace.json")}),l({source:G0("skills-dir")}).describe("Policy-list sentinel for the ~/.claude/skills/ auto-load (@skills-dir plugins). In strictKnownMarketplaces: opt the scan back IN (by default any allowlist blocks it). In blockedMarketplaces: turn the scan OFF without otherwise restricting marketplaces. Only meaningful in those two managed-settings lists (areLocalPluginDirsAllowedByPolicy); known_marketplaces.json / marketplace add etc. ignore it."),l({source:G0("hostPattern"),hostPattern:P().describe('Regex pattern to match the host/domain extracted from any marketplace source type. For github sources, matches against github.com. For git sources (SSH or HTTPS), extracts the hostname from the URL. Use in strictKnownMarketplaces to allow all marketplaces from a specific host (e.g., "^github\\.mycompany\\.com$").')}),l({source:G0("pathPattern"),pathPattern:P().describe('Regex pattern matched against the .path field of file and directory sources. Use in strictKnownMarketplaces to allow filesystem-based marketplaces alongside hostPattern restrictions for network sources. Use ".*" to allow all filesystem paths, or a narrower pattern (e.g., "^/opt/approved/") to restrict to specific directories.')}),l({source:G0("settings"),name:ss().refine(($)=>!as.has($.toLowerCase()),{message:"Reserved marketplace names cannot be used with settings sources. validateOfficialNameSource only accepts github/git sources from anthropics/* for these names; a settings source would be rejected after loadAndCacheMarketplace has already written to disk with cleanupNeeded=false."}).describe("Marketplace name. Must match the extraKnownMarketplaces key (enforced); the synthetic manifest is written under this name. Same validation "+"as PluginMarketplaceSchema plus reserved-name rejection \u2014 "+"validateOfficialNameSource runs after the disk write, too late to clean up."),plugins:K0(C11()).describe("Plugin entries declared inline in settings.json"),owner:NF().optional()}).describe("Inline marketplace manifest defined directly in settings.json. The reconciler writes a synthetic marketplace.json to the cache; diffMarketplaces detects edits via isEqual on the stored source (the plugins array is inside this object, so edits surface as sourceChanged).")])),ej=q0(()=>P().length(40).regex(/^[a-f0-9]{40}$/,"Must be a full 40-character lowercase git commit SHA")),Xn=q0(()=>P().regex(/^[0-9a-fA-F]{64}$/,"Must be a 64-character hex SHA-256 digest"));A11=q0(()=>l({source:G0("archive"),url:P().url().refine(L11,{message:j11}).describe("HTTPS URL of a zip archive containing the plugin. The plugin root (the directory holding .claude-plugin/) may be at the top of the archive "+"or nested one directory deep \u2014 a single wrapping directory is stripped."),sha256:Xn().optional().describe("SHA-256 digest of the archive. When set, every download is verified against it and the install is refused on mismatch. It also serves as the version identity when neither plugin.json nor the marketplace entry declares a `version`. Recommended. Note the update signal is the version string (plugin.json "+"version, else the entry version, else this digest) \u2014 changing only the digest "+"while a version is declared does not trigger an update.")}).describe("Plugin distributed as a zip archive fetched over HTTPS \u2014 for hosting on any "+"static file server or artifact repository (S3, GitLab, nginx) with no git or npm on the client. Authentication: the entry's own `headers` / `headersHelper` (bound to this URL), overlaid on the enclosing url-source marketplace's headers (static or `headersHelper`-minted) when the archive shares its origin.")),Qn=q0(()=>c0([a1(($)=>$==="."?"./":$,r4()).describe("Path to the plugin root, relative to the marketplace root (the directory containing .claude-plugin/, not .claude-plugin/ itself)"),l({source:G0("npm"),package:$n().or(P().refine(($)=>/^(?:file|https?|git(?:\+https?|\+ssh)?|ssh|github|gitlab|bitbucket):/i.test($)||!$.includes(".."),'Package reference cannot contain ".." path segments')).describe("Package name (or url, or local path, or anything else that can be passed to `npm` as a package)"),version:P().optional().describe("Specific version or version range (e.g., ^1.0.0, ~2.1.0)"),registry:P().url().optional().describe("Custom NPM registry URL (defaults to using system default, likely npmjs.org)")}).describe("NPM package as plugin source"),l({source:G0("url"),url:P().describe("Full git repository URL (https:// or git@)"),ref:P().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:ej().optional().describe("Specific commit SHA to use")}),l({source:G0("github"),repo:P().describe("GitHub repository in owner/repo format"),ref:P().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:ej().optional().describe("Specific commit SHA to use")}),l({source:G0("git-subdir"),url:P().describe("Git repository: GitHub owner/repo shorthand, https://, or git@ URL"),path:P().min(1).describe('Subdirectory within the repo containing the plugin (e.g., "tools/claude-plugin"). Cloned sparsely using partial clone (--filter=tree:0) to minimize bandwidth for monorepos.'),ref:P().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:ej().optional().describe("Specific commit SHA to use")}).describe("Plugin located in a subdirectory of a larger repository (monorepo). Only the specified subdirectory is materialized; the rest of the repo is not downloaded."),A11(),l({source:G0("command"),command:P().min(1).max(GF,{message:"command must not be longer than the install consent UI can display"}).refine(($)=>!is.test($),{message:"command must be printable ASCII (letters, digits, punctuation, single spaces) with no runs of 4 or more spaces"}).describe("Shell command that prints the absolute path of the plugin directory on stdout (exactly one line) and exits 0. It must leave a complete plugin in that directory before exiting; the directory is copied into the plugin cache, so the printed path may change between runs (it is re-resolved on every install and update, and once per session in the background). Runs through the platform shell (sh on macOS/Linux, cmd.exe on Windows) from the user's home directory with Claude Code's subprocess environment."),timeout:S0().int().positive().max(600).optional().describe("Seconds to wait for the command before giving up (default: 60)"),mode:A0(["copy","link"]).optional().describe("copy (default): the printed directory is copied into the plugin cache and content-hashed, so it may be deleted afterwards. link: the cache entry links to the printed directory "+"in place (no copy, no size limit; macOS/Linux) \u2014 for large exports; the directory must then stay "+"valid while Claude Code runs, and a different printed path is what signals new content.")}).describe("Plugin directory produced by a locally installed tool (e.g. an IDE that renders its plugin for the currently selected SDK). Claude Code runs the command, copies the directory it prints, and re-runs it in the background at startup to pick up changes."),l({source:G0("unsupported"),error:P().optional()}).describe("Placeholder for source types this Claude Code version does not recognize, or a known type whose fields failed validation (then `error` "+"holds the reason). Never authored by hand \u2014 PluginMarketplaceSchema rewrites "+"unparseable sources to this so the entry remains in marketplace.plugins (detectDelistedPlugins must not see it as removed). Install attempts fail at cachePlugin with an actionable message.")])),C11=q0(()=>l({name:eW().describe("Plugin name as it appears in the target repository"),source:Qn().describe("Where to fetch the plugin from. Must be a remote source \u2014 relative "+"paths have no marketplace repository to resolve against."),description:P().optional(),version:P().optional(),strict:$0().optional(),headers:R0(P(),P()).optional().describe("HTTP headers sent when downloading this entry's `archive` source."),headersHelper:BF().optional().describe("Command that prints a JSON object of HTTP headers for downloading this entry's `archive` source. Runs only when a user explicitly installs or updates this plugin. Unlike a catalog entry, an entry written here does not need `strict: false`: it is declared in a settings file, which has no manifest fields to inline. A declaration in project settings is not operator-authored, so request-routing and client-identity header names are still filtered there. Use an absolute path.")}).refine(($)=>typeof $.source!=="string",{message:'Plugins in a settings-sourced marketplace must use remote sources (github, git-subdir, npm, url, archive, command). Relative-path sources like "./foo" have no marketplace repository to resolve against.'}).refine(($)=>typeof $.source==="string"||$.source.source!=="unsupported",{message:"source.source: 'unsupported' is a parse-time placeholder and cannot be authored. Use a remote source (github, git-subdir, npm, url, archive, command)."})),T11=q0(()=>l({cli:K0(P().max(64)).max(10).optional().describe('First command tokens (e.g. ["stripe"]) \u2014 exact match against commands run this session.'),hosts:K0(P().max(128)).max(20).optional().describe('Hostnames (e.g. ["api.stripe.com"]) \u2014 exact, case-insensitive match against '+"hostnames seen in https?:// URLs in bash commands run this session. Bare hostname only: lowercase, no scheme, no port, no path."),filesRead:K0(P().max(256)).max(10).optional().describe('Glob patterns (e.g. ["**/*.tf"]) \u2014 the plugin is relevant when a file Claude has read '+"this session matches any pattern. Matched against read-file paths, forward-slash normalized, case-insensitive."),manifestDeps:K0(l({file:P().max(256),pattern:P().max(256)})).max(10).optional().describe("Dependency declared in a package manifest. Each {file, pattern} is a pair of RegExp sources: "+"`file` matches the manifest filename (package.json, go.mod, requirements.txt, \u2026); "+"`pattern` matches the dependency declaration inside that file. Evaluated against files read this session."),cwd:K0(P().max(256)).max(10).optional().describe('Glob patterns (e.g. ["Engine/Source/Runtime/Renderer/**"]) \u2014 the plugin is relevant when the '+`session's working directory is at or under a directory matching the pattern. Matched against the cwd both relative to the enclosing git repo root and as an absolute path, forward-slash normalized, case-insensitive. A bare directory (no glob characters) means "cwd is at or under this directory". Known at session start, so this signal can surface a suggestion before the first turn.`)})),D11=q0(()=>l({topic:P().max(64).optional().describe('What the user is working with when this plugin is relevant \u2014 fills "Working with {topic}?". '+'Often the product name (e.g. "Stripe"); use a domain (e.g. "design") when the plugin name does not read naturally as a topic. Defaults to the plugin name with each hyphen-segment capitalized.'),signals:T11().optional().describe("Matchers that determine when the plugin is relevant.")})),F11=q0(()=>M11().partial().extend({name:eW().describe("Unique identifier matching the plugin name"),source:Qn().describe("Where to fetch the plugin from"),headers:R0(P(),P()).optional().describe("Custom HTTP headers for fetching this plugin's archive; overrides the marketplace's"),headersHelper:BF().optional().describe("Command that prints a JSON object of HTTP headers for fetching this plugin's archive (e.g. a short-lived auth token); overrides this entry's `headers` and the marketplace's. Runs only when the user installs or updates this plugin, never during catalog browse. An entry that sets it must be `strict: false` with its manifest inlined here, so consent is informed from the entry alone before the command runs."),category:P().optional().describe('Category for organizing plugins (e.g., "productivity", "development")'),tags:K0(P()).optional().describe("Tags for searchability and discovery"),strict:$0().optional().default(!0).describe("Require the plugin manifest to be present in the plugin folder. If false, the marketplace entry provides the manifest."),relevance:a1(($)=>o1($)?$:void 0,D11().optional()).describe(`Declares when this plugin is relevant to the user's work. Consumed by the spinner tip ("Working with {topic}?"), session-start auto-suggest, and marketplace browse ranking.`)})),R11=q0(()=>l({name:eW()}));w11=new Set(["npm","url","github","git-subdir","archive","command","unsupported"]);E11=/^[A-Za-z0-9_$.-]{1,40}$/;S11=/^[A-Za-z0-9][-A-Za-z0-9._]*$/;v11=q0(()=>l({$schema:P().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:ss(),version:P().optional().describe("Marketplace manifest version"),description:P().optional().describe("Human-readable description of this marketplace"),owner:NF().describe("Marketplace maintainer or curator information"),plugins:K0(Y1()).transform(I11).describe("Collection of available plugins in this marketplace"),forceRemoveDeletedPlugins:$0().optional().describe("When true, plugins removed from this marketplace will be automatically uninstalled and flagged for users"),metadata:l({pluginRoot:P().optional().describe('Base directory for bare plugin source names, relative to the marketplace root (e.g. "./plugins" resolves "source": "formatter" as ./plugins/formatter). Sources that already start with "./" are unaffected.'),version:P().optional().describe("Marketplace version"),description:P().optional().describe("Marketplace description")}).optional().describe("Optional marketplace metadata"),allowCrossMarketplaceDependenciesOn:K0(P()).optional().describe("Marketplace names whose plugins may be auto-installed as dependencies. Only the root marketplace's allowlist applies \u2014 no transitive trust."),renames:R0(P(),P().nullable()).optional().catch(void 0).describe("Append-only map of old plugin name \u2192 current name (or null when removed). The loader follows this on plugin-not-found and migrates user settings to the new name.")})),YO1=q0(()=>a1(_11,v11())),UO1=new RegExp(`^${LC}$`),OF=q0(()=>P().regex(new RegExp(`^${LC}@${LC}$`),"Plugin ID must be in format: plugin@marketplace")),HO1=new RegExp(`[@:\\s/\\\\${vJ}]`,"u"),WO1=new RegExp(`[${vJ}]`,"u"),Kn=/[\p{Cc}\u200E\u200F\u202A-\u202E\u2066-\u2069]/u,h11=/^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\^[^@]*)?$/,g11=q0(()=>c0([P().regex(h11,"Dependency must be a plugin name, optionally qualified with @marketplace").transform(($)=>$.replace(/@\^[^@]*$/,"")),l({name:P().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/),marketplace:P().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/).optional()}).loose().transform(($)=>$.marketplace?`${$.name}@${$.marketplace}`:$.name)])),m11=q0(()=>l({version:P().describe("Currently installed version"),installedAt:P().describe("ISO 8601 timestamp of installation"),lastUpdated:P().optional().describe("ISO 8601 timestamp of last update"),installPath:P().describe("Absolute path to the installed plugin directory"),gitCommitSha:P().optional().describe("Git commit SHA for git-based plugins (for version tracking)"),resolvedVersion:P().optional().describe("Tag-derived semver this install resolved to (when fetched via a version constraint). Used by verifyAndDemote in preference to manifest.version, since the upstream may have forgotten to bump plugin.json."),auto:$0().optional().describe("True when this plugin was pulled in as a dependency rather than installed explicitly. Auto-installed plugins are eligible for removal by the orphan sweep when nothing depends on them. Absent = manual (preserves pre-flag installs)."),...cs(),...ls()})),GO1=q0(()=>l({version:G0(1).describe("Schema version 1"),plugins:R0(OF(),m11()).describe("Map of plugin IDs to their installation metadata")})),u11=q0(()=>A0(["managed","user","project","local"])),d11=q0(()=>l({scope:u11().describe("Installation scope"),projectPath:P().optional().describe("Project path (required for project/local scopes)"),installPath:P().describe("Absolute path to the versioned plugin directory"),version:P().optional().describe("Currently installed version"),installedAt:P().optional().describe("ISO 8601 timestamp of installation"),lastUpdated:P().optional().describe("ISO 8601 timestamp of last update"),gitCommitSha:P().optional().describe("Git commit SHA for git-based plugins"),resolvedVersion:P().optional().describe("Tag-derived semver this install resolved to"),auto:$0().optional().describe("True when pulled in as a dependency. Eligible for orphan sweep."),...cs(),...ls()})),BO1=q0(()=>l({version:G0(2).describe("Schema version 2"),plugins:R0(OF(),K0(d11())).describe("Map of plugin IDs to arrays of installation entries")})),p11=q0(()=>l({source:uK().describe("Where to fetch the marketplace from"),installLocation:P().describe("Local cache path where marketplace manifest is stored"),lastUpdated:P().describe("ISO 8601 timestamp of last marketplace refresh"),autoUpdate:$0().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),NO1=q0(()=>R0(P(),p11())),$L=["aspell","hunspell","ispell"],l11=["autoMode","deepLink","voice","briefView","screenReader"],XL={},$G={autoMode:{buildGate:()=>!1,shape:()=>XL,permissionsShape:()=>XL,permissionModes:()=>[]},deepLink:{buildGate:()=>!0,shape:()=>({disableDeepLinkRegistration:A0(["disable"]).optional().describe("Prevent claude-cli:// protocol handler registration with the OS")})},voice:{buildGate:()=>!0,shape:()=>({voiceEnabled:$0().optional().describe("Enable voice mode (hold-to-talk dictation)")})},briefView:{buildGate:()=>!0,shape:()=>({defaultView:A0(["chat","transcript"]).optional().describe("Default transcript view: chat (SendUserMessage checkpoints only) or transcript (full)")})},screenReader:{buildGate:()=>!1,shape:()=>XL}};oh={Task:"Agent",KillShell:"TaskStop",KillBash:"TaskStop",AgentOutputTool:"TaskOutput",BashOutputTool:"TaskOutput",AgentOutput:"TaskOutput",BashOutput:"TaskOutput",ListPeers:"ListAgents",Brief:"SendUserMessage",ListMcpResources:"ListMcpResourcesTool",ReadMcpResource:"ReadMcpResourceTool",ReadMcpResourceDir:"ReadMcpResourceDirTool"};MO1=`mcp__${Jn}__bash`,OO1=`mcp__${Jn}__web_fetch`;aH={filePatternTools:["Read","Write","Edit","Glob","NotebookRead","NotebookEdit","Cd"],bashPrefixTools:["Bash"],customValidation:{WebSearch:($)=>{if($.includes("*")||$.includes("?"))return{valid:!1,error:"WebSearch does not support wildcards",suggestion:"Use exact search terms without * or ?",examples:["WebSearch(claude ai)","WebSearch(typescript tutorial)"]};return{valid:!0}},WebFetch:($)=>{if($.includes("://")||$.startsWith("http"))return{valid:!1,error:"WebFetch permissions use domain format, not URLs",suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:github.com)"]};if(!$.startsWith("domain:"))return{valid:!1,error:'WebFetch permissions must use "domain:" prefix',suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:*.google.com)"]};return{valid:!0}}}};z51=/(?:^|[^\\])\\[()]/;K51=/^(?:[|&;<>]|\d+[<>])/;$g=q0(()=>Hn()),V51=q0(()=>Hn("allow"));XG=["accept","hold","refuse"],AC=["off","basic","full"],Y51=q0(()=>R0(P(),Tl0()));jO1=q0(()=>Wn(jF())),U51=q0(()=>c0([P(),l({}).passthrough().describe('{ id: stable id (letters, digits, ".", "_", "-"; max 64), text: the tip (max 500 characters, one line), cooldownSessions?: sessions to wait before showing it again (default 0), priority?: tie-break weight among never-shown tips (default 0) }')])),H51=q0(()=>a1(($)=>Array.isArray($)?$.filter((X)=>typeof X==="string"||!!X&&typeof X==="object"&&!Array.isArray(X)):[],K0(U51()))),Gn=q0(()=>l({source:uK().describe("Where to fetch the marketplace from"),installLocation:P().optional().describe("Local cache path where marketplace manifest is stored (auto-generated if not provided)"),autoUpdate:$0().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),Bn=q0(()=>{let $=()=>S0().min(0).max(1e4);return l({input:$(),output:$(),cacheRead:$(),cacheWrite:$()})}),Nn=q0(()=>S0().gt(0).lte(1).optional()),Mn=q0(()=>l({model:P().describe('Model to select, taken verbatim: an alias ("opus"), an Anthropic model ID, or a provider-format ID (Vertex, Bedrock, gateway). Same values --model accepts.'),label:P().optional().describe("Row title. Defaults to the model name."),description:P().optional().describe("Row subtitle. Defaults to a generic description."),behavesAs:P().optional().describe("For a model this version of Claude Code does not know: the ID of a model it does know "+'(e.g. "claude-opus-4-8") whose client-side handling \u2014 prompt profile, capability and effort '+"defaults \u2014 applies to it. Changes neither the row's label nor the model ID sent. Without it, "+"a model-catalog row for a model this version does not know is not offered until Claude Code is updated.")})),LF=q0(()=>l({serverName:P().regex(/^[a-zA-Z0-9_-]+$/,"Server name can only contain letters, numbers, hyphens, and underscores").optional().describe("Name of the MCP server that users are allowed to configure"),serverCommand:K0(P()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for allowed stdio servers"),serverUrl:P().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for allowed remote MCP servers')}).refine(($)=>eT([$.serverName!==void 0,$.serverCommand!==void 0,$.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),AF=q0(()=>l({serverName:P().min(1,"Server name must be non-empty").refine(($)=>$.trim().length>0,{message:"Server name must not be whitespace-only"}).refine(($)=>$===$.trim(),{message:"Server name has leading or trailing whitespace and will never match (names are compared verbatim)"}).optional().describe("Name of the MCP server that is explicitly blocked"),serverCommand:K0(P()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for blocked stdio servers"),serverUrl:P().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for blocked remote MCP servers')}).refine(($)=>eT([$.serverName!==void 0,$.serverCommand!==void 0,$.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),On=q0(()=>l({marketplace:P(),plugin:P()})),W51=q0(()=>a1(($)=>{if(typeof $!=="string"||!OF().safeParse($).success)return $;let X=$.indexOf("@");return{marketplace:$.slice(X+1),plugin:$.slice(0,X)}},On())),G51=/[\x00-\x1f\x7f-\x9f\u2028\u2029]|\p{DI}/u;j51=/\.(exe|ps1)$/i;D51=c11,Qg=["path","script","defaultSettings"];oH=q0(()=>l({path:T51(),timeoutMs:I3(Xg(1000)),refreshIntervalMs:I3(c0([G0(0),Xg(60000)]))}));G7=["macos","linux","windows","wsl"];CF=[...G7,"default"],CC=["path","script","interpreter","outputBehavior","onFailure","retries","timeoutMs","refreshIntervalMs","defaultSettings"],fU=["managedSettings","appendSystemPrompt"],i6=q0(()=>R0(P(),Y1()).superRefine(($,X)=>{for(let Q of["policyHelper","policyHelpers"])if($[Q]!==void 0&&$[Q]!==null)X.addIssue({code:"custom",message:`must not contain "${Q}" \u2014 the default payload is applied as managed settings and cannot configure further policy helpers`});for(let Q of CC)if($[Q]!==void 0&&$[Q]!==null)X.addIssue({code:"custom",message:`must not contain "${Q}" \u2014 a static payload is a managed-settings object, not a policyHelpers entry; entry fields (${CC.join("/")}) belong on the per-OS entries (policyHelpers.${G7.join("/")})`});for(let Q of fU)if($[Q]!==void 0&&$[Q]!==null)X.addIssue({code:"custom",message:`must not contain "${Q}" \u2014 a static payload is the managedSettings SUBTREE, not the helper's stdout envelope; paste the object your helper emits UNDER "managedSettings", not the envelope around it`});for(let Q of CF)if($[Q]!==void 0&&$[Q]!==null)X.addIssue({code:"custom",message:`must not contain "${Q}" \u2014 a static payload is the VALUE of a policyHelpers key (a managed-settings object), never another policyHelpers map; don't paste the map or its "${Q}" line inside the slot`})}));LO1=q0(()=>Tn("linux",i6()));v51=q0(()=>l(Object.fromEntries(CF.map(($)=>[$,a1((X)=>{if(X===null)return;if($!=="default"&&jn(X))return;return X},TC($).optional()).optional()])))),Zg=["skills","agents","hooks","mcp"],Kg=Object.freeze({type:"invalid-entry-stripped"}),h51=q0(()=>c0([l({type:G0("regex").describe('Config variant. This client understands "regex": matches turn output and builds a URL from named capture groups. Entries with other variants are preserved but skipped at runtime.'),pattern:P().describe("Regex matched against turn output (tool results and assistant text)"),url:P().describe("Link target. {name} placeholders are filled from named regex capture groups, e.g. (?<id>...) -> {id}. Values are URL-encoded; the origin must be literal in the template. The scheme must be https, http, or a recognized editor or workspace deep-link scheme: vscode, vscode-insiders, cursor, windsurf, zed, jetbrains, idea, slack, linear, notion, figma."),label:P().optional().describe("Badge text. {name} placeholders filled from named capture groups; defaults to the full match.")}).passthrough(),l({type:P().describe("Config variant discriminator for entries this client does not understand; the entry is preserved as-is and skipped at runtime.")}).passthrough()]));TF=q0(()=>Dn(jF())),Jg=Object.freeze({serverName:"invalid-entry-stripped"});Rn=[{alias:"additionalMarketplaces",canonical:"extraKnownMarketplaces"},{alias:"allowedMarketplaces",canonical:"strictKnownMarketplaces"}];c51=["enabled","enabledPlatforms"];Pn=[...G7.map(($)=>`${$}.defaultSettings`),"default"];xn=new Set(["credentials","network.tlsTerminate"]);B81=new N8(()=>new bn);AO1=N7.state("remote-settings"),CO1=N7.state(yn),T81=new Set(["HTTPS_PROXY","HTTP_PROXY","NO_PROXY","CLAUDE_CODE_PROXY_RESOLVES_HOSTS","CLAUDE_CODE_ENABLE_PROXY_AUTH_HELPER","CLAUDE_CODE_PROXY_AUTH_HELPER_TTL_MS","API_FORCE_IDLE_TIMEOUT","ANTHROPIC_UNIX_SOCKET","NODE_EXTRA_CA_CERTS","CLAUDE_CODE_CERT_STORE","CLAUDE_CODE_CLIENT_CERT","CLAUDE_CODE_CLIENT_KEY","CLAUDE_CODE_CLIENT_KEY_PASSPHRASE","ALL_PROXY","NODE_OPTIONS","NODE_TLS_REJECT_UNAUTHORIZED",...Os,...js,"AWS_ENDPOINT_URL_STS","AWS_ENDPOINT_URL","AWS_ENDPOINT_URL_SSO","AWS_ENDPOINT_URL_SSO_OIDC","AWS_ENDPOINT_URL_BEDROCK","AWS_ENDPOINT_URL_BEDROCK_RUNTIME",...Ts,...Ds,...Fs,"CLOUDSDK_CONFIG","GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES","GCLOUD_PROJECT","CLAUDE_CODE_CUSTOM_OAUTH_URL",...Ls,"CLAUDE_CODE_API_BASE_URL","CLAUDE_CODE_OAUTH_REFRESH_TOKEN","CLAUDE_CODE_OAUTH_SCOPES","CLAUDE_CODE_OAUTH_CLIENT_ID","CLAUDE_CODE_SESSION_ACCESS_TOKEN","CLAUDE_SESSION_INGRESS_TOKEN_FILE","CLAUDE_CODE_ENVIRONMENT_KIND","CLAUDE_CODE_REMOTE_SESSION_ID","ANTHROPIC_FEDERATION_RULE_ID","ANTHROPIC_ORGANIZATION_ID","ANTHROPIC_WORKSPACE_ID","ANTHROPIC_SERVICE_ACCOUNT_ID","ANTHROPIC_IDENTITY_TOKEN","ANTHROPIC_IDENTITY_TOKEN_FILE","ANTHROPIC_SCOPE","ANTHROPIC_PROFILE","ANTHROPIC_CONFIG_DIR","CLAUDE_CODE_FEDERATION_CACHE_DIR","HOME","XDG_CONFIG_HOME","APPDATA","USERPROFILE","ANTHROPIC_CUSTOM_HEADERS","CLAUDE_CODE_HOST_CREDS_FILE","CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST","CLAUDE_CODE_HOST_AUTH_ENV_VAR","CLAUDE_CONFIG_DIR","CLAUDE_SECURESTORAGE_CONFIG_DIR","CLAUDE_CODE_REMOTE_SETTINGS_PATH","CLAUDE_CODE_MANAGED_SETTINGS_PATH","CLAUDE_CODE_DISABLE_ADMIN_ENV_UNION","CLAUDE_CODE_MOCK_REMOTE_SETTINGS","USE_LOCAL_OAUTH","USE_STAGING_OAUTH","CLAUDE_LOCAL_OAUTH_API_BASE","CLAUDE_LOCAL_OAUTH_APPS_BASE","CLAUDE_LOCAL_OAUTH_CONSOLE_BASE","CLAUDE_BRIDGE_BASE_URL","CLAUDE_BRIDGE_OAUTH_TOKEN","CLAUDE_BRIDGE_SESSION_INGRESS_URL","CLAUDE_REMOTE_TOOLS_BRIDGE_URL"].map(($)=>$.toUpperCase()));w81={cli:!0,mcp:!0,"sdk-cli":!0,"sdk-ts":!0,"sdk-py":!0,bench:!0,"claude-vscode":!0,"claude-code-github-action":!0,"local-agent":!0,local_agent:!0,"claude-desktop":!0,remote:!0,remote_baku:!0,remote_cowork:!0,remote_trigger:!0,remote_cowork_trigger:!0,remote_desktop:!0,remote_mobile:!0,claude_in_slack:!0,"claude-in-slack":!0,"claude-in-teams":!0,"claude-desktop-3p":!0,"claude-security":!0,"ssh-remote":!0,"claude-coworker":!0,"claude-coworker-terminal":!0},TO1=new Set(Object.keys(w81)),P81=new Set(["claude-desktop-3p","local-agent"]);DO1=new N8(()=>new gn);y81=["-convert","json","-o","-","--"],b81=["-lint","-s","--"];m81=[{matches:($)=>$.path==="permissions.defaultMode"&&$.code==="invalid_value",tip:{suggestion:'Valid modes: "acceptEdits" (ask before file changes), "plan" (analysis only), "bypassPermissions" (auto-accept all), or "default" (standard behavior)',docLink:`${N2}/iam#permission-modes`}},{matches:($)=>$.path==="apiKeyHelper"&&$.code==="invalid_type",tip:{suggestion:'Provide a shell command that outputs your API key to stdout. The script should output only the API key. Example: "/bin/generate_temp_api_key.sh"'}},{matches:($)=>$.path==="cleanupPeriodDays"&&$.code==="too_small",tip:{suggestion:'cleanupPeriodDays must be at least 1. To keep transcripts for a long time, set a large number (e.g. 3650 for ~10 years). To disable transcript writes entirely, remove this setting and use the --no-session-persistence CLI flag or the SDK persistSession:false option instead. (0 is rejected because it previously silently disabled all transcript writes, which users setting it to mean "never clean up" did not expect.)'}},{matches:($)=>$.path.startsWith("env.")&&$.code==="invalid_type",tip:{suggestion:'Environment variables must be strings. Wrap numbers and booleans in quotes. Example: "DEBUG": "true", "PORT": "3000"',docLink:`${N2}/settings#environment-variables`}},{matches:($)=>($.path==="permissions.allow"||$.path==="permissions.deny")&&$.code==="invalid_type"&&$.expected==="array",tip:{suggestion:'Permission rules must be in an array. Format: ["Tool(specifier)"]. Examples: ["Bash(npm run build)", "Edit(docs/**)", "Read(~/.zshrc)"]. Use * for wildcards.'}},{matches:($)=>$.path.startsWith("hooks.")&&$.code==="invalid_key",tip:{suggestion:"Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",docLink:`${N2}/hooks`}},{matches:($)=>/\.hooks\.\d+\.command$/.test($.path)&&$.code==="invalid_type"&&$.received==="undefined",tip:{suggestion:'Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {"type": "command", "command": "echo", "args": ["hi"]}. For shell form, set `command` to the full shell string: {"type": "command", "command": "echo hi"}.',docLink:`${N2}/hooks#exec-form-and-shell-form`}},{matches:($)=>$.path.includes("hooks")&&$.code==="invalid_type",tip:{suggestion:'Hooks use a matcher + hooks array. The matcher is a string: a tool name ("Bash"), pipe-separated list ("Edit|Write"), or empty to match all. Example: {"PostToolUse": [{"matcher": "Edit|Write", "hooks": [{"type": "command", "command": "echo Done"}]}]}'}},{matches:($)=>$.code==="invalid_type"&&$.expected==="boolean",tip:{suggestion:'Use true or false without quotes. Example: "includeCoAuthoredBy": true'}},{matches:($)=>$.code==="unrecognized_keys",tip:{suggestion:"Check for typos or refer to the documentation for valid fields",docLink:`${N2}/settings`}},{matches:($)=>$.code==="invalid_value"&&$.enumValues!==void 0,tip:{suggestion:void 0}},{matches:($)=>$.code==="invalid_type"&&$.expected==="object"&&$.received===null&&$.path==="",tip:{suggestion:"Check for missing commas, unmatched brackets, or trailing commas. Use a JSON validator to identify the exact syntax error."}},{matches:($)=>$.path==="permissions.additionalDirectories"&&$.code==="invalid_type",tip:{suggestion:'Must be an array of directory paths. Example: ["~/projects", "/tmp/workspace"]. You can also use --add-dir flag or /add-dir command',docLink:`${N2}/iam#working-directories`}}],u81={permissions:`${N2}/iam#configuring-permissions`,env:`${N2}/settings#environment-variables`,hooks:`${N2}/hooks`};RO1=q0(()=>Dn(jF(),{strictPolicyHelperKeys:!0}).strict());l81=new Set(W9);o81=[{key:"allowedMcpServers",schema:LF},{key:"deniedMcpServers",schema:AF}];jg=new WeakMap;Cg={default:"settings.json",cowork:"cowork_settings.json"};w71=[["permissions","defaultMode"],["modelPicker","replaceBuiltInOptions"]];x71=new Set([...[...As].filter(($)=>$!=="ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION"),...Cs,"CLAUDE_CODE_AUTO_MODE_MODEL","CLAUDE_CODE_BG_CLASSIFIER_MODEL","CLAUDE_CONTEXT_COLLAPSE_MODEL","CLAUDE_CODE_SUBAGENT_MODEL_FORCE"]);tn=["managedSourcesBehavior","wslInheritsWindowsSettings"],xF=["policyHelper","policyHelpers"],JL={remote:"server-managed settings",plist:"the managed preferences plist",hklm:"the HKLM policy key",file:"managed-settings.json"};en=["allowedMcpServers","availableModels","strictKnownMarketplaces","allowedChannelPlugins"],f71=["awsPairs","ripgrep"];_71=["allowedMcpServers","availableModels","strictKnownMarketplaces","allowedChannelPlugins","allowedMarketplaces","allowedHttpHookUrls","httpHookAllowedEnvVars"],v71=["allowedMcpServers","availableModels"];d71=["forceLoginOrgUUID","allowedHttpHookUrls","httpHookAllowedEnvVars","allowRead"];zr=["apiKeyHelper","awsAuthRefresh","awsCredentialExport","gcpAuthRefresh"],l71=[...zr,"otelHeadersHelper","proxyAuthHelper","forceLoginOrgUUID","forceLoginMethod","forceLoginGatewayUrl","parentSettingsBehavior","env","modelPicker",...xF,...tn];U41=new qr;w3=Object.freeze({settings:{},errors:[]});N41=["secDefault","prependPlugins","appendPlugins"];O41=new N8(()=>new Yr);F41=new Map([["ENOENT",R8("ENOENT")],["EACCES",R8("EACCES")],["EPERM",R8("EPERM")],["ENOEXEC",R8("ENOEXEC")],["EAGAIN",R8("EAGAIN")],["EMFILE",R8("EMFILE")],["ENOMEM",R8("ENOMEM")],["ETIMEDOUT",R8("ETIMEDOUT")],["ERR_CHILD_PROCESS_STDIO_MAXBUFFER",R8("ERR_CHILD_PROCESS_STDIO_MAXBUFFER")]]),R41=new Map([["SIGTERM",R8("SIGTERM")],["SIGKILL",R8("SIGKILL")],["SIGINT",R8("SIGINT")]]);S41={user:"userSettings",project:"projectSettings",local:"localSettings"},bg={userSettings:"user",projectSettings:"project",localSettings:"local",flagSettings:"flag",policySettings:"managed"},y41=["user","project","local"],b41=new Set(["bypassPermissions","auto","acceptEdits"]),f41=new Set(["project"]),_41=new Set(["project","local"]);process.env.NoDefaultCurrentDirectoryInExePath="1";m41=["enabledPlugins","extraKnownMarketplaces","additionalMarketplaces"];c41=new Set(["EBUSY","EMFILE","ENFILE","ENOTEMPTY","EPERM"])});var _F={};B1(_F,{truthy:()=>ZG,selectClaudeInvokerKind:()=>Fr,sdkQueryProvider:()=>Pr,resolveProvider:()=>F21,emitSdkDegradationEvent:()=>Ir,codexProvider:()=>Er,clineProvider:()=>xr,claudeProvider:()=>fF,buildSdkLoopOptions:()=>wr,aiderProvider:()=>kr});import{mkdirSync as Tr,existsSync as Dr,readFileSync as M21,realpathSync as O21,appendFileSync as j21}from"fs";import{delimiter as L21,dirname as A21,isAbsolute as C21,relative as T21,resolve as tJ,sep as D21}from"path";async function F21($){let X=process.env.LOKI_TARGET_DIR??process.cwd();if($!=="claude"&&bF(X))throw Error(`host command guard is required, but provider '${$}' has no enforced PreToolUse hook`);switch($){case"claude":return Fr(process.env)==="sdk"?Pr():fF();case"codex":return Er();case"cline":return xr();case"aider":return kr();default:throw Error(`unknown provider: ${String($)}`)}}function JG($,X){let Q=process.env[$];return Q&&Q.length>0?Q:X}function ZG($){if($===void 0)return!1;switch($.trim().toLowerCase()){case"1":case"true":case"yes":case"on":return!0;default:return!1}}function Fr($){if(ZG($.LOKI_LEGACY_BASH))return"legacy";return ZG($.LOKI_SDK_LOOP)?"sdk":"legacy"}function KG($){if($==="fable")return"opus";if(process.env.LOKI_ALLOW_HAIKU==="true")switch($){case"planning":return"sonnet";case"development":return"sonnet";case"fast":return"haiku";default:return"sonnet"}switch($){case"planning":return"sonnet";case"development":return"sonnet";case"fast":return"sonnet";default:return"sonnet"}}function Rr($,X){let Q=(process.env.LOKI_MAX_TIER??"").trim().toLowerCase();if(!Q)return X;switch(Q){case"haiku":return KG("fast");case"sonnet":if($==="planning"||$==="fable")return KG("development");return X;case"opus":default:return X}}function R21($){let X=A21($);if(!X||X==="."||X==="/")return;Tr(X,{recursive:!0})}function zG($){try{return O21($)}catch{return tJ($)}}function I21($){return`'${$.replaceAll("'",`'"'"'`)}'`}function bF($){if(ZG(process.env.LOKI_HOST_GUARD))return!0;let X=process.env.LOKI_TARGET_DIR,Q=process.env.LOKI_WORKSPACE_ROOTS;if(!X||!Q||zG(X)!==zG($))return!1;let z=zG($);return Q.split(L21).some((Z)=>{if(!Z)return!1;let K=T21(zG(Z),z);return K===""||K!==".."&&!K.startsWith(`..${D21}`)&&!C21(K)})}function w21(){let $=tJ(L1,"autonomy","hooks","validate-bash.sh");if(!Dr($))throw Error(`host command guard hook is missing: ${$}`);return JSON.stringify({hooks:{PreToolUse:[{matcher:"Bash",hooks:[{type:"command",command:`bash ${I21($)}`}]}]}})}async function QQ($,X,Q){R21($);let z=Q.length>0?`${Q}
1118
- ${X}`:X;await Bun.write($,z)}function fF(){let $=JG("LOKI_CLAUDE_CLI","claude");return{async invoke(X){let Q=KG(X.tier),z=XO(X.tier,Q),Z=Rr(X.tier,z);if(process.env.ANTHROPIC_BASE_URL&&process.env.LOKI_MODEL_OVERRIDE)Z=process.env.LOKI_MODEL_OVERRIDE;await w6();let K=bF(X.cwd);if(K&&!u1("--settings"))return await QQ(X.iterationOutputPath,"","host command guard requires Claude CLI --settings support"),{exitCode:1,capturedOutputPath:X.iterationOutputPath};let J=Ek({tier:X.tier,complexity:process.env.LOKI_COMPLEXITY??"standard",primary:Z,targetDir:X.cwd}),q=[];if(X.mainLoop){let H=X.resumeFirstCall?yk(X.cwd):[];q=H.length>0?H:kk()}let V=[$,"--dangerously-skip-permissions","--model",Z,...J,...q,...K?["--settings",w21()]:[],"-p",X.prompt],Y;if(X.mainLoop){let H=JO(X.tier);if(H)Y={CAVEMAN_DEFAULT_MODE:H}}else Y={CAVEMAN_DEFAULT_MODE:WY()};let U=await $1(V,{cwd:X.cwd,env:Y});return await QQ(X.iterationOutputPath,U.stdout,U.stderr),{exitCode:U.exitCode,capturedOutputPath:X.iterationOutputPath}}}}function Ir($,X){try{let Q=process.env.LOKI_DIR??tJ($,".loki");Tr(Q,{recursive:!0});let z={type:"capability_degraded",source:"sdk_loop",timestamp:new Date().toISOString(),payload:{capability:"sdk_query",fail_closed:!0,...X}};j21(tJ(Q,"events.jsonl"),`${JSON.stringify(z)}
1118
+ ${X}`:X;await Bun.write($,z)}function fF(){let $=JG("LOKI_CLAUDE_CLI","claude");return{async invoke(X){let Q=KG(X.tier),z=XO(X.tier,Q),Z=Rr(X.tier,z);if(process.env.ANTHROPIC_BASE_URL&&process.env.LOKI_MODEL_OVERRIDE)Z=process.env.LOKI_MODEL_OVERRIDE;await w6();let K=bF(X.cwd);if(K&&!u1("--settings"))return await QQ(X.iterationOutputPath,"","host command guard requires Claude CLI --settings support"),{exitCode:1,capturedOutputPath:X.iterationOutputPath};let J=Ek({tier:X.tier,complexity:process.env.LOKI_COMPLEXITY??"standard",primary:Z,targetDir:X.cwd}),q=[];if(X.mainLoop){let G=X.resumeFirstCall?yk(X.cwd):[];q=G.length>0?G:kk()}let V=[$,"--dangerously-skip-permissions","--model",Z,...J,...q,...K?["--settings",w21()]:[],"-p",X.prompt],Y;if(X.mainLoop){let G=JO(X.tier);if(G)Y={CAVEMAN_DEFAULT_MODE:G}}else Y={CAVEMAN_DEFAULT_MODE:WY()};let U=Number(process.env.LOKI_PROVIDER_CALL_TIMEOUT??"7200"),H=Number.isFinite(U)&&U>0?U*1000:void 0,W=await $1(V,{cwd:X.cwd,env:Y,timeoutMs:H});return await QQ(X.iterationOutputPath,W.stdout,W.stderr),{exitCode:W.exitCode,capturedOutputPath:X.iterationOutputPath}}}}function Ir($,X){try{let Q=process.env.LOKI_DIR??tJ($,".loki");Tr(Q,{recursive:!0});let z={type:"capability_degraded",source:"sdk_loop",timestamp:new Date().toISOString(),payload:{capability:"sdk_query",fail_closed:!0,...X}};j21(tJ(Q,"events.jsonl"),`${JSON.stringify(z)}
1119
1119
  `)}catch{}}function wr($){let X={};try{let Q=tM($.cwd);if(Dr(Q)){let z=JSON.parse(M21(Q,"utf8"));if(z.mcpServers&&Object.keys(z.mcpServers).length>0)X.mcpServers=[z.mcpServers],X.strictMcpConfig=!0}}catch{}X.settingSources=["user","project","local"];try{X.effort=O$($.tier,$.complexity)}catch{}try{let Q=QO($.cwd);if(Q!==null){let z=Number(Q);if(Number.isFinite(z)&&z>0)X.maxBudgetUsd=z}}catch{}try{let Q=zO($.model,$.allowHaiku);if(Q)X.fallbackModel=Q}catch{}return X}function Cr($){return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:$}}}async function P21($,X){let Q=tJ(L1,"autonomy","hooks","validate-bash.sh");try{let z=Bun.spawn({cmd:["bash",Q],cwd:X,env:{...process.env,LOKI_HOST_GUARD:"1",LOKI_TARGET_DIR:X},stdin:"pipe",stdout:"pipe",stderr:"ignore"});z.stdin.write(JSON.stringify($)),z.stdin.end();let[Z,K]=await Promise.all([new Response(z.stdout).text(),z.exited]),J=JSON.parse(Z),q=J.hookSpecificOutput?.permissionDecision;if(K===0&&q==="allow")return J;if(K!==0&&q==="deny")return J;return Cr("LOKI_HOST_GUARD: invalid hook verdict was denied.")}catch{return Cr("LOKI_HOST_GUARD: hook execution failed, so the Bash command was denied.")}}function Pr(){return{async invoke($){if(!$.mainLoop)return fF().invoke($);let X=KG($.tier),Q=XO($.tier,X),z=Rr($.tier,Q);if(process.env.ANTHROPIC_BASE_URL&&process.env.LOKI_MODEL_OVERRIDE)z=process.env.LOKI_MODEL_OVERRIDE;let Z=JO($.tier),K="",J=1,q;try{let{query:Y}=await Promise.resolve().then(() => (Ar(),Lr)),U={...process.env};if(Z)U.CAVEMAN_DEFAULT_MODE=Z;let H=wr({tier:$.tier,model:z,cwd:$.cwd,complexity:process.env.DETECTED_COMPLEXITY??process.env.LOKI_COMPLEXITY,allowHaiku:process.env.LOKI_ALLOW_HAIKU==="true"}),W=Y({prompt:$.prompt,options:{model:z,cwd:$.cwd,permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0,includePartialMessages:!0,includeHookEvents:!0,...bF($.cwd)?{hooks:{PreToolUse:[{matcher:"Bash",hooks:[(N)=>P21(N,$.cwd)]}]}}:{},systemPrompt:xk()?{type:"preset",preset:"claude_code",append:ZO()}:{type:"preset",preset:"claude_code"},env:U,...H.mcpServers?{mcpServers:H.mcpServers}:{},...H.strictMcpConfig?{strictMcpConfig:!0}:{},...H.settingSources?{settingSources:H.settingSources}:{},...H.effort?{effort:H.effort}:{},...H.maxBudgetUsd?{maxBudgetUsd:H.maxBudgetUsd}:{},...H.fallbackModel?{fallbackModel:H.fallbackModel}:{}}}),G=await zy(W,{cwd:$.cwd,iteration:process.env.LOKI_ITERATION??"0",hookEventsEnabled:process.env.LOKI_HOOK_EVENTS!=="off",write:(N)=>process.stdout.write(N)});K=G.capturedText,J=G.sawResult?G.exitCode:1,q=G.rateLimit}catch(Y){K+=`
1120
1120
  [sdk-loop error: ${Y.message}]
1121
1121
  `,J=1,Ir($.cwd,{reason:Y.message,tier:$.tier,model:z,iteration:process.env.LOKI_ITERATION??"0"})}await QQ($.iterationOutputPath,K,"");let V={exitCode:J,capturedOutputPath:$.iterationOutputPath};if(q?.resetSeconds&&q.resetSeconds>0)V.rateLimitWaitSeconds=q.resetSeconds;return V}}}function E21($){switch($){case"planning":return"xhigh";case"development":return"high";case"fast":return"low";default:return"high"}}function x21($){let X=(process.env.LOKI_MAX_TIER??"").trim().toLowerCase();if(!X)return $;switch(X){case"haiku":case"low":return"low";case"sonnet":case"high":return $==="xhigh"?"high":$;case"opus":case"xhigh":default:return $}}function Er(){let $=JG("LOKI_CODEX_CLI","codex");return{async invoke(X){let Q=E21(X.tier),z=x21(Q),Z=[$,"exec","--sandbox","workspace-write","--skip-git-repo-check"];if(process.env.LOKI_CODEX_WEB_SEARCH==="true")Z.push("--search");let K=process.env.LOKI_CODEX_OUTPUT_LAST!=="false",J=null;if(K)J=`${X.iterationOutputPath}.last-message`,Z.push("--output-last-message",J);Z.push(X.prompt);let q=await $1(Z,{cwd:X.cwd,env:{LOKI_CODEX_REASONING_EFFORT:z,CODEX_MODEL_REASONING_EFFORT:z}});return await QQ(X.iterationOutputPath,q.stdout,q.stderr),{exitCode:q.exitCode,capturedOutputPath:X.iterationOutputPath}}}}function xr(){let $=JG("LOKI_CLINE_CLI","cline");return{async invoke(X){let Q=process.env.LOKI_CLINE_MODEL??"",z=[$,"-y"];if(Q.length>0)z.push("-m",Q);z.push(X.prompt);let Z=await $1(z,{cwd:X.cwd});return await QQ(X.iterationOutputPath,Z.stdout,Z.stderr),{exitCode:Z.exitCode,capturedOutputPath:X.iterationOutputPath}}}}function kr(){let $=JG("LOKI_AIDER_CLI","aider");return{async invoke(X){let Q=process.env.LOKI_AIDER_MODEL??"claude-opus-4-7",z=[$,"--message",X.prompt,"--yes-always","--no-auto-commits","--model",Q],Z=process.env.LOKI_AIDER_FLAGS??"";if(Z.length>0){for(let J of Z.split(/\s+/))if(J.length>0)z.push(J)}let K=await $1(z,{cwd:X.cwd});return await QQ(X.iterationOutputPath,K.stdout,K.stderr),{exitCode:K.exitCode,capturedOutputPath:X.iterationOutputPath}}}}var vF=s(()=>{y8();k1();j$();eM();Zy()});var fr={};B1(fr,{populatePrdQueue:()=>v21,populateOpenspecQueue:()=>m21,populateMirofishQueue:()=>b21,populateBmadQueue:()=>g21});import{existsSync as a5,mkdirSync as qG,readFileSync as eJ,readdirSync as k21,writeFileSync as l3,renameSync as S21,statSync as y21}from"fs";import{resolve as o5}from"path";async function b21($){let X=o5($.lokiDir,"queue"),Q=o5(X,".mirofish-populated"),z=o5($.lokiDir,"mirofish-tasks.json");if(!a5(z))return;if(a5(Q))return;let Z;try{Z=JSON.parse(eJ(z,"utf8"))}catch{return}if(!Array.isArray(Z)||Z.length===0)return;if(!a5(X))qG(X,{recursive:!0});let K=o5(X,"pending.json");await CQ(K,async()=>{if(a5(Q))return;let{tasks:J,wrapper:q}=VG(K),V=new Set(J.map((H)=>H.id)),Y=0;for(let H=0;H<Z.length;H++){let W=Z[H];if(!W||typeof W!=="object")continue;let G=W,N=typeof G.id==="string"?G.id:`mirofish-${String(H+1).padStart(3,"0")}`;if(V.has(N))continue;let M=typeof G.title==="string"?G.title:`MiroFish Advisory ${H+1}`,A=typeof G.description==="string"?G.description:"",j=G.priority==="high"||G.priority==="low"?G.priority:"medium",B={id:N,title:M,description:A,priority:j,status:"pending",source:"mirofish"};if(typeof G.category==="string")B.category=G.category;J.push(B),V.add(N),Y++}if(Y===0){l3(Q,"");return}let U=q?{...q,tasks:J}:J;YG(K,U),l3(Q,"")})}function VG($){if(!a5($))return{tasks:[],wrapper:null};try{let X=JSON.parse(eJ($,"utf8"));if(Array.isArray(X))return{tasks:X,wrapper:null};if(X&&typeof X==="object"){let Q=X,z=Array.isArray(Q.tasks)?Q.tasks:[],{tasks:Z,...K}=Q;return{tasks:z,wrapper:K}}}catch{}return{tasks:[],wrapper:null}}function YG($,X){let Q=`${$}.tmp.${process.pid}`;l3(Q,JSON.stringify(X,null,2)),S21(Q,$)}function f21($){let X=/^---[ \t]+END[ \t]+[^\r\n]+?[ \t]+DIRECTIVE[ \t]+---[ \t]*\r?$/im.exec($);return X?$.slice(X.index+X[0].length):$}function _21($){let X=/^(table of contents|overview|introduction|summary|appendix|references|changelog|glossary|background|metrics|roadmap|tech stack|deployment|risks|timeline)\b/i,Q=[],z=new Set,Z=!1;for(let K of $.split(`
@@ -1334,4 +1334,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1334
1334
  `),2}case"start":{let{runStart:z}=await Promise.resolve().then(() => (Et(),Pt));return z(Q)}default:return process.stderr.write(`Unknown command: ${X}
1335
1335
  `),process.stderr.write(xt),2}}DR();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var X61=await $61(Bun.argv.slice(2));process.exit(X61);
1336
1336
 
1337
- //# debugId=DBD34F4C4F4079D77C040FC158272AF6
1337
+ //# debugId=5FAD7899F9F8B208D9BC14EB41633B17
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '9.27.3'
78
+ __version__ = '9.28.0'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "9.27.3",
4
+ "version": "9.28.0",
5
5
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider, opencode).",
6
6
  "keywords": [
7
7
  "agent",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "loki-mode",
4
4
  "displayName": "Loki Mode",
5
- "version": "9.27.3",
5
+ "version": "9.28.0",
6
6
  "description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
7
7
  "author": {
8
8
  "name": "Autonomi",