You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@magpie.apache.org by po...@apache.org on 2026/09/21 15:49:36 UTC

(magpie) branch main updated: fix(setup): stop the update skill reporting the dropped lychee domains as drift (#1321)

This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/magpie.git


The following commit(s) were added to refs/heads/main by this push:
     new 3f2cff94 fix(setup): stop the update skill reporting the dropped lychee domains as drift (#1321)
3f2cff94 is described below

commit 3f2cff9405f4339f5378a454ca4d65be54c71360
Author: Jarek Potiuk <ja...@potiuk.com>
AuthorDate: Mon Sep 21 17:49:30 2026 +0200

    fix(setup): stop the update skill reporting the dropped lychee domains as drift (#1321)
    
    Check 4 of `setup-isolated-setup-update` told the agent that the
    dogfooded `allowedDomains` default carries eleven wildcard link-target
    hosts (`*.apache.org`, `*.nist.gov`, `lychee.cli.rs`, …) and that
    "without these, lychee fails the PR-blocking prek check locally on first
    run".  Both claims stopped being true in #501, which moved the lychee
    hook to `offline = true` and dropped those hosts from
    `.claude/settings.json` precisely because the hook no longer reaches
    them.  `docs/setup/secure-agent-setup.md` was updated in that PR; this
    skill was not, so a drift report run against current settings reports
    eleven correctly-absent domains as missing defaults and walks the
    adopter into re-adding dead allowlist entries.
    
    Rewrite the bullet pair to the post-#501 reality: the default allows
    only the two hosts prek needs to bootstrap rustup and `cargo install`
    lychee, the removed hosts are dead weight to *drop* if still present,
    and `enableWeakerNetworkIsolation` stays for native-TLS CLI tools
    (`gh` / `gcloud` / `terraform`) rather than for lychee.
    
    Add a guard so the prose cannot silently drift from the settings again:
    `tools/sandbox-lint/tests/test_doc_domain_consistency.py` parses both
    lists out of the skill and asserts the kept hosts are allowed and the
    dropped hosts are not.  Re-adding `*.nist.gov` to the settings, or
    removing `static.rust-lang.org`, now fails the workspace pytest hook.
    
    Generated-by: Claude Opus 5
---
 docs/mode-economics.md                             |  4 +-
 .../skills/isolated-setup-update/SKILL.md          | 49 +++++++-------
 .../tests/test_doc_domain_consistency.py           | 75 ++++++++++++++++++++++
 3 files changed, 103 insertions(+), 25 deletions(-)

diff --git a/docs/mode-economics.md b/docs/mode-economics.md
index 6b6e2df3..c5528716 100644
--- a/docs/mode-economics.md
+++ b/docs/mode-economics.md
@@ -92,7 +92,7 @@ special-token spellings counted as ordinary text.
 Coverage: **75 of 75 local `skills/*/SKILL.md` files**.
 External `source.md` redirects and harness symlinks are excluded.
 
-Measurement manifest SHA-256: `4556129999018ce339eb0f7c8292e18a424d57716fadd8407f29d9c4a9decec3`.
+Measurement manifest SHA-256: `1ae8680e2a68bddd8a2d9ce0a761b055cebac5ea74312ba2a05196b6f3ba3cd9`.
 
 | Skill file | Measured tokens | Source SHA-256 (first 16 characters) |
 |---|---:|---|
@@ -161,7 +161,7 @@ Measurement manifest SHA-256: `4556129999018ce339eb0f7c8292e18a424d57716fadd8407
 | [setup](../skills/setup/SKILL.md) | 8,724 | `82788542bb240309` |
 | [setup-isolated-setup-doctor](../skills/setup-isolated-setup-doctor/SKILL.md) | 7,950 | `3fa5d728fa080ed0` |
 | [setup-isolated-setup-install](../skills/setup-isolated-setup-install/SKILL.md) | 11,278 | `418ea9794077c6e9` |
-| [setup-isolated-setup-update](../skills/setup-isolated-setup-update/SKILL.md) | 5,069 | `dd56cf376cd14f55` |
+| [setup-isolated-setup-update](../skills/setup-isolated-setup-update/SKILL.md) | 5,111 | `96096e6ac10407d3` |
 | [setup-isolated-setup-verify](../skills/setup-isolated-setup-verify/SKILL.md) | 8,502 | `6f0a2594801bdf27` |
 | [setup-override-upstream](../skills/setup-override-upstream/SKILL.md) | 4,012 | `fb583feb56b7f77c` |
 | [setup-privacy-llm](../skills/setup-privacy-llm/SKILL.md) | 2,145 | `0e27b542a1656846` |
diff --git a/plugins/magpie-setup/skills/isolated-setup-update/SKILL.md b/plugins/magpie-setup/skills/isolated-setup-update/SKILL.md
index 4c899ce4..efed1abe 100644
--- a/plugins/magpie-setup/skills/isolated-setup-update/SKILL.md
+++ b/plugins/magpie-setup/skills/isolated-setup-update/SKILL.md
@@ -257,29 +257,32 @@ Walk each:
    the secure setup before the guard shipped. Report new entries
    the user does not have; do not auto-merge.
 
-   Two network-layer defaults landed with the `lychee` link-check
-   prek hook — surface both if the user's settings predate them
-   (both `sandbox.network.*`):
-
-   - **Broadened `allowedDomains`.** The dogfooded default now
-     allows the curated set the framework's own docs and dev tools
-     reach — `*.crates.io` (so the rust `lychee` hook can
-     `cargo install` lychee), `*.apache.org`, `*.anthropic.com`,
-     `*.claude.com`, `*.mitre.org`, `*.nist.gov`, `*.github.io`,
-     `gist.github.com`, `astral.sh`, `json.schemastore.org`,
-     `lychee.cli.rs`, `sdkman.io`. Without these, lychee fails the
-     PR-blocking `prek` check locally on first run.
-   - **`enableWeakerNetworkIsolation: true`.** Required for
-     native-TLS CLI tools (lychee, and the same mechanism the
-     schema notes for `gh` / `gcloud` / `terraform`) to verify TLS
-     through the sandbox's TLS-terminating proxy — without it lychee
-     fails every external link with `failed to verify TLS
-     certificate`. **Surface the documented trade-off when
-     reporting it**: the schema warns it "reduces security — opens a
-     potential data-exfiltration vector through the trustd service,"
-     so the user decides whether to enable it (the default ships it
-     on because the link check needs it). It is a no-op outside the
-     sandbox, e.g. in CI.
+   Two `sandbox.network.*` settings are worth a look while diffing
+   — but neither is a "missing default" to re-add:
+
+   - **`allowedDomains` is deliberately narrow.** The dogfooded
+     default allows `*.crates.io` and `static.rust-lang.org`, the
+     only hosts prek needs to bootstrap a rustup toolchain and
+     `cargo install` the `lychee` link-check hook on first run.
+     The wildcard link-target hosts that once sat beside them
+     (`*.apache.org`, `*.anthropic.com`, `*.claude.com`,
+     `*.mitre.org`, `*.nist.gov`, `*.github.io`, `gist.github.com`,
+     `astral.sh`, `json.schemastore.org`, `lychee.cli.rs`,
+     `sdkman.io`) were dropped when the hook went offline
+     (`offline = true` in `.lychee.toml`): lychee no longer fetches
+     the URLs the docs link to, so it never reaches them. A settings
+     file without those hosts is current, not stale — report their
+     *presence* as dead weight to drop, never their absence as
+     drift.
+   - **`enableWeakerNetworkIsolation: true`.** It is not there for
+     lychee, which runs offline. It lets native-TLS CLI tools verify
+     TLS through the sandbox's TLS-terminating proxy — the mechanism
+     the schema notes for `gh` / `gcloud` / `terraform`. **Surface
+     the documented trade-off when reporting it**: the schema warns
+     it "reduces security — opens a potential data-exfiltration
+     vector through the trustd service," so the user decides whether
+     to keep it. macOS-only, and a no-op outside the sandbox, e.g.
+     in CI.
 5. **comdev MCP checkouts (`ponymail`, `apache-projects`).** These
    ASF MCP servers are installed from a local `apache/comdev`
    checkout and are **tracked at `main`, not pinned** — unlike the
diff --git a/tools/sandbox-lint/tests/test_doc_domain_consistency.py b/tools/sandbox-lint/tests/test_doc_domain_consistency.py
new file mode 100644
index 00000000..afe3c5b9
--- /dev/null
+++ b/tools/sandbox-lint/tests/test_doc_domain_consistency.py
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""The update skill's `allowedDomains` prose must match the dogfooded settings.
+
+`setup-isolated-setup-update` tells the agent which sandbox domains are a
+current default and which were deliberately dropped. When
+`.claude/settings.json` moves and that prose does not, the skill reports the
+absence of a removed host as drift and walks adopters into re-adding dead
+allowlist entries. These tests read both sides and fail on that divergence.
+"""
+
+from __future__ import annotations
+
+import json
+import re
+from pathlib import Path
+
+REPO_ROOT = Path(__file__).resolve().parents[3]
+SETTINGS = REPO_ROOT / ".claude" / "settings.json"
+SKILL = REPO_ROOT / "plugins" / "magpie-setup" / "skills" / "isolated-setup-update" / "SKILL.md"
+
+# The two prose anchors the assertions parse. Rewording the bullet is fine;
+# keeping these phrases is what makes the claim machine-checkable.
+KEPT_RE = re.compile(r"default allows (.+?), the\s+only hosts", re.DOTALL)
+DROPPED_RE = re.compile(r"once sat beside them\s*\((.+?)\) were dropped", re.DOTALL)
+
+
+def _backticked(blob: str) -> set[str]:
+    return set(re.findall(r"`([^`]+)`", blob))
+
+
+def _settings_domains() -> set[str]:
+    settings = json.loads(SETTINGS.read_text())
+    return set(settings["sandbox"]["network"]["allowedDomains"])
+
+
+def _skill_text() -> str:
+    return SKILL.read_text()
+
+
+def test_kept_domains_are_actually_allowed() -> None:
+    match = KEPT_RE.search(_skill_text())
+    assert match, "the skill no longer states which domains the default allows"
+    kept = _backticked(match.group(1))
+    assert kept, "no domains parsed out of the 'default allows' sentence"
+    assert kept <= _settings_domains(), (
+        "the update skill names domains as the dogfooded default that "
+        f"{SETTINGS} does not allow: {sorted(kept - _settings_domains())}"
+    )
+
+
+def test_dropped_domains_are_not_allowed_again() -> None:
+    match = DROPPED_RE.search(_skill_text())
+    assert match, "the skill no longer lists the dropped link-target hosts"
+    dropped = _backticked(match.group(1))
+    assert dropped, "no domains parsed out of the dropped-hosts list"
+    readded = dropped & _settings_domains()
+    assert not readded, (
+        f"the update skill says these hosts were dropped, but {SETTINGS} allows them again: {sorted(readded)}"
+    )