From 8107c1849115c45921e82bd508567e92ce1b64d8 Mon Sep 17 00:00:00 2001 From: SIN-Agent Date: Sun, 26 Apr 2026 04:30:33 +0200 Subject: [PATCH 1/5] docs: document local workspace hygiene --- CONTRIBUTING.md | 9 +++++++++ README.md | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 693362cfc0..5437d200b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,12 +29,21 @@ bun ./scripts/dev-docs.mjs bun ./scripts/build-docs.mjs ``` +## Workspace hygiene + +Keep `OpenSIN-documentation/` scoped to this repo only. + +- Put companion repos, local clones, and worktrees in sibling directories such as `~/dev/`. +- Do **not** place side repos inside the docs repo root, even if they are temporary. +- Before opening a PR, verify the root stays clean with `git status --short`. + ## PR checklist - [ ] Claim is backed by evidence or a source link - [ ] Surface registry updated when needed - [ ] Links resolve and anchors still work - [ ] Build passes locally +- [ ] No nested local repos or worktrees were introduced into the repo root - [ ] llms files updated when docs map changes ## Review expectations diff --git a/README.md b/README.md index 8e98b3cc8d..91c76d67c1 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,10 @@ bun run dev bun ./scripts/build-docs.mjs ``` +> [!NOTE] +> Keep companion repos and local worktrees outside this repository root. +> Use sibling directories such as `~/dev/` so `OpenSIN-documentation/` stays clean during sync, checkout, and review. + ## šŸ“‚ Structure ```text From 2226897a76720ea085d0eadad2f24777c0c567c8 Mon Sep 17 00:00:00 2001 From: SIN-Agent Date: Sun, 26 Apr 2026 04:30:33 +0200 Subject: [PATCH 2/5] chore: add worktree hygiene PR check --- .github/pull_request_template.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 77ea5d3a8e..f8d15d1d2e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,3 +13,4 @@ - [ ] This PR keeps ownership scoped to docs canon - [ ] This PR does not overclaim implementation ownership - [ ] This PR does not replace org overview as registry layer +- [ ] This PR does not add nested local repos or worktrees under `OpenSIN-documentation/` From f2e8305c3b4133a3e6529b4e3dcc24827d5c5512 Mon Sep 17 00:00:00 2001 From: SIN-Agent Date: Sun, 26 Apr 2026 04:49:21 +0200 Subject: [PATCH 3/5] chore(ci): exclude nested git worktrees from scans --- .github/workflows/docs.yml | 11 +++++++++++ .github/workflows/repo-health-check.yml | 12 ++++++++++-- .github/workflows/repo-health.yml | 14 +++++++++++--- .gitignore | 8 ++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 99e771aff6..838c5b99b4 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,8 +17,16 @@ name: Docs Build & Deploy on: push: branches: [main, fix/docs-modernize-standards] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' pull_request: branches: [main] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' # ============================================================================= # Environment variables — Bun version pinned for reproducibility @@ -98,6 +106,9 @@ jobs: --include="*.sh" \ --exclude-dir=node_modules \ --exclude-dir=.git \ + --exclude-dir=worktrees \ + --exclude-dir=.worktrees \ + --exclude-dir='*.wt' \ --exclude-dir=.vitepress \ --exclude-dir=.github \ --exclude=AGENTS.md \ diff --git a/.github/workflows/repo-health-check.yml b/.github/workflows/repo-health-check.yml index 7cad7a2597..1b11f50f74 100644 --- a/.github/workflows/repo-health-check.yml +++ b/.github/workflows/repo-health-check.yml @@ -3,8 +3,16 @@ name: Repo Health Check on: push: branches: [main] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' pull_request: branches: [main] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' workflow_dispatch: inputs: scan_all_repos: @@ -96,9 +104,9 @@ jobs: echo "### Secret Detection" >> $GITHUB_STEP_SUMMARY SECRETS_FOUND=0 - # Scan for common secret patterns + # Scan for common secret patterns (worktree & .git excluded to prevent recursive descent and false positives) for pattern in "api_key\s*=\s*['\"][^'\"]*['\"]" "password\s*=\s*['\"][^'\"]*['\"]" "secret\s*=\s*['\"][^'\"]*['\"]" "token\s*=\s*sk-"; do - RESULTS=$(grep -rl --include="*.js" --include="*.ts" --include="*.py" --include="*.json" --include="*.env" -E "$pattern" . 2>/dev/null | grep -v node_modules | grep -v .git || true) + RESULTS=$(grep -rl --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=venv --exclude-dir=.opencode --exclude-dir=worktrees --exclude-dir=.worktrees --exclude-dir='*.wt' --include="*.js" --include="*.ts" --include="*.py" --include="*.json" --include="*.env" -E "$pattern" . 2>/dev/null || true) if [ -n "$RESULTS" ]; then echo "- šŸ”“ Potential secret found matching pattern: \`$pattern\`" >> $GITHUB_STEP_SUMMARY echo "$RESULTS" | while read -r f; do echo " - \`$f\`" >> $GITHUB_STEP_SUMMARY; done diff --git a/.github/workflows/repo-health.yml b/.github/workflows/repo-health.yml index 79850676bd..115097257e 100644 --- a/.github/workflows/repo-health.yml +++ b/.github/workflows/repo-health.yml @@ -3,8 +3,16 @@ name: Repo Health Check on: push: branches: [main] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' pull_request: branches: [main] + paths-ignore: + - 'worktrees/**' + - '.worktrees/**' + - '*.wt/**' jobs: health-check: @@ -40,10 +48,10 @@ jobs: - name: Check for banned package-lock.json run: | - LOCK_FILES=$(find . -name "package-lock.json" -not -path "*/node_modules/*" 2>/dev/null | wc -l) + LOCK_FILES=$(find . -name "package-lock.json" 2>/dev/null | grep -v '/node_modules/' | grep -v '/.git/' | grep -v '/worktrees/' | grep -v '/.worktrees/' | grep -v '\.wt/' | wc -l) if [ "$LOCK_FILES" -gt 0 ]; then echo "āŒ Found $LOCK_FILES package-lock.json files (npm is banned, use bun)" - find . -name "package-lock.json" -not -path "*/node_modules/*" + find . -name "package-lock.json" 2>/dev/null | grep -v '/node_modules/' | grep -v '/.git/' | grep -v '/worktrees/' | grep -v '/.worktrees/' | grep -v '\.wt/' exit 1 fi echo "āœ… No package-lock.json files found (bun mandate compliance)" @@ -80,7 +88,7 @@ jobs: - name: Check for package-lock.json after install run: | - if [ -f "package-lock.json" ]; then + if find . -name "package-lock.json" 2>/dev/null | grep -v '/node_modules/' | grep -v '/.git/' | grep -v '/worktrees/' | grep -v '/.worktrees/' | grep -v '\.wt/' | grep -q .; then echo "āŒ package-lock.json was created! Remove it and use only bun.lockb" exit 1 fi diff --git a/.gitignore b/.gitignore index 8039ac74b8..00ee0ee796 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,11 @@ pool-chrome-profiles/ rotator-temp/ source-of-truth/ website-member.opensin.ai/ + +# Worktree & nested git isolation (prevents recursive scans, secret false positives & watcher loops) +/worktrees/ +/.worktrees/ +*.wt/ +.git/worktrees/ +**/.git/ +**/.git From 796aade8d3546512f5d90b6429af45f5983a3da9 Mon Sep 17 00:00:00 2001 From: SIN-Agent Date: Sun, 26 Apr 2026 04:49:21 +0200 Subject: [PATCH 4/5] feat(build): enforce worktree hygiene before docs builds --- package.json | 2 ++ scripts/build-docs.mjs | 2 ++ scripts/worktree-hygiene.mjs | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 scripts/worktree-hygiene.mjs diff --git a/package.json b/package.json index a5ff1e2491..75d8b64d75 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ }, "packageManager": "bun@latest", "scripts": { + "predev": "bun ./scripts/worktree-hygiene.mjs", + "prebuild": "bun ./scripts/worktree-hygiene.mjs", "dev": "vitepress dev docs", "build": "bun ./scripts/build-docs.mjs", "preview": "vitepress preview docs" diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs index ec5146d2df..cd7db6ddf2 100755 --- a/scripts/build-docs.mjs +++ b/scripts/build-docs.mjs @@ -1,4 +1,6 @@ #!/usr/bin/env bun import { build } from 'vitepress'; +import { runWorktreeHygiene } from './worktree-hygiene.mjs'; +await runWorktreeHygiene(); await build('docs'); diff --git a/scripts/worktree-hygiene.mjs b/scripts/worktree-hygiene.mjs new file mode 100644 index 0000000000..b7868f605e --- /dev/null +++ b/scripts/worktree-hygiene.mjs @@ -0,0 +1,54 @@ +#!/usr/bin/env bun +import { readdirSync } from 'node:fs'; +import { join, relative } from 'node:path'; + +const ROOT = process.cwd(); +const IGNORED = new Set(['node_modules', '.git', 'dist', '.vitepress', 'venv', '.opencode']); + +function scan(dir, depth = 0) { + if (depth > 3) return []; + + const hits = []; + let entries; + + try { + entries = readdirSync(dir, { withFileTypes: true }); + } catch { + return hits; + } + + for (const entry of entries) { + const full = join(dir, entry.name); + + if (entry.name === '.git') { + if (dir !== ROOT) hits.push(full); + continue; + } + + if (IGNORED.has(entry.name)) continue; + + if (entry.isDirectory()) { + hits.push(...scan(full, depth + 1)); + } + } + + return hits; +} + +export function runWorktreeHygiene() { + const nested = scan(ROOT); + + if (nested.length > 0) { + console.error('āŒ Worktree/nested .git detected inside repository root:'); + nested.forEach((path) => console.error(` - ${relative(ROOT, path)}`)); + console.error('\nāš ļø Worktrees must reside outside the repository root to prevent recursive scans, secret detector false positives, and VitePress watcher loops.'); + console.error('šŸ‘‰ Move worktrees to a sibling directory (e.g., ../OpenSIN-worktrees/) or run: git worktree prune'); + process.exit(1); + } + + console.log('āœ… Worktree hygiene check passed. No nested .git artifacts found.'); +} + +if (import.meta.main) { + runWorktreeHygiene(); +} From 0e093cdd1d8318b090169129681bf3e4daf4cc88 Mon Sep 17 00:00:00 2001 From: SIN-Agent Date: Sun, 26 Apr 2026 04:49:22 +0200 Subject: [PATCH 5/5] chore(vitepress): ignore nested worktree paths --- docs/.vitepress/config.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 9ed0ce7f0a..55e5ddef23 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -5,6 +5,13 @@ export default defineConfig({ description: 'Guides and concepts for the OpenSIN API.', lang: 'en-US', ignoreDeadLinks: true, + vite: { + server: { + watch: { + ignored: ['**/.git/**', '**/.worktrees/**', '**/worktrees/**', '**/*.wt/**', '**/node_modules/**', '**/.opencode/**', '**/venv/**'], + }, + }, + }, head: [ ['link', { rel: 'icon', href: '/logo.png' }], ['link', { rel: 'canonical', href: 'https://docs.opensin.ai/' }],