aidd-lint: trigger architecture (hook + home ADR) #108

Closed
opened 2026-07-23 11:31:32 +00:00 by jared · 2 comments
Owner

Context

How the aidd-lint tiers actually fire (see mapping ticket). Proposal: a PostToolUse hook on Write/Edit where the file matches **/*.md under plugin/prompt/reference paths. Gates: skip edits under ~20 changed words (a 5-word edit needs no lint pass); dedupe repeated edits to the same file within a session. Tier 1 (deterministic cops) runs synchronously in the hook -- fast, no model cost. Tier 2 (charter judge) runs async or batched at session end -- it costs a model call. Tier 3 is not automated: findings neither tier can classify route to a human, mirroring ADR-0048's judgment-residue -> reviewer-charter pattern.

Open decision -- WHERE THIS LIVES, needs an ADR before implementation (/os-adr:find then /os-adr:create):

  • os-doc-hygiene: doc-quality is its domain; already has scan/report/clean infra and lifecycle state.
  • os-sdlc: owns the cop/ticket/TDD discipline and the mine-lints discovery loop.
  • New plugin: if AiDD-file linting is judged its own domain.

Acceptance criteria

  • ADR recorded for the home decision.
  • Hook config + edit-size gate implemented and documented in the chosen plugin.
  • Tier-1 run wired synchronous; Tier-2 wired async/on-demand; both output to one report format.
  • A 5-word edit to a .md file triggers nothing; a 100-word edit triggers Tier 1.

Non-goals

  • No linting of non-AiDD markdown (README, docs/ prose) in v1 -- scope is prompts, skills, references, instructions.
  • No blocking/rejecting edits; report-only.

Verify

Edit-size gate boundary test (19 vs 21 changed words); hook fires on SKILL.md edit in a sandbox session; report lands where the chosen plugin documents.

## Context How the aidd-lint tiers actually fire (see mapping ticket). Proposal: a PostToolUse hook on Write/Edit where the file matches `**/*.md` under plugin/prompt/reference paths. Gates: skip edits under ~20 changed words (a 5-word edit needs no lint pass); dedupe repeated edits to the same file within a session. Tier 1 (deterministic cops) runs synchronously in the hook -- fast, no model cost. Tier 2 (charter judge) runs async or batched at session end -- it costs a model call. Tier 3 is not automated: findings neither tier can classify route to a human, mirroring ADR-0048's judgment-residue -> reviewer-charter pattern. Open decision -- WHERE THIS LIVES, needs an ADR before implementation (`/os-adr:find` then `/os-adr:create`): - **os-doc-hygiene**: doc-quality is its domain; already has scan/report/clean infra and lifecycle state. - **os-sdlc**: owns the cop/ticket/TDD discipline and the mine-lints discovery loop. - **New plugin**: if AiDD-file linting is judged its own domain. ## Acceptance criteria - ADR recorded for the home decision. - Hook config + edit-size gate implemented and documented in the chosen plugin. - Tier-1 run wired synchronous; Tier-2 wired async/on-demand; both output to one report format. - A 5-word edit to a .md file triggers nothing; a 100-word edit triggers Tier 1. ## Non-goals - No linting of non-AiDD markdown (README, docs/ prose) in v1 -- scope is prompts, skills, references, instructions. - No blocking/rejecting edits; report-only. ## Verify Edit-size gate boundary test (19 vs 21 changed words); hook fires on SKILL.md edit in a sandbox session; report lands where the chosen plugin documents.
Author
Owner

Implemented on branch aidd-lint/tier-2 (uncommitted, pending review). hooks/hooks.json (PostToolUse Write|Edit|MultiEdit + SessionStart + SessionEnd, all fail-open exit-0), pure AiddLint::Gate — Edit = added+removed word diff, Write to tracked file = word-diff vs git show HEAD:<path> (whole-content only for untracked; prevents lint storms on scaffolded files), threshold in top-level gate: config, 19/21 boundary tests. Scope via paths: globs (CLAUDE.md excluded v1). Session dedupe + Tier-2 queue under .cc-os/aidd-lint/, SessionStart GC sweep of orphans (gc.orphan_days), SessionEnd finalize-only — never invokes a model; Tier-2 drain is on-demand per premortem timeout/auth/cost risk. Single report.md keep-exactly-one rollover, no JSON twin. invariants.md documents four invariants incl. the Tier2::Judge seam #107 implemented against. ADR-0059 records the trigger architecture.

Bonus fix: Config repo-root/config-discovery used File.directory?(".git"), always false in git worktrees — fixed (File.exist?) with regression tests; also affected DeadReferencePointer.

Open: queue-drain wiring (follow-up); bin/refresh-plugins at merge time. Suite green (151/316 with #107).

Implemented on branch aidd-lint/tier-2 (uncommitted, pending review). hooks/hooks.json (PostToolUse Write|Edit|MultiEdit + SessionStart + SessionEnd, all fail-open exit-0), pure AiddLint::Gate — Edit = added+removed word diff, Write to tracked file = word-diff vs `git show HEAD:<path>` (whole-content only for untracked; prevents lint storms on scaffolded files), threshold in top-level gate: config, 19/21 boundary tests. Scope via paths: globs (CLAUDE.md excluded v1). Session dedupe + Tier-2 queue under .cc-os/aidd-lint/, SessionStart GC sweep of orphans (gc.orphan_days), SessionEnd finalize-only — never invokes a model; Tier-2 drain is on-demand per premortem timeout/auth/cost risk. Single report.md keep-exactly-one rollover, no JSON twin. invariants.md documents four invariants incl. the Tier2::Judge seam #107 implemented against. ADR-0059 records the trigger architecture. Bonus fix: Config repo-root/config-discovery used File.directory?(".git"), always false in git worktrees — fixed (File.exist?) with regression tests; also affected DeadReferencePointer. Open: queue-drain wiring (follow-up); bin/refresh-plugins at merge time. Suite green (151/316 with #107).
Author
Owner

Reviewed and merged to main in 41240a8 (2026-07-23).

Reviewed and merged to main in 41240a8 (2026-07-23).
jared closed this issue 2026-07-23 17:49:50 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#108
No description provided.