feat(hooks): add lint-format-advisory PostToolUse advisory hook#80
feat(hooks): add lint-format-advisory PostToolUse advisory hook#80
Conversation
…lugin trees - hooks/src/hooks/lint-format-advisory.ts: PostToolUse advisory hook for syntax/type/lint/format checks - hooks/tests/lint-format-advisory.test.ts: 42 tests (unit, extension gating, path exclusion, throttle, multi-IDE, error) - registered in core-claude, core-cursor, core-copilot, core-codex hooks.json.tmpl
Rosetta Triage ReviewSummary: Adds a Findings:
Suggestions:
Automated triage by Rosetta agent |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Rosetta hook (lint-format-advisory) that runs on PostToolUse file modifications and emits an advisory prompting agents to run syntax/type/lint/format checks after editing source-like files. It also wires the hook into the generated IDE plugin hook configurations and adds coverage to validate gating + throttling behavior.
Changes:
- Added
lint-format-advisoryhook implementation (extension/path filters + session/file throttling) and a Vitest test suite covering behavior across IDE payload shapes. - Registered the new hook in the plugin hook config templates / outputs for multiple IDE plugin trees (Claude, Cursor, Copilot, Codex) and added the compiled hook bundles.
- Added a plan doc and updated ignore rules for worktree infrastructure.
Reviewed changes
Copilot reviewed 16 out of 19 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.gitignore |
Ignores /.worktrees/ to keep local worktree infra out of SCM. |
agents/IMPLEMENTATION.md |
Documents the new lint-format-advisory hook at a high level. |
docs/plans/2026-05-05-lint-format-advisory.md |
Plan/notes for implementing and validating the hook. |
hooks/src/hooks/lint-format-advisory.ts |
New PostToolUse advisory hook (filters + throttle + message). |
hooks/tests/lint-format-advisory.test.ts |
New test suite validating extension gating, exclusions, throttling, and IDE output shapes. |
plugins/core-claude/hooks/hooks.json.tmpl |
Registers lint-format-advisory in the Claude hook config template. |
plugins/core-claude/hooks/hooks.json |
Registers lint-format-advisory in the generated Claude hook config. |
plugins/core-claude/hooks/lint-format-advisory.js |
Compiled/bundled hook artifact for the Claude plugin. |
plugins/core-cursor/hooks/hooks.json.tmpl |
Registers lint-format-advisory in the Cursor hook config template. |
plugins/core-cursor/hooks/hooks.json |
Registers lint-format-advisory in the generated Cursor hook config. |
plugins/core-cursor/.cursor/hooks/lint-format-advisory.js |
Compiled/bundled hook artifact for the Cursor plugin runtime path. |
plugins/core-copilot/hooks/hooks.json.tmpl |
Registers lint-format-advisory in the Copilot “hooks/” config template. |
plugins/core-copilot/hooks/hooks.json |
Registers lint-format-advisory in the generated Copilot “hooks/” config. |
plugins/core-copilot/hooks/lint-format-advisory.js |
Compiled/bundled hook artifact for the Copilot plugin. |
plugins/core-copilot/.github/plugin/hooks.json.tmpl |
Registers lint-format-advisory in the Copilot agentPlugins hook config template. |
plugins/core-codex/.codex-plugin/hooks.json.tmpl |
Registers lint-format-advisory in the Codex hook config template. |
plugins/core-codex/.codex/hooks.json |
Registers lint-format-advisory in the Codex runtime hook config. |
plugins/core-codex/.codex/hooks/lint-format-advisory.js |
Compiled/bundled hook artifact for the Codex plugin runtime path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| "matcher": "Write|Edit|create_file|replace_string_in_file|multi_replace_string_in_file", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "bash": "for base in \"$HOME/Library/Application Support/Code/agentPlugins\" \"$HOME/.local/share/Code/agentPlugins\"; do root=\"$base/github.com/griddynamics/rosetta/plugins/core-copilot\"; if [ -f \"$root/hooks/lint-format-advisory.js\" ]; then node \"$root/hooks/lint-format-advisory.js\"; break; fi; done", | ||
| "powershell": "$root = \"$env:LOCALAPPDATA\\Code\\agentPlugins\\github.com\\griddynamics\\rosetta\\plugins\\core-copilot\"; if (Test-Path \"$root\\hooks\\lint-format-advisory.js\") { node \"$root\\hooks\\lint-format-advisory.js\" }" | ||
| } | ||
| ] | ||
| } |
| }, | ||
| { | ||
| "matcher": "Write|Edit|apply_patch|functions.apply_patch", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "node .codex/hooks/lint-format-advisory.js" | ||
| } | ||
| ] | ||
| } |
| > **WORKTREE SETUP — READ FIRST:** | ||
| > All work happens in a dedicated git worktree, NOT in the main checkout. | ||
| > **Task 0 must be executed first** — it creates the worktree at | ||
| > `.worktrees/lint-format-advisory/` (relative to repo root `/Users/akoziar/dev/gd/rosetta`). | ||
| > After Task 0, ALL file edits, `git add`, `git commit`, and `npm` commands | ||
| > run from inside `/Users/akoziar/dev/gd/rosetta/.worktrees/lint-format-advisory/`. | ||
| > Use absolute paths in all tool calls. Never commit in the main checkout. | ||
|
|
||
| **Goal:** Add a `PostToolUse` hook that nudges AI agents to add a plan step for syntax/type/lint/format checks after editing any monitored code file, without running those checks itself. | ||
|
|
||
| **Architecture:** Single hook entry file (`lint-format-advisory.ts`) using `defineHook` DSL with `extOneOfCi` predicate and `throttle.dedupBy: ['session','filePath']`. Zero runtime deps. Registered in all four plugin trees. No library split — logic is `advise(message(filePath))`, no evaluation module needed. | ||
|
|
||
| **Tech Stack:** TypeScript 5.4, Node.js CJS, vitest 4, esbuild (auto-bundled per IDE by `scripts/build-bundles.mjs`). | ||
|
|
||
| **Branch:** `feat/hooks-lint-format-advisory` from `v3`. Worktree: `.worktrees/lint-format-advisory/`. PR target: `v3`. | ||
|
|
||
| **Repo root:** `/Users/akoziar/dev/gd/rosetta` | ||
| **Worktree root:** `/Users/akoziar/dev/gd/rosetta/.worktrees/lint-format-advisory` | ||
| **Plan file (absolute):** `/Users/akoziar/dev/gd/rosetta/docs/plans/2026-05-05-lint-format-advisory.md` |
| **Branch:** `feat/hooks-lint-format-advisory` from `v3`. Worktree: `.worktrees/lint-format-advisory/`. PR target: `v3`. | ||
|
|
||
| **Repo root:** `/Users/akoziar/dev/gd/rosetta` | ||
| **Worktree root:** `/Users/akoziar/dev/gd/rosetta/.worktrees/lint-format-advisory` | ||
| **Plan file (absolute):** `/Users/akoziar/dev/gd/rosetta/docs/plans/2026-05-05-lint-format-advisory.md` | ||
|
|
||
| --- | ||
|
|
||
| ## Key File Paths | ||
|
|
||
| | Role | Path (relative to repo root) | | ||
| | --- | --- | | ||
| | Hook entry (create) | `hooks/src/hooks/lint-format-advisory.ts` | | ||
| | Tests (create) | `hooks/tests/lint-format-advisory.test.ts` | | ||
| | Plan doc (create in worktree) | `docs/plans/2026-05-05-lint-format-advisory.md` | |
| - Monitored extensions: `.html`, `.css`, `.js`, `.ts`, `.jsx`, `.tsx`, `.py`, `.cs`, `.ps1`, `.cmd`, `.java`, `.go`, `.rs`, `.md`. | ||
| - Throttle: `dedupBy: ['session','filePath']` — one advisory per (session, file) within a 5-second window; Copilot double-fire deduped automatically. | ||
| - No plan_manager coupling (deferred to future PR alongside actual linter execution). | ||
| - Registered in all four plugins via `.tmpl` templates. Full vitest suite (42 tests). |
…] style Update advisoryMessage to use path.basename and the [Rosetta Advisory] prefix, matching the md-file-advisory pattern. Update Cursor format integration test to expect basename in advisory output.
Summary
hooks/src/hooks/lint-format-advisory.ts: PostToolUse hook that emits an advisory nudging AI agents to run syntax/type/lint/format checks after editing a code file..html .css .js .ts .jsx .tsx .py .cs .ps1 .cmd .java .go .rs .md.dedupBy: ['session','filePath']— no spam on rapid edits; Copilot double-fire absorbed by same mechanism.hooks.json.tmpltemplates (core-claude,core-cursor,core-copilot,core-codex)./.worktrees/to.gitignore(infrastructure).hooks-linked-unicornbrainstorm notes.Test plan
cd hooks && npm run check— no TS errorscd hooks && npm run build— four bundles producedcd hooks && npm run test— all 398 tests pass including regression.tsfile in Claude Code session → advisory appears; edit.json→ silent; same.tsimmediately again → silent🤖 Generated with Claude Code