- Transform tufte-press from reference guide to conversation-aware generator - Add JSON generation from conversation context following strict schema - Create build automation scripts with Nix environment handling - Integrate CUPS printing with duplex support - Add comprehensive workflow documentation Scripts added: - skills/tufte-press/scripts/generate-and-build.sh (242 lines) - skills/tufte-press/scripts/build-card.sh (23 lines) Documentation: - Updated SKILL.md with complete workflow instructions (370 lines) - Updated README.md with usage examples (340 lines) - Created SKILL-DEVELOPMENT-STRATEGY-tufte-press.md (450 lines) - Added worklog: 2025-11-10-tufte-press-skill-evolution.org Features: - Agent generates valid JSON from conversation - Schema validation before build (catches errors early) - Automatic Nix shell entry for dependencies - PDF build via tufte-press toolchain - Optional print with duplex support - Self-contained margin notes enforced - Complete end-to-end testing Workflow: Conversation → JSON → Validate → Build → Print Related: niri-window-capture, screenshot-latest, worklog skills
7.5 KiB
Data Model: Screenshot Analysis Skill
Feature: 001-screenshot-analysis
Date: 2025-11-08
Overview
This skill has a minimal data model focused on configuration and file metadata. There are no persistent data structures or databases - all data is ephemeral (file system state) or configuration (JSON file).
Entities
Screenshot File
Description: A screenshot image file discovered in the configured directory
Attributes:
path(string, absolute): Full filesystem path to the screenshot file- Example:
/home/user/Pictures/Screenshots/screenshot-2025-11-08-143022.png - Validation: Must be absolute path, must exist, must be readable
- Example:
modification_time(timestamp, Unix epoch): File modification time in seconds since epoch- Example:
1731078622(2025-11-08 14:30:22 UTC) - Used for: Sorting files by recency
- Source:
stat -c '%Y'
- Example:
format(enum): Image file format- Allowed values:
PNG,JPG,JPEG - Validation: Case-insensitive match on file extension
- Used for: Filtering non-screenshot files
- Allowed values:
Lifecycle: Ephemeral (discovered on each invocation, not persisted)
Relationships: None (standalone file, no references)
State Transitions: N/A (stateless)
Screenshot Directory
Description: Location where screenshots are stored
Attributes:
path(string, absolute): Full filesystem path to the directory- Default:
~/Pictures/Screenshots(expanded to absolute) - Custom: Loaded from config file
screenshot_dirfield - Validation: Must be absolute, must exist, must be readable
- Default:
exists(boolean, derived): Whether the directory exists- Computed:
[[ -d "$path" ]]
- Computed:
readable(boolean, derived): Whether the directory is readable- Computed:
[[ -r "$path" ]]
- Computed:
Lifecycle: Checked on each skill invocation
Relationships: Contains zero or more Screenshot Files
Skill Configuration
Description: Optional user configuration stored in JSON file
Storage Location (precedence order):
~/.config/opencode/skills/screenshot-analysis/config.json(OpenCode)~/.claude/skills/screenshot-analysis/config.json(Claude Code)
Schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"screenshot_dir": {
"type": "string",
"description": "Custom screenshot directory path (absolute or ~-expanded)",
"examples": [
"/home/user/Pictures/Screenshots",
"~/Screenshots",
"/mnt/storage/screenshots"
]
}
},
"additionalProperties": false
}
Attributes:
screenshot_dir(string, optional): Custom directory path- Default:
~/Pictures/Screenshotsif omitted or file doesn't exist - Validation: Must resolve to valid directory path after tilde expansion
- Default:
Lifecycle: Loaded once per skill invocation
Validation Rules:
- If config file missing → Use default, no error
- If config file malformed JSON → Log warning, use default
- If
screenshot_dirpresent but invalid path → Error with actionable message - If
screenshot_diromitted → Use default
Example Valid Configs:
// Minimal (use all defaults)
{}
// Custom directory
{
"screenshot_dir": "/home/user/Documents/Screenshots"
}
// Tilde expansion supported
{
"screenshot_dir": "~/Pictures/MyScreenshots"
}
Example Invalid Configs:
// Invalid: not an object
"~/Pictures"
// Invalid: wrong type
{
"screenshot_dir": 12345
}
// Invalid: extra fields (allowed but ignored per additionalProperties: false)
{
"screenshot_dir": "~/Pictures/Screenshots",
"unknown_field": "value"
}
Data Flow
1. Skill Invoked
↓
2. Load Configuration
- Check ~/.config/opencode/skills/screenshot-analysis/config.json
- Check ~/.claude/skills/screenshot-analysis/config.json
- Parse JSON (jq)
- Extract screenshot_dir or use default
↓
3. Validate Directory
- Expand tilde (~) to absolute path
- Check directory exists ([[ -d ]])
- Check directory readable ([[ -r ]])
↓
4. Discover Screenshot Files
- Find regular files (exclude symlinks)
- Filter by extension (.png, .jpg, .jpeg)
- Get modification times (stat -c '%Y %n')
↓
5. Sort by Recency
- Primary: modification time (newest first)
- Tiebreaker: lexicographic filename (Z > A)
↓
6. Select File(s)
- Latest: First result (head -1)
- Nth: Nth result (sed -n "${N}p")
- Time-filtered: All matching time constraint
↓
7. Return File Path(s)
- Absolute path(s) to agent
- Agent passes to image analysis
Validation Rules Summary
| Entity | Field | Validation | Error Behavior |
|---|---|---|---|
| Config File | JSON format | Valid JSON | Warn + use default |
| Config File | screenshot_dir | Absolute/expandable path | Error if invalid |
| Screenshot Dir | path | Exists + readable | Error with message |
| Screenshot File | path | Regular file (not symlink) | Skip (filter) |
| Screenshot File | format | PNG/JPG/JPEG extension | Skip (filter) |
| Screenshot File | modification_time | Valid Unix timestamp | Skip (malformed) |
Edge Cases
Empty Directory
- Scenario: Screenshot directory exists but contains no screenshot files
- Behavior: Return empty result (not an error)
- Message: "No screenshots found in {directory}"
Permission Denied
- Scenario: Screenshot directory exists but is not readable
- Behavior: Error with actionable message
- Message: "Directory not readable (permission denied): {directory}"
Symlinks Present
- Scenario: Directory contains symlinks to screenshot files
- Behavior: Symlinks are filtered out (skip)
- Validation:
find -type fexcludes symlinks automatically
Same Timestamp
- Scenario: Multiple files have identical modification times
- Behavior: Use lexicographic filename ordering as tiebreaker
- Example: Given
a.pngandz.pngboth at timestamp 1731078622,z.pngis selected (Z > A)
Malformed Config
- Scenario: config.json exists but contains invalid JSON
- Behavior: Log warning, fall back to default directory
- Message: "Warning: Failed to parse config.json, using default directory"
Missing jq
- Scenario:
jqcommand not found on system - Behavior: Log warning, fall back to default directory
- Message: "Warning: jq not found, using default directory"
Constraints
Performance:
- File discovery must complete in <1 second for 1000 files (SC-002)
- Config loading must be negligible (<10ms)
Storage:
- No persistent storage (stateless skill)
- Config file size limited to 1KB (reasonable for JSON with single path field)
Scalability:
- Tested up to 1000 files (requirement)
- Degrades gracefully beyond 10,000 files (acceptable for screenshot directories)
Assumptions
- Screenshot files are regular files (not symlinks, special files, or directories)
- Modification time accurately reflects screenshot recency (OS maintains mtime correctly)
- File extensions (.png, .jpg, .jpeg) reliably indicate image format (case-insensitive)
- Config file is user-managed (skill doesn't create or modify it)
- Users won't have more than ~10,000 screenshots in a single directory
Future Enhancements (Out of Scope for v1)
- Screenshot Metadata Database: Index screenshots for faster queries (>10k files)
- Tag/Label Support: Add metadata field for user-defined tags
- Multi-Directory Search: Support searching multiple directories
- Format Conversion: Support additional formats (WebP, BMP, TIFF)
- Content-Based Search: OCR text extraction, visual similarity