wiki: auto-compile 2026-05-15 (1 log(s), 254 articles)
This commit is contained in:
parent
7c2d50931e
commit
a34ce64f00
16 changed files with 648 additions and 2 deletions
|
|
@ -10,3 +10,7 @@ tags: [daily]
|
|||
- 10:10 (<1min) — session ended | `memory-compiler`
|
||||
- 10:11 — session ended | `memory-compiler`
|
||||
- 10:12 (<1min) — session ended | `memory-compiler`
|
||||
- 10:14 (<1min) — session ended | `memory-compiler`
|
||||
- 10:14 (<1min) — session ended | `memory-compiler`
|
||||
- 10:15 (<1min) — session ended | `memory-compiler`
|
||||
- 10:15 (<1min) — session ended | `memory-compiler`
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ This 3-hop pattern works for hundreds of articles without vector search.
|
|||
| [[wiki/tech-patterns/_index\|tech-patterns/]] | Recurring tech stacks: FastAPI, React/Vite, Next.js, Azure AD, AI, Box, One2Edit, Redis/Celery, cost-tracker, OMG API | 29 |
|
||||
| [[wiki/architecture/_index\|architecture/]] | Cross-cutting architectural patterns: Docker Compose, multi-agent AI, GCP timeout, RAG, hotfolder, optical-dev deploy, cost-tracker, new-project checklist, troubleshooting playbooks, ADR log, Cloud Run Jobs | 11 |
|
||||
| [[wiki/client-knowledge/_index\|client-knowledge/]] | Per-client notes for Ford, H&M, L'Oréal, Barclays, Ferrero, 3M, BAIC | 7 |
|
||||
| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 196 |
|
||||
| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 197 |
|
||||
| [[wiki/connections/_index\|connections/]] | Cross-cutting insights linking 2+ concepts: FastAPI+Azure AD+Docker trinity, AI→cost-tracker, Apache+Vite basePath, GCP→REST polling, Box+hotfolder, Docker DNS+AdGuard, Celery prefork×faster_whisper memory stacking | 10 |
|
||||
| [[wiki/qa/_index\|qa/]] | Filed answers to queries (saved with `--file-back`) | 0 |
|
||||
| [[wiki/homelab/_index\|homelab/]] | Self-hosted infra: Proxmox install, IOMMU/PCI passthrough, hypervisor setup, budget builds, HP Elitedesk G3, Homarr API + Apps + Boards + Certificates + Integrations + Settings + Tasks + AdGuard + Clock + Docker Stats + Docker Integration + Download Client + Firewall + Proxmox Integration + Radarr + Readarr + Sonarr + Bookmarks + Calendar + Icons + App Widget + Weather + GitHub + Nextcloud + qBittorrent + RSS Feed + Speedtest Tracker + System Health Monitoring + System Resources + Services Map + Media Stack | 43 |
|
||||
|
|
@ -31,7 +31,7 @@ This 3-hop pattern works for hundreds of articles without vector search.
|
|||
| [[wiki/dotfiles/_index\|dotfiles/]] | Linux terminal ricing: Kitty, Fish, WezTerm CLI, modern Rust CLI tools, LazyVim, unified themes, Tabby, Aerospace WM | 22 |
|
||||
| [[wiki/agent-sdk/_index\|agent-sdk/]] | Claude Agent SDK (formerly Claude Code SDK) — build autonomous AI agents in Python and TypeScript | 30 |
|
||||
| [[wiki/llm-models/_index\|llm-models/]] | LLM model catalogs — OpenAI, Claude/Anthropic, and Google Gemini models, IDs, context, pricing | 3 |
|
||||
| [[wiki/claude-code/_index\|claude-code/]] | Claude Code product docs — install, capabilities, surfaces, MCP, hooks, scheduling, multi-agent, plugins, skills, channels, error recovery, LM Studio local, Figma MCP | 33 |
|
||||
| [[wiki/claude-code/_index\|claude-code/]] | Claude Code product docs — install, capabilities, surfaces, MCP, hooks, scheduling, multi-agent, plugins, skills, channels, error recovery, LM Studio local, Figma MCP, global rules, local config | 36 |
|
||||
| [[wiki/reports/_index\|reports/]] | Weekly and monthly summaries — generate: `uv run python scripts/report-generator.py --weekly` | 1 |
|
||||
| [[wiki/infrastructure/_index\|infrastructure/]] | Server inventory: all 10 SSH hosts — optical, optical-dev, optical-prod, baic, librechat, modocmms, box-cli, aimpress, pve | 11 |
|
||||
|
||||
|
|
|
|||
|
|
@ -47,3 +47,6 @@ Claude Code is Anthropic's agentic coding assistant. Works across terminal, IDE,
|
|||
| [[wiki/claude-code/claude-skills-guide\|claude-skills-guide]] | Complete guide to building Claude Skills: SKILL.md structure, YAML frontmatter, progressive disclosure, MCP integration, testing, distribution, 5 workflow patterns | raw/file_EE003DA9-270B-4159-A329-C89962F85415.pdf | 2026-05-06 |
|
||||
| [[wiki/claude-code/figma-mcp-custom-rules\|figma-mcp-custom-rules]] | Project-level CLAUDE.md rules for Figma MCP: required tool flow (get_design_context → get_screenshot → implement → validate), asset rules, auto-generate rules prompt | raw/Add custom rules and instructions.md | 2026-05-15 |
|
||||
| [[wiki/claude-code/figma-mcp-avoid-large-frames\|figma-mcp-avoid-large-frames]] | Select components/chunks, not full screens — large selections slow tools, cause errors, or truncate output; how to debug output quality | raw/Avoid selecting large, heavy frames.md | 2026-05-15 |
|
||||
| [[wiki/claude-code/global-rules-claude-md\|global-rules-claude-md]] | Global CLAUDE.md rules: core principles, workflow (plan-first, subagents, verify), escalation, change limits, skills/MCP routing, git, code reuse, secrets, server ops | raw/Claude Code Global Rules (CLAUDE.md).md | 2026-05-15 |
|
||||
| [[wiki/claude-code/local-machine-config\|local-machine-config]] | CLAUDE.local.md: Obsidian vault path + folder structure, Mailgun domain gotcha (mg.oliver.solutions), Oliver VPN Tunnelblick check snippet | raw/Claude Code Local Config (CLAUDE.local.md).md | 2026-05-15 |
|
||||
| [[wiki/claude-code/figma-mcp-setup\|figma-mcp-setup]] | Figma MCP server setup in Claude Code: remote (plugin install) vs desktop (Dev Mode + local URL); auth flow, what tools are unlocked | raw/Claude Code and Figma Set up the MCP server.md | 2026-05-15 |
|
||||
|
|
|
|||
76
wiki/claude-code/figma-mcp-setup.md
Normal file
76
wiki/claude-code/figma-mcp-setup.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
title: "Figma MCP Server — Setup in Claude Code"
|
||||
aliases: [figma-mcp-setup, figma-claude-code-setup]
|
||||
tags: [figma, mcp, claude-code, setup, design]
|
||||
sources: [raw/Claude Code and Figma Set up the MCP server.md]
|
||||
created: 2026-05-15
|
||||
updated: 2026-05-15
|
||||
---
|
||||
|
||||
# Figma MCP Server — Setup in Claude Code
|
||||
|
||||
Gives Claude Code structured access to Figma: read components/variables/layout, generate code from frames, use Code Connect, and write native content back to the canvas.
|
||||
|
||||
## Two Versions
|
||||
|
||||
| Version | When to use |
|
||||
|---------|-------------|
|
||||
| **Remote** (recommended) | Most users — broadest feature set |
|
||||
| **Desktop** | Specific org/enterprise use cases only |
|
||||
|
||||
## Remote Setup (Preferred)
|
||||
|
||||
Install the Figma plugin (includes MCP server + Agent Skills):
|
||||
|
||||
```bash
|
||||
claude plugin install figma@claude-plugins-official
|
||||
```
|
||||
|
||||
Then:
|
||||
1. Restart Claude Code
|
||||
2. Run `/plugin` → navigate to **Installed** tab
|
||||
3. Select `figma` → press Enter → authenticate via browser
|
||||
4. Click **Allow access**
|
||||
5. Run `/plugin` again — `figma` should show as **connected**
|
||||
|
||||
## Desktop Setup
|
||||
|
||||
Only if remote is unavailable (org/enterprise).
|
||||
|
||||
**In Figma desktop app:**
|
||||
1. Open a Design file → switch to Dev Mode (toolbar toggle)
|
||||
2. Enable MCP server in right sidebar → copy the URL
|
||||
|
||||
**In Claude Code terminal:**
|
||||
```bash
|
||||
claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp
|
||||
```
|
||||
Restart Claude Code, then verify with `/mcp`.
|
||||
|
||||
## What the MCP Server Provides
|
||||
|
||||
- Read: components, variables, layout data, FigJam content, Make resources
|
||||
- Generate code from selected frames
|
||||
- Code Connect — keeps generated code aligned with real components
|
||||
- Write to canvas — create/update native Figma content
|
||||
- Send live web interfaces to Figma as editable layers
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- Use the **remote** version unless you have an explicit org/enterprise reason for desktop
|
||||
- Install via `claude plugin install figma@claude-plugins-official` — this is the recommended path
|
||||
- After install, authenticate once via browser OAuth; stays connected across sessions
|
||||
- Desktop version requires Figma desktop app + Dev Mode + manually copying the local URL
|
||||
- After setup, test with `/mcp` (desktop) or `/plugin` (remote) to confirm connection
|
||||
|
||||
## Related Articles
|
||||
|
||||
- [[wiki/claude-code/mcp-integration|MCP Integration in Claude Code]]
|
||||
- [[wiki/claude-code/figma-mcp-custom-rules|Figma MCP Custom Rules (CLAUDE.md)]]
|
||||
- [[wiki/claude-code/figma-mcp-avoid-large-frames|Avoid Selecting Large Figma Frames]]
|
||||
- [[wiki/claude-code/plugin-marketplaces|Plugin Marketplaces]]
|
||||
|
||||
## Sources
|
||||
|
||||
- `raw/Claude Code and Figma Set up the MCP server.md`
|
||||
- Official: https://help.figma.com/hc/en-us/articles/39888612464151
|
||||
253
wiki/claude-code/global-rules-claude-md.md
Normal file
253
wiki/claude-code/global-rules-claude-md.md
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
---
|
||||
title: "Global Claude Code Rules (CLAUDE.md)"
|
||||
aliases: [claude-md-rules, global-rules, claude-global-config]
|
||||
tags: [claude-code, configuration, workflow, rules, skills, mcp]
|
||||
sources: [raw/Claude Code Global Rules (CLAUDE.md).md]
|
||||
created: 2026-05-15
|
||||
updated: 2026-05-15
|
||||
---
|
||||
|
||||
# Global Claude Code Rules (CLAUDE.md)
|
||||
|
||||
The global `CLAUDE.md` file sets the operating contract for Claude Code across all projects. It enforces engineering discipline, context hygiene, and consistent conventions.
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
- **Simplicity first** — minimum code that solves the task; no speculative abstractions.
|
||||
- **No laziness** — fix root cause, not symptoms; senior-dev standard.
|
||||
- **Minimal blast radius** — change only what's necessary; smaller diff = fewer regressions.
|
||||
|
||||
---
|
||||
|
||||
## Workflow Rules
|
||||
|
||||
| Rule | Detail |
|
||||
|------|--------|
|
||||
| **Plan-first** | 3+ steps or architecture → plan mode. Exceptions: typos, renames, one-liners. |
|
||||
| **Subagents over main context** | Research/exploration/parallel analysis → Agent tool. Non-trivial impl → `isolation: "worktree"`. |
|
||||
| **Verify before done** | Backend: `pytest` + type check. Frontend: `npm run build` + lint. DB: `alembic upgrade head` + rollback. Docker: build + up + healthcheck. |
|
||||
| **Demand elegance** | Pause before finalizing: "is there a more elegant solution?" Skip for hotfixes/one-liners/config changes. |
|
||||
| **Autonomous bug fixing** | Log/failed test → read trace, fix, re-run immediately. Never ask "how to fix." |
|
||||
| **Explain non-trivial changes** | 1–3 lines high-level after any non-trivial edit. |
|
||||
|
||||
---
|
||||
|
||||
## Escalation Thresholds
|
||||
|
||||
- **3 failed fix attempts** → STOP, show what was tried, ask for direction.
|
||||
- **Breaking change** (public API / schema migration / breaking rename) → confirm before applying.
|
||||
- **Uncertain root cause** → show 2–3 hypotheses, ask.
|
||||
|
||||
---
|
||||
|
||||
## Change Limits
|
||||
|
||||
- **>5 files or >200 lines diff** → pause, show plan, confirm.
|
||||
- **Unrequested refactoring** → don't do it; offer as a separate task.
|
||||
|
||||
---
|
||||
|
||||
## Token Discipline
|
||||
|
||||
- **20+ messages OR noticeable slowdown** → suggest `/compact`.
|
||||
- **Topic switch** (different project/feature) → new session, not `/compact`.
|
||||
- **Subagent returned >2000 words** → summarize to 200 words before inserting into context.
|
||||
|
||||
---
|
||||
|
||||
## Self-Improvement Loop
|
||||
|
||||
```
|
||||
PreCompact/SessionEnd hooks → flush.py → daily/YYYY-MM-DD.md
|
||||
→ compile.py (21:00) → wiki/concepts/ in Obsidian
|
||||
→ SessionStart injects back
|
||||
```
|
||||
|
||||
**Guaranteed lesson persistence** — write in final reply:
|
||||
```
|
||||
Lesson: <rule>
|
||||
Reason: <reason>
|
||||
Scope: global | project:<name> | skill:<name> | shared:<pattern>
|
||||
```
|
||||
`compile.py` routes `Scope: shared:*` → `wiki/shared-patterns/`.
|
||||
|
||||
- **Session tasks:** `TaskCreate` / `TodoWrite`. Never create `tasks/todo.md`.
|
||||
- **Session logs** are written by Stop/SessionEnd hooks — don't duplicate manually.
|
||||
|
||||
---
|
||||
|
||||
## Language Policy
|
||||
|
||||
- Respond to user in **Russian**.
|
||||
- Code, comments, file names, commits, variables, docs — strictly **English**.
|
||||
|
||||
---
|
||||
|
||||
## Don'ts
|
||||
|
||||
- No `try/except` without specific error handling.
|
||||
- No files created "for the future" (empty modules, placeholder configs).
|
||||
- No formatting/style changes in files unrelated to the task.
|
||||
- No logic duplication — find existing util/helper first.
|
||||
- Never say "I can't" — find a workaround, then report the limitation.
|
||||
|
||||
---
|
||||
|
||||
## Skills Routing
|
||||
|
||||
### Always Active (Obsidian)
|
||||
|
||||
| Skill | When |
|
||||
|-------|------|
|
||||
| `obsidian:defuddle` | Instead of WebFetch for any URL (articles, docs). Skip: `.md` URLs, raw APIs. |
|
||||
| `obsidian:obsidian-markdown` | Creating/editing `.md` in Obsidian vault. |
|
||||
| `obsidian:obsidian-cli` | Reading/writing/searching vault notes via CLI. |
|
||||
| `obsidian:obsidian-bases` | `.base` files (database views). |
|
||||
| `obsidian:json-canvas` | `.canvas` files. |
|
||||
|
||||
### By Trigger
|
||||
|
||||
| Trigger | Skill |
|
||||
|---------|-------|
|
||||
| `.py`, script, module | `fullstack-dev-skills:python-pro` |
|
||||
| FastAPI routes, Pydantic | `fullstack-dev-skills:fastapi-expert` |
|
||||
| Auth, JWT, Azure AD, OWASP | `fullstack-dev-skills:security-reviewer` |
|
||||
| React, `.tsx`, Vite | `fullstack-dev-skills:react-expert` |
|
||||
| TypeScript types, generics | `fullstack-dev-skills:typescript-pro` |
|
||||
| UI/UX decisions, layout, design | `frontend-design:frontend-design` |
|
||||
| Dockerfile, docker-compose, GCP, nginx | `fullstack-dev-skills:devops-engineer` |
|
||||
| SQL, schema, migrations, PostgreSQL | `fullstack-dev-skills:postgres-pro` |
|
||||
| Tests, mocking | `fullstack-dev-skills:test-master` |
|
||||
| E2E, Playwright | `fullstack-dev-skills:playwright-expert` |
|
||||
| RAG, vector DB, embeddings | `fullstack-dev-skills:rag-architect` |
|
||||
| Prompt design, Claude/OpenAI API | `fullstack-dev-skills:prompt-engineer` |
|
||||
| Full docs from scratch | `documentation-pipeline:ln-100-documents-pipeline` |
|
||||
| Code review (file/diff) | `fullstack-dev-skills:code-reviewer` |
|
||||
| PR review | `pr-review-toolkit:review-pr` |
|
||||
| Stack trace, root cause | `fullstack-dev-skills:debugging-wizard` |
|
||||
|
||||
**Conflict resolution:** multiple skill match → primary = main action; secondary = consult only.
|
||||
|
||||
---
|
||||
|
||||
## MCP Routing
|
||||
|
||||
| MCP | When |
|
||||
|-----|------|
|
||||
| `context7` | Docs for FastAPI, Next.js, React, etc. |
|
||||
| `basic-memory` | Save solution mid-session / recall past-session context |
|
||||
| `postgres` | Direct SQL queries to project DB without writing scripts |
|
||||
| `redis` | Redis operations (cc-dashboard, ai-cost-tracker, video-accessibility) |
|
||||
| `sequential-thinking` | Complex multi-step architectural tasks |
|
||||
|
||||
Built into harness (no config needed): Playwright, Figma MCP, Magic.
|
||||
|
||||
---
|
||||
|
||||
## Second Brain — Obsidian Vault
|
||||
|
||||
**Before asking user — search vault first.**
|
||||
|
||||
**Lookup order:**
|
||||
1. Session-start context → do NOT re-read (already in window).
|
||||
2. `Read 01 Projects/<project>/*.md` → only if task is project-specific.
|
||||
3. `Read wiki/_master-index.md` → only if pattern/architecture needed.
|
||||
4. Ask user → last resort if info truly absent.
|
||||
|
||||
---
|
||||
|
||||
## Git Rules
|
||||
|
||||
- **Commit format:** `type(scope): description` (conventional commits)
|
||||
- **Types:** `feat`, `fix`, `refactor`, `docs`, `chore`, `test`
|
||||
- **Branch naming:** `feature/<short-desc>`, `fix/<short-desc>`
|
||||
- **Atomic commits:** one concern = one commit
|
||||
- **Worktrees:** multiple branches + new task → offer worktree; Agent for non-trivial impl → `isolation: "worktree"`
|
||||
- **Agent conflicts:** two agents must NOT edit the same file; if unavoidable — sequential, not parallel
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Policy
|
||||
|
||||
- New package → check: existing analogue in project; size; license; last commit.
|
||||
- Prefer stdlib / already-installed packages.
|
||||
- Adding dependency → explicitly notify user.
|
||||
|
||||
---
|
||||
|
||||
## Secrets Policy
|
||||
|
||||
- **NEVER** hardcode secrets in code, commits, logs.
|
||||
- Before commit → check diff for keys/passwords/tokens.
|
||||
- `.env` files → always in `.gitignore`. Create `.env.example` with placeholders.
|
||||
- Found leaked secret → immediately notify user.
|
||||
|
||||
---
|
||||
|
||||
## Server Operations
|
||||
|
||||
- **NEVER** run commands on remote servers without explicit user instruction.
|
||||
- **NEVER** destructive commands (`rm -rf`, `DROP TABLE`, `TRUNCATE`, `git push --force`) without explicit confirm.
|
||||
- **Production DB** → `SELECT` only. Any write → confirm + remind about backup.
|
||||
|
||||
---
|
||||
|
||||
## Code Reuse
|
||||
|
||||
### Search Before Write
|
||||
|
||||
1. Search current project → `grep`/`rg` by functionality.
|
||||
2. Search vault `wiki/shared-patterns/` → already-solved patterns.
|
||||
3. Search shared-libs → ready package.
|
||||
4. Search neighboring projects (subagent) → similar implementation.
|
||||
5. Only if 1–4 empty → write from scratch.
|
||||
|
||||
### Standard Library Choices
|
||||
|
||||
| Task | Standard | Avoid |
|
||||
|------|----------|-------|
|
||||
| HTTP client (Python) | `httpx` | requests, aiohttp |
|
||||
| HTTP client (TS) | `fetch` / `ky` | axios |
|
||||
| Validation (Python) | `pydantic` | marshmallow, attrs |
|
||||
| Date handling (TS) | `date-fns` | moment, dayjs |
|
||||
| Env config (Python) | `pydantic-settings` | python-dotenv directly |
|
||||
| Logging (Python) | `structlog` | print, stdlib logging |
|
||||
| Task queue | `celery` / `arq` | custom implementations |
|
||||
| DB migrations | `alembic` (Python) | raw SQL scripts |
|
||||
|
||||
### Anti-Duplication
|
||||
|
||||
- Copy-paste spotted inside project → offer extract (don't do silently).
|
||||
- Pattern repeated in 3+ projects → flag: "worth moving to shared".
|
||||
- Never sync copies manually — divergence = signal to extract shared package.
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- All Claude Code sessions operate under these rules globally via `~/.claude/CLAUDE.md`.
|
||||
- Plan mode is mandatory for 3+ step tasks; subagents protect main context.
|
||||
- Verification is non-negotiable before marking work done.
|
||||
- Skills are invoked by trigger (file type, task type) — always before starting work.
|
||||
- Git uses conventional commits + atomic changes; worktrees for parallel agent work.
|
||||
- Code reuse: search 4 places before writing from scratch; standard library table is authoritative.
|
||||
- Session self-improvement loop: hooks → flush.py → compile.py → Obsidian wiki → re-injected next session.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [[wiki/claude-code/dot-claude-folder|dot-claude-folder]] — `.claude/` folder structure (CLAUDE.md location, hooks, skills, agents)
|
||||
- [[wiki/claude-code/skills|skills]] — Skills system: creation, storage scopes, invocation
|
||||
- [[wiki/claude-code/custom-subagents|custom-subagents]] — Subagent patterns referenced in workflow rules
|
||||
- [[wiki/claude-code/oliver-skills-config|oliver-skills-config]] — Oliver Agency skills selection rationale
|
||||
- [[wiki/claude-code/scheduled-tasks|scheduled-tasks]] — `/loop`, `CronCreate` tools for session scheduling
|
||||
- [[wiki/architecture/new-project-checklist|new-project-checklist]] — New project stub note procedure
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- `raw/Claude Code Global Rules (CLAUDE.md).md`
|
||||
70
wiki/claude-code/local-machine-config.md
Normal file
70
wiki/claude-code/local-machine-config.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: "Claude Code Local Machine Config (CLAUDE.local.md)"
|
||||
aliases: [claude-local-config, claude-local-md, local-config]
|
||||
tags: [claude-code, config, obsidian, mailgun, vpn, oliver]
|
||||
sources: [raw/Claude Code Local Config (CLAUDE.local.md).md]
|
||||
created: 2026-05-15
|
||||
updated: 2026-05-15
|
||||
---
|
||||
|
||||
# Claude Code Local Machine Config (CLAUDE.local.md)
|
||||
|
||||
Local overrides for the global [[wiki/claude-code/global-rules-claude-md|CLAUDE.md]] — machine-specific paths, credentials, and infrastructure details that must not be committed.
|
||||
|
||||
---
|
||||
|
||||
## Obsidian Vault
|
||||
|
||||
**Path:** `~/Library/Mobile Documents/iCloud~md~obsidian/Documents/VadymSamoilenko/`
|
||||
|
||||
| Folder | Contents |
|
||||
|--------|----------|
|
||||
| `01 Projects/<name>/` | Tech stack, server, deploy command, URL, session notes |
|
||||
| `wiki/` | Knowledge base: tech patterns, architecture, concepts |
|
||||
| `02 Areas/` | Pending commands, homelab config |
|
||||
| `99 Daily/` | Session logs |
|
||||
|
||||
See [[wiki/obsidian-rag/_index|obsidian-rag/]] for how Claude Code navigates the vault.
|
||||
|
||||
---
|
||||
|
||||
## Email — Mailgun
|
||||
|
||||
- **Credentials:** `source ~/.secrets/mailgun.env`
|
||||
- **Base URL:** `https://api.mailgun.net/v3`
|
||||
- Always add to `.env` / `.env.example` automatically; `.env` always in `.gitignore`
|
||||
|
||||
> **Gotcha:** domain must be `mg.oliver.solutions`, **not** `oliver.solutions`.
|
||||
> Wrong domain → Mailgun returns 404/401 → Python wrapper silently returns `False` → generic 500 error upstream.
|
||||
|
||||
---
|
||||
|
||||
## Oliver VPN
|
||||
|
||||
Must be connected before any SSH or deploy to Oliver servers:
|
||||
- `optical-dev`, `optical-web-1`, `baic`, `box-cli`, `10.220.168.*`
|
||||
|
||||
**Check + auto-connect (Tunnelblick):**
|
||||
|
||||
```bash
|
||||
VPN_STATE=$(osascript -e 'tell application "Tunnelblick" to get state of first configuration where name contains "Oliver"' 2>/dev/null)
|
||||
[ "$VPN_STATE" != "CONNECTED" ] && osascript -e 'tell application "Tunnelblick" to connect "Oliver VPN"' && sleep 5
|
||||
```
|
||||
|
||||
Run this before any SSH/deploy command targeting Oliver infrastructure. See [[wiki/infrastructure/_index|infrastructure/]] for the full server inventory.
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- `CLAUDE.local.md` holds machine-specific config that overrides global `CLAUDE.md` — never commit it
|
||||
- Obsidian vault lives in iCloud at a known path; folder structure is: Projects / wiki / Areas / Daily
|
||||
- Mailgun domain must be `mg.oliver.solutions` — wrong domain causes silent 404/401 → 500
|
||||
- Always check Oliver VPN (Tunnelblick) before SSH/deploy to any Oliver server
|
||||
- The osascript snippet auto-connects Tunnelblick if not already connected
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- `raw/Claude Code Local Config (CLAUDE.local.md).md`
|
||||
|
|
@ -57,6 +57,9 @@ ssh baic "sudo systemctl status baic_dashboard.service"
|
|||
| SSE needs `?token=` | `EventSource` can't set custom headers | [[wiki/concepts/sse-jwt-query-param]] |
|
||||
| SPA index.html must be no-cache | Old hashes cause blank screen after rebuild | [[wiki/concepts/spa-index-html-cache-control]] |
|
||||
| MS SSO IDs are not UUIDs | `ms-4n0T2x-...` format breaks UUID validators | [[wiki/concepts/microsoft-sso-non-uuid-ids]] |
|
||||
| Mailgun sending domain | Must use `mg.oliver.solutions`, NOT `oliver.solutions` — wrong subdomain causes silent failure (wrapper returns `False`, endpoint returns 500) | [[wiki/concepts/mailgun-sending-domain-oliver]] |
|
||||
| FastAPI lifespan service access | Services initialised in `lifespan()` must be accessed via `request.app.state.service_name`, not imported from `app.main` | [[wiki/concepts/fastapi-lifespan-locals-app-state]] |
|
||||
| Multi-layer rename (agent/role) | Renaming any AI agent or modcomms role requires simultaneous update: frontend label + TS union type + Python class attr + backend dict key + DB seed row | — |
|
||||
|
||||
## Features
|
||||
|
||||
|
|
|
|||
|
|
@ -241,5 +241,9 @@
|
|||
| [[wiki/concepts/docker-compose-force-recreate]] | `docker compose up -d` after build keeps old container running — `--force-recreate` required to apply new image | daily/2026-05-13.md | 2026-05-13 |
|
||||
| [[wiki/concepts/next-app-router-favicon]] | Next.js App Router favicon requires both `public/favicon.ico` AND `src/app/icon.png` (512×512) — one file alone is insufficient | daily/2026-05-13.md | 2026-05-13 |
|
||||
| [[wiki/concepts/pil-photo-compression-pipeline]] | PIL photo pipeline: `thumbnail((1200,1200), LANCZOS)` + JPEG 82 progressive; re-encoding already-compressed JPEG gives no size benefit | daily/2026-05-13.md | 2026-05-13 |
|
||||
| [[wiki/concepts/fastapi-lifespan-locals-app-state]] | `lifespan()` local vars are NOT module exports — access services via `request.app.state.service_name`, never `from app.main import service` | daily/2026-05-14.md | 2026-05-15 |
|
||||
| [[wiki/concepts/apache-redirect-suffix-preservation]] | `RedirectMatch permanent ^/path(/.*)?$ https://dest/path$1` — suffix-preserving 301 for service deactivation; replaces ProxyPass+Alias+Directory block | daily/2026-05-14.md | 2026-05-15 |
|
||||
| [[wiki/concepts/cloudflare-cdn-cache-corruption]] | HTTP 200 + `img.naturalHeight === 0` = CDN serving corrupt cached stub; replacing file on disk has no effect without cache purge | daily/2026-05-14.md | 2026-05-15 |
|
||||
| [[wiki/concepts/html5-video-source-order-ios]] | iOS Safari requires `playsInline` + `muted` for inline autoplay; `<source>` order matters — MP4 must be listed before WebM or Safari stalls | daily/2026-05-14.md | 2026-05-15 |
|
||||
<!-- Articles added automatically by compile.py -->
|
||||
<!-- Format: | [[concepts/slug]] | One-line summary | daily/YYYY-MM-DD.md | date | -->
|
||||
|
|
|
|||
61
wiki/concepts/apache-redirect-suffix-preservation.md
Normal file
61
wiki/concepts/apache-redirect-suffix-preservation.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
title: "Apache RedirectMatch — Suffix-Preserving 301 for Service Deactivation"
|
||||
tags: [apache, redirect, regex, devops, oliver]
|
||||
source: daily/2026-05-14.md
|
||||
created: 2026-05-15
|
||||
---
|
||||
|
||||
# Apache RedirectMatch — Suffix-Preserving 301 for Service Deactivation
|
||||
|
||||
## Pattern
|
||||
|
||||
When deactivating a path served by `ProxyPass` (e.g., moving a service off a subdomain), replace the entire `ProxyPass + Alias + Directory` block with a single `RedirectMatch`:
|
||||
|
||||
```apache
|
||||
# BEFORE (active service)
|
||||
ProxyPass /video-accessibility http://localhost:3001/
|
||||
ProxyPass /video-accessibility/ http://localhost:3001/
|
||||
Alias /video-accessibility /var/vhosts/.../video-accessibility
|
||||
<Directory /var/vhosts/.../video-accessibility>
|
||||
...
|
||||
</Directory>
|
||||
|
||||
# AFTER (service moved to optical-dev)
|
||||
RedirectMatch permanent ^/video-accessibility(/.*)?$ https://optical-dev.oliver.solutions/video-accessibility$1
|
||||
```
|
||||
|
||||
## Key Details
|
||||
|
||||
| Part | Meaning |
|
||||
|------|---------|
|
||||
| `^/video-accessibility` | Anchor to exact path prefix |
|
||||
| `(/.*)?` | Capture group 1: optional trailing slash + anything |
|
||||
| `$` | End of URI |
|
||||
| `$1` | Append captured suffix to destination URL |
|
||||
|
||||
## Why the capture group matters
|
||||
|
||||
Without `(/.*)?$1`, deep links break silently:
|
||||
|
||||
```
|
||||
# Without suffix capture:
|
||||
/video-accessibility/jobs/abc123 → https://optical-dev.../video-accessibility
|
||||
# (suffix lost — 404 on destination)
|
||||
|
||||
# With suffix capture:
|
||||
/video-accessibility/jobs/abc123 → https://optical-dev.../video-accessibility/jobs/abc123
|
||||
```
|
||||
|
||||
## When to use
|
||||
|
||||
- Service relocated to a different server/subdomain, but old URLs must keep working
|
||||
- Deactivating a vhost path without breaking bookmarks or SEO
|
||||
- Simpler than maintaining a dead ProxyPass target
|
||||
|
||||
## Reload
|
||||
|
||||
```bash
|
||||
sudo apachectl configtest && sudo systemctl reload apache2
|
||||
```
|
||||
|
||||
Always run `configtest` first — a regex syntax error silently 500s the entire vhost.
|
||||
59
wiki/concepts/cloudflare-cdn-cache-corruption.md
Normal file
59
wiki/concepts/cloudflare-cdn-cache-corruption.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
title: "Cloudflare CDN Cache Corruption — naturalHeight:0 Diagnostic"
|
||||
tags: [cloudflare, cdn, cache, debugging, media, payload-cms]
|
||||
source: daily/2026-05-14.md
|
||||
created: 2026-05-15
|
||||
---
|
||||
|
||||
# Cloudflare CDN Cache Corruption — `naturalHeight: 0` Diagnostic
|
||||
|
||||
## Symptom
|
||||
|
||||
- File replaced on disk (or re-uploaded via CMS)
|
||||
- HTTP response: `200 OK`, `content-type: image/jpeg` (or video/mp4)
|
||||
- Browser still renders broken image / blank video
|
||||
- Response headers include `cache-control: max-age=14400` and `cf-cache-status: HIT`
|
||||
- File is 896 bytes (or similarly tiny stub) despite correct size on origin
|
||||
|
||||
## Root Cause
|
||||
|
||||
Cloudflare cached a corrupt or stub response (e.g., a partial upload, a 0-byte placeholder) and continues serving it with HTTP 200. Replacing the file on the origin disk has **zero effect** until the cached response is purged.
|
||||
|
||||
## Diagnostic — JavaScript
|
||||
|
||||
```javascript
|
||||
// Run in browser console against any image URL suspected of CDN corruption
|
||||
const img = new Image()
|
||||
img.onload = () => console.log('naturalHeight:', img.naturalHeight)
|
||||
img.onerror = () => console.log('load error')
|
||||
img.src = 'https://example.com/media/video-thumbnail.jpg'
|
||||
|
||||
// naturalHeight === 0 with HTTP 200 → CDN serving corrupt cached stub
|
||||
// naturalHeight > 0 → image is valid
|
||||
```
|
||||
|
||||
## Fix Options
|
||||
|
||||
| Option | Command / Action | Notes |
|
||||
|--------|-----------------|-------|
|
||||
| **Purge via Cloudflare dashboard** | Zone → Caching → Purge Cache → Custom URLs | Requires Cloudflare account access |
|
||||
| **Purge via API** | `curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache"` | Fastest; scriptable |
|
||||
| **Delete CMS record** | Delete the media entry in Payload CMS (or equivalent) | Frontend falls back to static imports that bypass the poisoned URL |
|
||||
| **Rename the file** | Upload with a new filename — new URL, no cached entry | Last resort; breaks existing links |
|
||||
|
||||
## Payload CMS Workaround
|
||||
|
||||
When CDN cache purge is not immediately possible:
|
||||
|
||||
1. Delete the media document in Payload CMS admin
|
||||
2. Commit static asset to repo → frontend `import` uses bundled file (bypasses CDN URL entirely)
|
||||
3. Re-upload media later once CDN entry expires or is purged
|
||||
|
||||
## Key Signal
|
||||
|
||||
> **HTTP 200 + `img.naturalHeight === 0`** = CDN serving corrupt data.
|
||||
> HTTP status is NOT a reliable signal for media validity when CDN is in the path.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[wiki/concepts/cloudflare-proxied-domain-npm-subpath]] — Cloudflare proxied domains + NPM routing
|
||||
56
wiki/concepts/fastapi-lifespan-locals-app-state.md
Normal file
56
wiki/concepts/fastapi-lifespan-locals-app-state.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
title: "FastAPI lifespan() Locals — Must Access via request.app.state"
|
||||
tags: [fastapi, lifespan, app-state, python, gotcha]
|
||||
source: daily/2026-05-14.md
|
||||
created: 2026-05-15
|
||||
---
|
||||
|
||||
# FastAPI lifespan() Locals — Must Access via `request.app.state`
|
||||
|
||||
## Rule
|
||||
|
||||
Variables declared inside `lifespan()` are **local to that function**. They are NOT module-level exports. Importing them from `app.main` causes `ImportError` or returns `None`.
|
||||
|
||||
## Wrong
|
||||
|
||||
```python
|
||||
# app/main.py
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
knowledge_base_service = KnowledgeBaseService()
|
||||
yield
|
||||
|
||||
# routes/some_router.py
|
||||
from app.main import knowledge_base_service # ImportError — not exported
|
||||
```
|
||||
|
||||
## Correct
|
||||
|
||||
```python
|
||||
# app/main.py
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
app.state.knowledge_base_service = KnowledgeBaseService()
|
||||
yield
|
||||
# cleanup if needed
|
||||
|
||||
# routes/some_router.py
|
||||
@router.get("/query")
|
||||
async def query(request: Request):
|
||||
svc = request.app.state.knowledge_base_service
|
||||
# or safely:
|
||||
svc = getattr(request.app.state, "knowledge_base_service", None)
|
||||
```
|
||||
|
||||
## Why
|
||||
|
||||
`lifespan()` is a coroutine, not a module. Its local namespace is destroyed after `yield` returns. The canonical FastAPI pattern is `app.state` — a `State` object attached to the `FastAPI` instance that persists for the application lifetime.
|
||||
|
||||
## Diagnosis
|
||||
|
||||
The bug typically surfaces as HTTP 500 during the first request, with a `NameError` or `AttributeError` in the traceback. The lifespan itself runs fine (service initialises, logs look healthy), but route handlers can't reach the service.
|
||||
|
||||
## See Also
|
||||
|
||||
- FastAPI docs: [Lifespan Events](https://fastapi.tiangolo.com/advanced/events/)
|
||||
- Related pattern in this project: `analysis_routes.py` uses `request.app.state.knowledge_base_service`
|
||||
46
wiki/concepts/html5-video-source-order-ios.md
Normal file
46
wiki/concepts/html5-video-source-order-ios.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
title: "HTML5 Video — playsInline + MP4-First Source Order for iOS Safari"
|
||||
tags: [html, video, ios, safari, react, frontend]
|
||||
source: daily/2026-05-14.md
|
||||
created: 2026-05-15
|
||||
---
|
||||
|
||||
# HTML5 Video — `playsInline` + MP4-First Source Order for iOS Safari
|
||||
|
||||
## Required Attributes for Inline Autoplay
|
||||
|
||||
```html
|
||||
<!-- ALL four attributes required for silent autoplay on iOS Safari -->
|
||||
<video playsInline autoPlay muted loop>
|
||||
<source src="video.mp4" type="video/mp4" />
|
||||
<source src="video.webm" type="video/webm" />
|
||||
</video>
|
||||
```
|
||||
|
||||
In React/JSX: use `playsInline` (camelCase), not `playsinline`.
|
||||
|
||||
## `<source>` Order Matters
|
||||
|
||||
**MP4 must be listed first.** Safari reads `<source>` tags in order and stops at the first it can decode. WebM is not supported by Safari — if WebM is listed first, Safari stalls and never attempts MP4.
|
||||
|
||||
| Order | Result |
|
||||
|-------|--------|
|
||||
| MP4 → WebM | Safari plays MP4 ✓ |
|
||||
| WebM → MP4 | Safari stalls silently ✗ |
|
||||
|
||||
## Why `playsInline` Is Required
|
||||
|
||||
Without `playsInline`, iOS Safari forces the video into native fullscreen on play — breaking hero sections, background videos, and looping banners. The video appears to do nothing (silent refusal).
|
||||
|
||||
## Full Checklist for iOS Autoplay
|
||||
|
||||
- [x] `playsInline` (camelCase in JSX)
|
||||
- [x] `autoPlay` (camelCase in JSX)
|
||||
- [x] `muted` — iOS does NOT allow autoplay with audio
|
||||
- [x] `loop` (if looping)
|
||||
- [x] MP4 source listed before WebM
|
||||
- [x] Video file served with correct `Content-Type: video/mp4`
|
||||
|
||||
## Diagnostic
|
||||
|
||||
Video plays on desktop Chrome/Firefox but not iOS Safari → check `playsInline` first. Video plays on iOS Safari but shows a full-screen takeover → `playsInline` missing.
|
||||
11
wiki/log.md
11
wiki/log.md
|
|
@ -1,6 +1,17 @@
|
|||
|
||||
# Build Log
|
||||
|
||||
## [2026-05-15T21:00:00+02:00] compile | daily/2026-05-14.md
|
||||
- Source: daily/2026-05-14.md
|
||||
- Sessions: BAIC modcomms (FastAPI lifespan + Mailgun), video-accessibility (Cloudflare CDN corruption + iOS video), Apache redirect (service deactivation)
|
||||
- Articles created:
|
||||
- [[wiki/concepts/fastapi-lifespan-locals-app-state]] — `lifespan()` local vars not exported; use `request.app.state`
|
||||
- [[wiki/concepts/apache-redirect-suffix-preservation]] — `RedirectMatch` suffix-preserving 301 replaces ProxyPass+Alias+Directory
|
||||
- [[wiki/concepts/cloudflare-cdn-cache-corruption]] — `naturalHeight:0` diagnostic; HTTP 200 ≠ valid media when CDN in path
|
||||
- [[wiki/concepts/html5-video-source-order-ios]] — `playsInline` + MP4-first source order for iOS Safari inline autoplay
|
||||
- Articles updated: [[wiki/client-knowledge/baic]] (Mailgun domain gotcha, FastAPI lifespan access pattern, multi-layer rename coupling)
|
||||
- Index updates: [[wiki/concepts/_index]] (236→240, +4 entries); [[wiki/_master-index]] (concepts 196→240)
|
||||
|
||||
## [2026-05-14T00:00:00+02:00] compile | daily/2026-05-12.md
|
||||
- Source: daily/2026-05-12.md
|
||||
- Articles created: (none)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue