AGENTS.md ยท diff
git:20260808.642b7d7 to git:20260908.0c07d35
25 added, 0 removed. Audit A to A.
# Kinocut - Project Rules
## Public Agent Skill
- `skills/kinocut/SKILL.md` is the canonical public skill for this repo.
- Invoke `$kinocut` in compatible agent hosts for guarded video inspection, editing, Hyperframes, repurposing, release checkpoints, and human-review workflows.
- `skills/mcp-video/SKILL.md` is a compatibility entry point only. Keep it thin and direct new work to `$kinocut`.
- Keep the skill aligned with `docs/CLI_REFERENCE.md`, `docs/TOOLS.md`, the Python client, and public MCP tool names when those surfaces change.
## Before Writing Any Code
1. **Check if it already exists.** Search `ffmpeg_helpers.py`, `validation.py`, `limits.py`, and `defaults.py` before writing any utility function. Import, don't duplicate.
2. **Check the public API.** Functions registered as MCP tools in `server.py` are the public surface. Internal functions are prefixed with `_`. Don't break tool signatures.
## FFmpeg Security
3. **ALL user-controlled values in FFmpeg filter strings MUST be escaped** with `_escape_ffmpeg_filter_value()` from `ffmpeg_helpers.py`. This includes: colors, fonts, text, paths, and any string that goes into a `-vf` or `-filter_complex` argument.
4. **Gold standard pattern** (from `effects_engine.py:text_animated`):
```python
safe_text = _escape_ffmpeg_filter_value(text)
safe_font = _escape_ffmpeg_filter_value(font) if font is not None else font
safe_color = _escape_ffmpeg_filter_value(color) if color is not None else color
```
5. **Never use f-string interpolation of user values directly into filter strings** without escaping.
## Error Handling
6. **Always raise custom types from `errors.py`**, never raw `ValueError`, `RuntimeError`, or `FileNotFoundError`.
- Input file issues โ `InputFileError`
- FFmpeg processing failures โ `ProcessingError` (auto-truncates stderr to 500 chars)
- Bad parameters โ `MCPVideoError` with `error_type="validation_error"`
7. **Never embed `result.stderr` directly in error messages.** Route through `ProcessingError` which truncates to 500 chars.
8. **Never use bare `except Exception:` without logging.** Always `except Exception as e: logger.warning(...)`.
## Subprocess Calls
9. **ALL `subprocess.run()` and `subprocess.Popen()` calls MUST have a `timeout` parameter.** Use `DEFAULT_FFMPEG_TIMEOUT` from `defaults.py`.
10. **Catch `subprocess.TimeoutExpired`** and raise `ProcessingError` with a clear timeout message.
11. **Validate input paths** with `_validate_input_path()` from `ffmpeg_helpers.py` before passing to subprocess.
## Configuration
12. **All default values MUST be defined in `defaults.py`.** Reference by name, never hardcode magic numbers like `crf=23`, `timeout=600`, `fps=30`.
13. **Validation constants** go in `validation.py`. Resource limits go in `limits.py`. Runtime defaults go in `defaults.py`.
## Size Limits
14. **No module may exceed 800 LOC.** If it does, split into a subpackage.
15. **No function may exceed 80 lines.** If it does, extract helpers.
16. **No dead code.** If a function/method/constant has zero callers outside its definition, remove it.
## Architecture
17. **`ffmpeg_helpers.py` is the single source of truth** for: `_run_ffmpeg()`, `_validate_input_path()`, `_escape_ffmpeg_filter_value()`, `_get_video_duration()`, `_run_ffprobe()`, `_seconds_to_srt_time()`. Never duplicate these.
18. **`server.py` is the tool registration layer.** Business logic goes in engine modules, not in server tool handlers.
19. **Lazy imports in `server.py`** keep startup fast. Follow the existing pattern: import inside the tool handler function.
## Git Workspace Hygiene
Preserve user-owned repository state and inspect it before any Git cleanup.
- Do not delete branches, remove worktrees, prune remotes, rebase, merge, reset,
or discard changes unless the task explicitly authorizes the exact operation
and target.
- Clean up only artifacts created by the current task when that cleanup is safe
and authorized; otherwise report them for owner direction.
- A clean working tree is a goal only when the task requires it. Never convert
an existing dirty state into a cleanup task or overwrite user work.
+ ## Contributor CI ownership
+
+ When checking external contributions, own the CI investigation instead of handing
+ the user an unexplained approval gate.
+
+ - An empty PR check list is not evidence that CI is absent. Inspect workflow runs
+ for the exact PR head; distinguish `action_required`, queued, running, failed,
+ skipped and successful runs. Confirm the reason for `action_required`.
+ - Explain first-time-contributor approval as permission to execute CI. It does
+ not approve the code, merge the PR, or grant the contributor repository access.
+ - Before enabling a run, inspect the complete diff, workflow definitions and
+ invoked scripts, token permissions, secrets exposure and runner isolation.
+ Do not execute untrusted code on a persistent or privileged runner merely to
+ clear the gate. Recheck that the reviewed head still matches the pending run.
+ - When existing user authority covers normal CI execution and review establishes
+ that the run is safe, approve the specific pending runs and verify their actual
+ states. Do not ask the user to repeat authorization or perform a routine click.
+ - If authority, access or safety is unresolved, state the exact blocker, the
+ investigation already completed, and the smallest decision or action needed.
+ Never substitute a bare "maintainer approval required" status for that work.
+ - Keep run approval separate from code review and merge gates. Do not disable
+ protections, expand token permissions, change repository settings, approve
+ future contributions indiscriminately, or post contributor messages without
+ the applicable authorization.
+
## Testing
20. **Every fix must pass `python3 -m pytest tests/ -x -q --tb=short`** before committing.
21. **Run `python3 -c "import kinocut, mcp_video; assert kinocut.Client is mcp_video.Client"`** to verify the canonical import and compatibility shim after changes.
<!-- EMPOWER_ORCHESTRATOR:START -->
## Empower Orchestrator law
The canonical law and blast-radius check live in
`docs/agent-law/empower-orchestrator.md`. Read that source when orchestrating
automation or durable system changes.
<!-- EMPOWER_ORCHESTRATOR:END -->