mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 08:36:25 +00:00
The quick start walked a new user into gh repo fork - forks of public repos are always public - and two steps later had /setup write personal data into tracked files, with the only complete warning in SETUP.md section 8, a section about pulling updates that a first-time user has no reason to open during onboarding. A real user hit exactly this (#345). The warning now sits adjacent to both fork commands (README step 1, SETUP.md section 2, both pointing at section 8's private-remote recipe), and /setup checks the origin's visibility BEFORE writing anything: a public-fork origin gets a confirm-first warning instead of a note after every file is on disk. A private origin, no origin, or a non-git directory continues silently. Reported by @basilevs with a complete reproduction and fix analysis; this implements his fixes (1) and (4). Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
86 lines
3.4 KiB
Python
86 lines
3.4 KiB
Python
"""Guards for the onboarding privacy warnings (issue #345).
|
|
|
|
The README's quick start walks a new user into creating a public fork
|
|
(forks of public repos cannot be private) and then has /setup write
|
|
personal data into tracked files, with the only complete warning sitting
|
|
in SETUP.md section 8 - a section about pulling updates, downstream of
|
|
the decision it should inform. A real user hit exactly this. These tests
|
|
pin that the warning lives at the point of decision (adjacent to both
|
|
fork commands) and that /setup checks the origin's visibility BEFORE
|
|
writing anything, not in its closing notes.
|
|
"""
|
|
import re
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parent.parent
|
|
README = REPO / "README.md"
|
|
SETUP_GUIDE = REPO / "SETUP.md"
|
|
SETUP_COMMAND = REPO / ".claude" / "commands" / "setup.md"
|
|
|
|
|
|
def section(text: str, heading: str) -> str:
|
|
"""Body of a markdown section up to the next heading of the same level."""
|
|
level = heading.split(" ")[0]
|
|
pattern = re.compile(
|
|
rf"^{re.escape(heading)}\n(.*?)(?=^{level} |\Z)", re.MULTILINE | re.DOTALL
|
|
)
|
|
match = pattern.search(text)
|
|
return match.group(1) if match else ""
|
|
|
|
|
|
class TestForkWarningsAtTheDecisionPoint(unittest.TestCase):
|
|
def assert_warns(self, body: str, where: str):
|
|
self.assertRegex(
|
|
body,
|
|
re.compile(r"public", re.IGNORECASE),
|
|
f"{where}'s fork section must say the fork will be public",
|
|
)
|
|
self.assertIn(
|
|
"personal data",
|
|
body,
|
|
f"{where}'s fork section must say /setup writes personal data into tracked files",
|
|
)
|
|
self.assertRegex(
|
|
body,
|
|
re.compile(r"section 8|§8|#8-pulling", re.IGNORECASE),
|
|
f"{where}'s fork section must point at SETUP.md section 8's private-remote recipe",
|
|
)
|
|
|
|
def test_readme_quick_start_warns_next_to_the_fork_command(self):
|
|
body = section(README.read_text(encoding="utf-8"), "### 1. Fork and clone")
|
|
self.assertIn("gh repo fork", body, "sanity: the fork command lives in this section")
|
|
self.assert_warns(body, "README")
|
|
|
|
def test_setup_guide_warns_next_to_the_fork_command(self):
|
|
body = section(SETUP_GUIDE.read_text(encoding="utf-8"), "## 2. Fork and clone")
|
|
self.assertIn("gh repo fork", body, "sanity: the fork command lives in this section")
|
|
self.assert_warns(body, "SETUP.md")
|
|
|
|
|
|
class TestSetupChecksOriginBeforeWriting(unittest.TestCase):
|
|
def test_preflight_exists_and_precedes_profile_generation(self):
|
|
text = SETUP_COMMAND.read_text(encoding="utf-8")
|
|
self.assertIn(
|
|
"git remote get-url origin",
|
|
text,
|
|
"/setup must check where the working copy would publish to",
|
|
)
|
|
preflight_at = text.index("git remote get-url origin")
|
|
writes_at = text.index("## Step 3: Generate Profile Files")
|
|
self.assertLess(
|
|
preflight_at,
|
|
writes_at,
|
|
"the origin check must run before any profile file is written - the "
|
|
"existing Step 4 note fires after everything is already on disk",
|
|
)
|
|
self.assertIn(
|
|
"public",
|
|
text[max(0, preflight_at - 2000) : preflight_at + 2000].lower(),
|
|
"the preflight must be about public visibility, not just remote presence",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|