refactor(vault): Phase 5 — single agent contract
- Rewrite AGENTS.md as single operations manual (PARA, permission table, frontmatter conventions, safety rules, code style) - Root CLAUDE.md = one-line pointer to AGENTS.md - Delete 13 stub CLAUDE.md files across vault directories - Delete .claude/project-instructions.md + .claude/memory/instructions/ (content merged into AGENTS.md) - .claude/settings.json: deny plugin data.json + 04_Archive + git push; ask on .obsidian/** edits; remove SessionStart hook (claudesidian welcome) - Delete 3 upstream commands (init-bootstrap, install-claudesidian, upgrade) - Add risk/writes metadata to 14 remaining commands - Rewrite README.md (remove all claudesidian content) - package.json: name → my-vault, remove check-updates/firecrawl scripts
This commit is contained in:
@@ -1,176 +1,105 @@
|
||||
# Agent Coding Guidelines
|
||||
# AGENTS.md — Vault Operations Manual
|
||||
|
||||
**Purpose**: Code style and workflow for agentic coding assistants in this vault
|
||||
**Last Updated**: 2026-01-06
|
||||
**Purpose**: Single source of truth for AI agents operating in this Obsidian vault.
|
||||
**Last Updated**: 2026-09-26
|
||||
|
||||
---
|
||||
|
||||
## Build & Lint Commands
|
||||
## Directory Structure (PARA)
|
||||
|
||||
```
|
||||
00_Inbox/ Temporary capture, process weekly
|
||||
01_Projects/ Time-bound work with deadlines
|
||||
02_Areas/ Ongoing responsibilities (Health, Finance, etc.)
|
||||
03_Resources/ Reference materials and knowledge base
|
||||
04_Archive/ Completed items and clippings
|
||||
05_Attachments/ Media files (images, PDFs)
|
||||
06_Metadata/ Templates and reference docs (8 files)
|
||||
|
||||
.claude/ Agent config, commands, hooks
|
||||
.config/ ESLint, Prettier, TypeScript config
|
||||
.scripts/ Utility scripts (JS/Python)
|
||||
.github/ CI workflows
|
||||
.obsidian/ Obsidian app config (do not rewrite)
|
||||
```
|
||||
|
||||
## Permission Table
|
||||
|
||||
| Path | Rule |
|
||||
|---|---|
|
||||
| `00_Inbox/` | Free to create and edit |
|
||||
| `01_Projects/` | Edit on request |
|
||||
| `03_Resources/` | Edit on request |
|
||||
| `02_Areas/` | **Ask before editing** |
|
||||
| `04_Archive/` | **Never rewrite** — read-only historical record |
|
||||
| `06_Metadata/Templates/` | **Never rewrite** — wired to Obsidian plugins |
|
||||
| `.obsidian/` | **Never rewrite** — app config |
|
||||
| `.obsidian/plugins/*/data.json` | **Hard deny** — may contain secrets |
|
||||
| Credential files (see .gitignore) | **Never read or write** |
|
||||
|
||||
## Frontmatter Conventions
|
||||
|
||||
Active notes (00–03) use these core keys:
|
||||
- `created` (required) — ISO date `YYYY-MM-DD`
|
||||
- `status` — one of: `draft`, `active`, `done`, `archived`
|
||||
- `tags`, `type`, `updated` — optional
|
||||
|
||||
Content keys (never delete): `title`, `description`, `source`, `date`, `author`, `published`, `aliases`
|
||||
|
||||
**Clipper boundary**: `04_Archive/Inbox-Clippings/**` permanently uses the web clipper schema (`date`/`page-title`/`url`). Never migrate.
|
||||
|
||||
## Safety Rules
|
||||
|
||||
1. **Read before writing** — always read a file before editing it
|
||||
2. **Never delete without approval** — ask before removing content
|
||||
3. **Preserve everything when merging** — only remove verified exact duplicates
|
||||
4. **Verify before moving** — check destination exists, update all `[[wikilinks]]` after move
|
||||
5. **Never move numbered folders** (00–06) from vault root
|
||||
6. **Get approval for bulk operations** affecting 5+ files
|
||||
7. **Never commit secrets** — run `.scripts/verify-vault.mjs` before pushing
|
||||
|
||||
## Git Workflow
|
||||
|
||||
```bash
|
||||
# Lint & format (auto-fixes issues)
|
||||
pnpm lint # Run eslint + prettier with auto-fix
|
||||
|
||||
# Check only (no fixes)
|
||||
pnpm lint:check # Verify code style compliance
|
||||
|
||||
# Format only
|
||||
pnpm format # Prettier format all files
|
||||
pnpm format:check # Check formatting without changes
|
||||
|
||||
# Run scripts directly (no test framework configured)
|
||||
node .scripts/update-attachment-links.js
|
||||
GEMINI_API_KEY=xxx node .claude/mcp-servers/gemini-vision.mjs
|
||||
python3 .scripts/rename-chinese-to-english.py
|
||||
pnpm lint # Auto-fix before committing
|
||||
pnpm lint:check # Verify without changes
|
||||
node .scripts/verify-vault.mjs # Secret scanner (CI runs this too)
|
||||
```
|
||||
|
||||
- Commit after each work session with descriptive messages
|
||||
- Pull before starting work
|
||||
- Never force-push to main
|
||||
|
||||
## Organization Principles
|
||||
|
||||
- Inbox is temporary — process weekly
|
||||
- One idea per note (atomic notes)
|
||||
- Flat structure over deep nesting (max 4 levels for new notes)
|
||||
- Use links not folders for relationships
|
||||
- Link liberally, prefer over-linking
|
||||
|
||||
## Work Approach
|
||||
|
||||
- **Simple tasks** — execute directly
|
||||
- **Complex changes** — propose plan first (affected files, steps, rollback)
|
||||
|
||||
---
|
||||
|
||||
## Code Style Guidelines
|
||||
## Scripts — Code Style
|
||||
|
||||
### TypeScript/JavaScript
|
||||
### JavaScript/TypeScript
|
||||
|
||||
#### Imports
|
||||
- Single quotes, semicolons, `node:` prefix for built-in imports
|
||||
- `camelCase` functions/variables, `UPPER_SNAKE_CASE` constants, `PascalCase` classes
|
||||
- Prefix unused params with `_`
|
||||
- Handle errors in async functions, check env vars early
|
||||
|
||||
```javascript
|
||||
import type { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
```
|
||||
### Python
|
||||
|
||||
#### Formatting
|
||||
- `snake_case` functions/variables, `UPPER_SNAKE_CASE` constants
|
||||
- Type hints on function signatures
|
||||
|
||||
```javascript
|
||||
// Single quotes for strings, use semicolons
|
||||
const value = 'string'
|
||||
const obj = { name, value }
|
||||
const msg = `Hello ${name}`
|
||||
```
|
||||
|
||||
#### Error Handling
|
||||
|
||||
```javascript
|
||||
// Always handle errors in async functions
|
||||
try {
|
||||
await fs.access(filePath)
|
||||
} catch {
|
||||
throw new Error(`File not found: ${filePath}`)
|
||||
}
|
||||
|
||||
// Check environment variables early
|
||||
if (!process.env.API_KEY) {
|
||||
console.error('❌ API_KEY environment variable is required')
|
||||
process.exit(1)
|
||||
}
|
||||
```
|
||||
|
||||
#### Naming Conventions
|
||||
|
||||
```javascript
|
||||
function analyzeImage(args) {} // camelCase
|
||||
const MAX_ATTEMPTS = 60 // UPPER_SNAKE_CASE
|
||||
const imagePath = 'path/to/file.png' // camelCase
|
||||
class ImageAnalyzer {} // PascalCase
|
||||
function process(data, _unused) {} // Prefix unused with _
|
||||
```
|
||||
|
||||
### Python Scripts
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
path = Path('05_Attachments/Organized')
|
||||
|
||||
def process_files(files: List[str]) -> Dict[str, str]:
|
||||
"""Process list of files."""
|
||||
return {f: f for f in files}
|
||||
|
||||
file_path = 'path/to/file.md' # snake_case
|
||||
MAX_RETRIES = 3 # UPPER_SNAKE_CASE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Organization
|
||||
|
||||
```bash
|
||||
.claude/mcp-servers/ # MCP server implementations
|
||||
.scripts/ # Utility scripts (JS/Python)
|
||||
.config/ # Config files (eslint, prettier, tsconfig)
|
||||
```
|
||||
|
||||
### Script Structure
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs'
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
if (args.length !== 1) {
|
||||
console.log('Usage: node script.js <arg>')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Implementation
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### File Walking
|
||||
|
||||
```javascript
|
||||
function walkDir(dir, callback) {
|
||||
fs.readdirSync(dir).forEach((f) => {
|
||||
const dirPath = path.join(dir, f)
|
||||
const isDirectory = fs.statSync(dirPath).isDirectory()
|
||||
if (isDirectory && !f.includes('node_modules') && !f.includes('.git')) {
|
||||
walkDir(dirPath, callback)
|
||||
} else if (!isDirectory) {
|
||||
callback(dirPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Processing Files
|
||||
|
||||
```javascript
|
||||
walkDir('.', (filepath) => {
|
||||
if (filepath.endsWith('.md')) {
|
||||
let content = fs.readFileSync(filepath, 'utf8')
|
||||
// Process content
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(filepath, content, 'utf8')
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Before Making Changes
|
||||
|
||||
1. Read existing files to understand patterns
|
||||
2. Check package.json for available scripts/dependencies
|
||||
3. Run lint before committing: `pnpm lint`
|
||||
4. Test changes by running scripts directly
|
||||
5. Commit with descriptive message after verification
|
||||
|
||||
---
|
||||
|
||||
**Resources**:
|
||||
### Config
|
||||
|
||||
- ESLint: `.config/eslint.config.js`
|
||||
- Prettier: `.config/.prettierrc.js`
|
||||
|
||||
Reference in New Issue
Block a user