Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Quality โ Go testing, linting, coverage, race detection, LSP gates
Each harness specialist agent (moai-harness-hook-ci-specialist,
moai-harness-workflow-specialist, moai-harness-quality-specialist) loads this single
skill for shared context. Supplements general agents (expert-devops, manager-spec,
manager-quality) with project-specific patterns.
27 hook events spanning Session, Tool, Agent, State, Permissions, Interaction, Team,
and Worktree categories. Verify: ls .claude/hooks/moai/handle-*.sh | wc -l == 27. Full
event list in .claude/rules/moai/core/agent-hooks.md.
SPEC Workflow Pipeline
/moai plan "description" โ manager-spec โ SPEC document with EARS requirements
/moai run SPEC-XXX โ manager-develop โ Implementation (TDD or DDD)
/moai sync SPEC-XXX โ manager-docs โ Documentation + PR creation
Quality Targets
go vet ./... and golangci-lint run must be zero errors at all phases.
go test ./... all-pass at all phases; -race must be zero races at run.
Coverage: per-package >= 85% at sync (go test -cover ./...); critical packages
(internal/cli/, internal/template/) >= 90%. LSP gates: run = zero errors / zero type
errors / zero lint errors; sync adds warnings cap (max 10).
Implementation Guide
Section 1 โ Hook & CI Patterns
Hook wrapper pattern (thin shell wrapper, Go does the work): read stdin JSON via
INPUT=$(cat), pipe to moai hook {event} <<< "$INPUT". Lives at
.
.claude/hooks/moai/handle-{event}.sh
settings.json invocation rules: always quote $CLAUDE_PROJECT_DIR (e.g.
"$CLAUDE_PROJECT_DIR/.claude/hooks/moai/handle-X.sh"); set timeout (default 5s, max
10s for post-processing); use full path, do not rely on PATH.
Agent-scoped hooks declared in agent YAML frontmatter under hooks: map (per event:
PreToolUse, PostToolUse, SubagentStop, etc.) with matcher regex and command
shell call to handle-agent-hook.sh {action}. Default timeout 5s (10s for post-processing).
GitHub Actions workflows in .github/workflows/: ci.yml (push/PR to main โ matrix
ubuntu/macos/windows ร Go 1.24, lint + test + build); release.yml (tag v* โ
GoReleaser 5 platforms); release-drafter.yml (PR merge to main โ auto-label + draft
changelog); auto-merge.yml (Dependabot CI pass โ squash); codeql.yml (push/PR โ Go
security analysis); spec-lint.yml (PR โ SPEC frontmatter validation);
spec-status-auto-sync.yml (schedule โ status drift detection); docs-i18n-check.yml
(PR touching docs-site โ 4-locale sync verification).
Release process โ always use ./scripts/release.sh vX.Y.Z "description" (or
--hotfix); never manual tag push. Chain: script โ tag โ release.yml โ GoReleaser โ
5-platform binaries โ GitHub Release โ Release Drafter updates changelog.
Hook handler testing: Go unit tests in internal/hook/ read JSON from stdin and
exercise the handler logic directly.
Section 2 โ Workflow Patterns
SPEC structure under .moai/specs/<SPEC-ID>/: spec.md (EARS + AC), plan.md (M1..Mn
milestones), acceptance.md (binary AC + REQโAC traceability, Tier M+), scenarios.md
(Tier L), risks.md (Tier L), progress.md (auto-generated during run). Tier S = 2
artifacts (spec + plan, AC inline); Tier M = 3 (adds acceptance.md); Tier L = 5 (adds
design + research).
EARS requirement patterns: Ubiquitous (The system shall [action]); Event-Driven
(When [event], the system shall [action]); Unwanted (If [bad condition], the system shall [action]); State-Driven (While [state], the system shall [action]); Optional
(Where [feature] enabled, the system shall [action]).
Plan-in-main doctrine: SPEC plan PRs merge to main (not feature branches). Run phase
uses worktree isolation. Sync PRs merge to main with full review history.
Milestones: M1 Foundation โ M2 Core โ M3 Integration โ M4 Edge cases โ M5 Polish.
Waves: 30+ task SPECs split into wave-PRs; track in progress.md.
AC format: AC-{SHORT}-{NN}: {verifiable condition} with Verification: command
and Priority: P0|P1|P2.
Critical test isolation rules: (1) always t.TempDir() โ auto-cleanup under /tmp;
(2) filepath.Join trap: Join("/a/b", "/var/folders/x") = /a/b/var/folders/x (WRONG)
โ use filepath.Abs(); (3) OTEL_* env vars MUST NOT use t.Setenv in parallel tests
(global state race); (4) after any fix, run FULL suite (go test ./...); (5) flaky debug
disables cache via go test -count=1 ./....
Test execution: go test ./... (full), -race (race detection), -cover (coverage),
-run TestX ./pkg/ (specific), -count=1 (disable cache for flaky debug), -v (verbose).
Table-driven test pattern: standard Go convention โ tests := []struct{name, input, want string; wantErr bool}{...} + for _, tt := range tests { t.Run(tt.name, ...) }.
Cover happy path + error path + edge cases per row.
LSP quality gate thresholds by phase:
Phase
LSP Errors
Type Errors
Lint Errors
Warnings
plan
Baseline captured
Baseline
Baseline
Baseline
run
Zero required
Zero required
Zero required
โ
sync
Zero required
Zero required
Zero required
Max 10
Pre-commit quality gate: go vet ./... && golangci-lint run && go test ./....
Coverage report: go test -coverprofile=coverage.out ./... then
go tool cover -html=coverage.out.
Common quality issues: filepath.Join with absolute path โ use filepath.Abs();
OTEL data race in parallel tests โ fake/no-op exporter; test writes outside temp dir โ
always t.TempDir(); flaky CI โ go test -race -count=1.