@bonesofspring/ai-rules 0.2.28 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/docs/MAVIS-COMPATIBILITY.md +10 -6
- package/docs/MAVIS.md +15 -6
- package/docs/OPENCODE-COMPATIBILITY.md +2 -2
- package/docs/OPENCODE.md +1 -1
- package/package.json +1 -1
- package/presets/_shared/core/meta/preset-pr-checklist.md +2 -2
- package/presets/claude/android-kotlin/CLAUDE.md +3 -1
- package/presets/claude/android-kotlin/REPO_AGENTS.md +1 -1
- package/presets/claude/android-kotlin/hooks/README.md +6 -5
- package/presets/claude/android-kotlin/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/android-kotlin/hooks/examples/README.md +2 -0
- package/presets/claude/android-kotlin/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/android-kotlin/rules/README.md +1 -1
- package/presets/claude/android-kotlin/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/android-kotlin/settings.json +23 -0
- package/presets/claude/go/CLAUDE.md +3 -1
- package/presets/claude/go/REPO_AGENTS.md +1 -1
- package/presets/claude/go/hooks/README.md +6 -5
- package/presets/claude/go/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/go/hooks/examples/README.md +2 -0
- package/presets/claude/go/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/go/rules/README.md +1 -1
- package/presets/claude/go/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/go/settings.json +23 -0
- package/presets/claude/ios-swift/CLAUDE.md +3 -1
- package/presets/claude/ios-swift/REPO_AGENTS.md +1 -1
- package/presets/claude/ios-swift/hooks/README.md +6 -5
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/ios-swift/hooks/examples/README.md +2 -0
- package/presets/claude/ios-swift/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/ios-swift/rules/README.md +1 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/ios-swift/settings.json +23 -0
- package/presets/claude/java/CLAUDE.md +3 -1
- package/presets/claude/java/REPO_AGENTS.md +1 -1
- package/presets/claude/java/hooks/README.md +6 -5
- package/presets/claude/java/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/java/hooks/examples/README.md +2 -0
- package/presets/claude/java/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/java/rules/README.md +1 -1
- package/presets/claude/java/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/java/settings.json +23 -0
- package/presets/claude/mcp-ts/CLAUDE.md +3 -1
- package/presets/claude/mcp-ts/REPO_AGENTS.md +1 -1
- package/presets/claude/mcp-ts/hooks/README.md +8 -3
- package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/mcp-ts/hooks/examples/README.md +5 -0
- package/presets/claude/mcp-ts/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/mcp-ts/rules/README.md +1 -1
- package/presets/claude/mcp-ts/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/mcp-ts/settings.json +23 -0
- package/presets/claude/next/CLAUDE.md +3 -1
- package/presets/claude/next/REPO_AGENTS.md +1 -1
- package/presets/claude/next/hooks/README.md +10 -1
- package/presets/claude/next/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/next/hooks/examples/README.md +2 -0
- package/presets/claude/next/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/next/rules/README.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/next/settings.json +23 -0
- package/presets/claude/nuxt/CLAUDE.md +3 -1
- package/presets/claude/nuxt/REPO_AGENTS.md +1 -1
- package/presets/claude/nuxt/hooks/README.md +7 -4
- package/presets/claude/nuxt/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/nuxt/hooks/examples/README.md +2 -0
- package/presets/claude/nuxt/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/nuxt/rules/README.md +1 -1
- package/presets/claude/nuxt/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/nuxt/settings.json +23 -0
- package/presets/claude/php-hexagonal/CLAUDE.md +3 -1
- package/presets/claude/php-hexagonal/REPO_AGENTS.md +1 -1
- package/presets/claude/php-hexagonal/hooks/README.md +6 -5
- package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/php-hexagonal/hooks/examples/README.md +3 -1
- package/presets/claude/php-hexagonal/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/php-hexagonal/rules/README.md +1 -1
- package/presets/claude/php-hexagonal/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/php-hexagonal/settings.json +23 -0
- package/presets/claude/php-laravel/CLAUDE.md +6 -0
- package/presets/claude/php-laravel/REPO_AGENTS.md +1 -1
- package/presets/claude/php-laravel/hooks/README.md +6 -5
- package/presets/claude/php-laravel/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/php-laravel/hooks/examples/README.md +3 -1
- package/presets/claude/php-laravel/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/php-laravel/rules/README.md +1 -1
- package/presets/claude/php-laravel/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/php-laravel/settings.json +23 -0
- package/presets/claude/svelte/CLAUDE.md +3 -1
- package/presets/claude/svelte/REPO_AGENTS.md +1 -1
- package/presets/claude/svelte/hooks/README.md +7 -4
- package/presets/claude/svelte/hooks/chain-team-phases.sh +18 -0
- package/presets/claude/svelte/hooks/examples/README.md +2 -0
- package/presets/claude/svelte/hooks/guard-shell-command.sh +32 -9
- package/presets/claude/svelte/rules/README.md +1 -1
- package/presets/claude/svelte/rules/tooling-and-review/ai-local-overlay.md +0 -5
- package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +2 -2
- package/presets/claude/svelte/settings.json +23 -0
- package/presets/cursor/android-kotlin/REPO_AGENTS.md +1 -1
- package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/go/REPO_AGENTS.md +1 -1
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/ios-swift/REPO_AGENTS.md +1 -1
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/java/REPO_AGENTS.md +1 -1
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/mcp-ts/REPO_AGENTS.md +1 -1
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/next/REPO_AGENTS.md +1 -1
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/nuxt/REPO_AGENTS.md +1 -1
- package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/php-hexagonal/REPO_AGENTS.md +1 -1
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/php-laravel/REPO_AGENTS.md +1 -1
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +2 -2
- package/presets/cursor/svelte/REPO_AGENTS.md +1 -1
- package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +2 -2
- package/presets/mavis/README.md +2 -0
- package/presets/mavis/android-kotlin/MAVIS.md +10 -1
- package/presets/mavis/android-kotlin/REPO_AGENTS.md +1 -1
- package/presets/mavis/android-kotlin/adapter-map.json +1 -1
- package/presets/mavis/android-kotlin/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/go/MAVIS.md +10 -1
- package/presets/mavis/go/REPO_AGENTS.md +1 -1
- package/presets/mavis/go/adapter-map.json +1 -1
- package/presets/mavis/go/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/ios-swift/MAVIS.md +10 -1
- package/presets/mavis/ios-swift/REPO_AGENTS.md +1 -1
- package/presets/mavis/ios-swift/adapter-map.json +1 -1
- package/presets/mavis/ios-swift/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/java/MAVIS.md +10 -1
- package/presets/mavis/java/REPO_AGENTS.md +1 -1
- package/presets/mavis/java/adapter-map.json +1 -1
- package/presets/mavis/java/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/mcp-ts/MAVIS.md +10 -1
- package/presets/mavis/mcp-ts/REPO_AGENTS.md +1 -1
- package/presets/mavis/mcp-ts/adapter-map.json +1 -1
- package/presets/mavis/mcp-ts/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/next/MAVIS.md +10 -1
- package/presets/mavis/next/REPO_AGENTS.md +1 -1
- package/presets/mavis/next/adapter-map.json +1 -1
- package/presets/mavis/next/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/nuxt/MAVIS.md +10 -1
- package/presets/mavis/nuxt/REPO_AGENTS.md +1 -1
- package/presets/mavis/nuxt/adapter-map.json +1 -1
- package/presets/mavis/nuxt/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/php-hexagonal/MAVIS.md +10 -1
- package/presets/mavis/php-hexagonal/REPO_AGENTS.md +1 -1
- package/presets/mavis/php-hexagonal/adapter-map.json +1 -1
- package/presets/mavis/php-hexagonal/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/php-laravel/MAVIS.md +10 -1
- package/presets/mavis/php-laravel/REPO_AGENTS.md +1 -1
- package/presets/mavis/php-laravel/adapter-map.json +1 -1
- package/presets/mavis/php-laravel/rules/preset-pr-checklist.md +2 -2
- package/presets/mavis/platform-contract.json +4 -4
- package/presets/mavis/svelte/MAVIS.md +10 -1
- package/presets/mavis/svelte/REPO_AGENTS.md +1 -1
- package/presets/mavis/svelte/adapter-map.json +1 -1
- package/presets/mavis/svelte/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/README.md +1 -1
- package/presets/opencode/android-kotlin/OPENCODE.md +8 -1
- package/presets/opencode/android-kotlin/REPO_AGENTS.md +1 -1
- package/presets/opencode/android-kotlin/adapter-map.json +1 -1
- package/presets/opencode/android-kotlin/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/go/OPENCODE.md +8 -1
- package/presets/opencode/go/REPO_AGENTS.md +1 -1
- package/presets/opencode/go/adapter-map.json +1 -1
- package/presets/opencode/go/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/ios-swift/OPENCODE.md +8 -1
- package/presets/opencode/ios-swift/REPO_AGENTS.md +1 -1
- package/presets/opencode/ios-swift/adapter-map.json +1 -1
- package/presets/opencode/ios-swift/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/java/OPENCODE.md +8 -1
- package/presets/opencode/java/REPO_AGENTS.md +1 -1
- package/presets/opencode/java/adapter-map.json +1 -1
- package/presets/opencode/java/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/mcp-ts/OPENCODE.md +8 -1
- package/presets/opencode/mcp-ts/REPO_AGENTS.md +1 -1
- package/presets/opencode/mcp-ts/adapter-map.json +1 -1
- package/presets/opencode/mcp-ts/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/next/OPENCODE.md +8 -1
- package/presets/opencode/next/REPO_AGENTS.md +1 -1
- package/presets/opencode/next/adapter-map.json +1 -1
- package/presets/opencode/next/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/nuxt/OPENCODE.md +8 -1
- package/presets/opencode/nuxt/REPO_AGENTS.md +1 -1
- package/presets/opencode/nuxt/adapter-map.json +1 -1
- package/presets/opencode/nuxt/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/php-hexagonal/OPENCODE.md +8 -1
- package/presets/opencode/php-hexagonal/REPO_AGENTS.md +1 -1
- package/presets/opencode/php-hexagonal/adapter-map.json +1 -1
- package/presets/opencode/php-hexagonal/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/php-laravel/OPENCODE.md +8 -1
- package/presets/opencode/php-laravel/REPO_AGENTS.md +1 -1
- package/presets/opencode/php-laravel/adapter-map.json +1 -1
- package/presets/opencode/php-laravel/rules/preset-pr-checklist.md +2 -2
- package/presets/opencode/platform-contract.json +1 -1
- package/presets/opencode/svelte/OPENCODE.md +8 -1
- package/presets/opencode/svelte/REPO_AGENTS.md +1 -1
- package/presets/opencode/svelte/adapter-map.json +1 -1
- package/presets/opencode/svelte/rules/preset-pr-checklist.md +2 -2
- package/scripts/check-local-overlay.sh +40 -4
- package/scripts/check-mavis-local-overlay.mjs +23 -0
- package/scripts/check-mavis-platform-contract.mjs +5 -2
- package/scripts/check-opencode-local-overlay.mjs +19 -0
- package/scripts/check-opencode-platform-contract.mjs +5 -2
- package/scripts/check-preset-token-budget.sh +7 -0
- package/scripts/fixtures/cli-golden/claude/next.json +10 -10
- package/scripts/fixtures/cli-golden/cursor/next.json +2 -2
- package/scripts/fixtures/cli-golden/mavis/android-kotlin.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/go.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/ios-swift.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/java.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/mcp-ts.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/next.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/nuxt.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/php-hexagonal.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/php-laravel.json +3 -3
- package/scripts/fixtures/cli-golden/mavis/svelte.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/android-kotlin.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/go.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/ios-swift.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/java.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/mcp-ts.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/next.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/nuxt.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/php-hexagonal.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/php-laravel.json +3 -3
- package/scripts/fixtures/cli-golden/opencode/svelte.json +3 -3
- package/scripts/lib/generate-mavis-adapter.mjs +10 -1
- package/scripts/lib/generate-opencode-adapter.mjs +8 -1
- package/scripts/sync-claude-settings.mjs +25 -0
- package/scripts/sync-dogfood-claude.sh +62 -0
- package/scripts/test-mavis-orchestration.mjs +3 -2
|
@@ -69,4 +69,4 @@ A `.ai.local/` directory MAY exist at the repo root or at any nesting depth in m
|
|
|
69
69
|
|
|
70
70
|
Plain markdown rules under `.ai.local/rules/*.md` are read by the agent with higher priority than preset rules. Living gotchas live in `.ai.local/conventions.md`.
|
|
71
71
|
|
|
72
|
-
Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule
|
|
72
|
+
On every turn, probe `ls -la .ai.local`, apply `.ai.local/rules/*.md` and `.ai.local/conventions.md`, and acknowledge `Using .ai.local: <rule-name>`. Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule is always-on on Cursor and session-start on Claude (no `paths:`). Mavis and OpenCode have no native `alwaysApply`; this section plus the platform entry's essential-rules list is the reinforcement.
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
| `chain-team-phases.sh` | Pipeline chaining after subagent stop (`TEAM_ROOT=.ai.local/team`) |
|
|
6
6
|
| `guard-shell-command.sh` | Destructive git / package-manager guard; **allows** `xcodebuild` / `simctl` / `xcrun` |
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
No `hooks.json`. Default chain and shell guard are registered in `.claude/settings.json` (see **Shipped wiring**). Cookbook scripts in `hooks/examples/` stay unwired; keep stack-safe recipes (this preset: **ios-swift**).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Shipped wiring (Claude Code settings)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`.claude/settings.json` `hooks` (https://code.claude.com/docs/en/hooks) registers:
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- `PreToolUse` matcher `Bash` → `guard-shell-command.sh` (reads `tool_input.command`; emits `permissionDecision` `ask` or `allow`)
|
|
15
|
+
- `SubagentStop` → `chain-team-phases.sh` (kebab-case `agent_type` maps to `status: completed`; empty or non-kebab types are ignored; `stop_hook_active` does not recurse)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
There is no `hooks.json`. Cookbook scripts under `hooks/examples/` stay unwired. A hook crash is not a deny (Cursor `failClosed` has no Claude field); `ask` is the supported review decision.
|
|
@@ -21,6 +21,24 @@ try {
|
|
|
21
21
|
process.exit(0);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// Claude Code SubagentStop has hook_event_name / agent_type / stop_hook_active, not status.
|
|
25
|
+
// Kebab-case agent_type (preset roles) is the completed signal. Empty or non-kebab
|
|
26
|
+
// types (Claude internal agents) do not advance the pipeline. stop_hook_active
|
|
27
|
+
// means this hook already continued the turn — do not recurse.
|
|
28
|
+
// Manual pipes of {"status":"completed"} skip this block.
|
|
29
|
+
if (hookInput.hook_event_name === 'SubagentStop') {
|
|
30
|
+
if (hookInput.stop_hook_active === true) {
|
|
31
|
+
process.stdout.write('{}');
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
const agentType = typeof hookInput.agent_type === 'string' ? hookInput.agent_type : '';
|
|
35
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentType)) {
|
|
36
|
+
process.stdout.write('{}');
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (hookInput.status == null) hookInput.status = 'completed';
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
if (hookInput.status !== 'completed') {
|
|
25
43
|
process.stdout.write('{}');
|
|
26
44
|
process.exit(0);
|
|
@@ -10,6 +10,8 @@ Optional scripts under `hooks/examples/`. **Not** referenced from default `hooks
|
|
|
10
10
|
|
|
11
11
|
## Wiring (Claude Code)
|
|
12
12
|
|
|
13
|
+
Default `.claude/settings.json` already registers `guard-shell-command.sh` on `PreToolUse` (matcher `Bash`) and `chain-team-phases.sh` on `SubagentStop`. Cookbook scripts are not in that default set.
|
|
14
|
+
|
|
13
15
|
Claude Code has no preset `hooks.json`; hooks are registered in `.claude/settings.json` and fire on events such as `PreToolUse`, `PostToolUse`, and `Stop`.
|
|
14
16
|
|
|
15
17
|
1. Copy an example into `hooks/` (drop `.example` suffix), e.g. `cp hooks/examples/secret-guard.example.sh hooks/secret-guard.sh`.
|
|
@@ -19,20 +19,43 @@ try {
|
|
|
19
19
|
process.exit(0);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const claudePreTool = event.hook_event_name === 'PreToolUse';
|
|
23
|
+
const command = String(
|
|
24
|
+
event.command
|
|
25
|
+
|| (event.input && event.input.command)
|
|
26
|
+
|| (event.tool_input && event.tool_input.command)
|
|
27
|
+
|| '',
|
|
28
|
+
);
|
|
27
29
|
|
|
28
|
-
function out(permission, userMessage
|
|
30
|
+
function out(permission, userMessage) {
|
|
31
|
+
if (claudePreTool) {
|
|
32
|
+
const decision = permission === 'ask' || permission === 'deny' ? permission : 'allow';
|
|
33
|
+
const hookSpecificOutput = {
|
|
34
|
+
hookEventName: 'PreToolUse',
|
|
35
|
+
permissionDecision: decision,
|
|
36
|
+
};
|
|
37
|
+
if (userMessage && decision !== 'allow') {
|
|
38
|
+
hookSpecificOutput.permissionDecisionReason = userMessage;
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput }));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!userMessage) {
|
|
44
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
29
47
|
process.stdout.write(JSON.stringify({
|
|
30
48
|
permission,
|
|
31
49
|
user_message: userMessage,
|
|
32
|
-
agent_message:
|
|
50
|
+
agent_message: userMessage,
|
|
33
51
|
}));
|
|
34
52
|
}
|
|
35
53
|
|
|
54
|
+
if (!command.trim()) {
|
|
55
|
+
out('allow');
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
|
|
37
60
|
if (dangerousGit.test(command)) {
|
|
38
61
|
out(
|
|
@@ -61,7 +84,7 @@ if (!expected && fs.existsSync('package.json')) {
|
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
if (!expected) {
|
|
64
|
-
|
|
87
|
+
out('allow');
|
|
65
88
|
process.exit(0);
|
|
66
89
|
}
|
|
67
90
|
|
|
@@ -75,5 +98,5 @@ if (used && used !== expected) {
|
|
|
75
98
|
process.exit(0);
|
|
76
99
|
}
|
|
77
100
|
|
|
78
|
-
|
|
101
|
+
out('allow');
|
|
79
102
|
NODE
|
|
@@ -13,7 +13,7 @@ In Claude Code all `.md` files under `rules/` are **discovered recursively**. Bo
|
|
|
13
13
|
|
|
14
14
|
## Loading budget
|
|
15
15
|
|
|
16
|
-
- **Session-start (no `paths:`):** 3–5 — `ios-app-core`, `boundaries`, `code-quality` (≤200 body lines total)
|
|
16
|
+
- **Session-start (no `paths:`):** 3–5 — `ios-app-core`, `boundaries`, `code-quality` (≤200 body lines total), `ai-local-overlay`
|
|
17
17
|
- **Everything else** — with `paths:` (commands/team/agents and/or Feature/Swift globs)
|
|
18
18
|
- **Soft twin depth:** domain rules ≥15 body lines; thin aliases (`agent-team-intake`, `technical-retro`) may be shorter (as in next)
|
|
19
19
|
|
|
@@ -30,7 +30,7 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
30
30
|
- [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
|
|
31
31
|
- [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
|
|
32
32
|
- [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
|
|
33
|
-
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`
|
|
33
|
+
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, and `sync-dogfood-opencode.sh` when those platforms changed, or document an intentional skip, when maintaining this monorepo
|
|
34
34
|
- [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
|
|
35
35
|
|
|
36
36
|
## Pointers
|
|
@@ -40,6 +40,6 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
40
40
|
- Budget: `preset-token-budget`
|
|
41
41
|
- Leakage: `preset-no-cross-stack-leakage`
|
|
42
42
|
- Validation: stack `agents/build-verifier.md` → preset-structure section
|
|
43
|
-
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
43
|
+
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
44
44
|
- Drift script: `packages/ai-rules/scripts/check-shared-core-drift.sh`
|
|
45
45
|
- Orchestrator: when editing presets, load this checklist + twin-sync
|
|
@@ -6,5 +6,28 @@
|
|
|
6
6
|
"Bash(git push *)"
|
|
7
7
|
],
|
|
8
8
|
"ask": []
|
|
9
|
+
},
|
|
10
|
+
"hooks": {
|
|
11
|
+
"PreToolUse": [
|
|
12
|
+
{
|
|
13
|
+
"matcher": "Bash",
|
|
14
|
+
"hooks": [
|
|
15
|
+
{
|
|
16
|
+
"type": "command",
|
|
17
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-shell-command.sh"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"SubagentStop": [
|
|
23
|
+
{
|
|
24
|
+
"hooks": [
|
|
25
|
+
{
|
|
26
|
+
"type": "command",
|
|
27
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/chain-team-phases.sh"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
]
|
|
9
32
|
}
|
|
10
33
|
}
|
|
@@ -4,7 +4,8 @@ Preset for Java backends using ports & adapters (Spring Boot default).
|
|
|
4
4
|
|
|
5
5
|
**Repo-root agents:** see [`AGENTS.md`](../../AGENTS.md) at the project root.
|
|
6
6
|
|
|
7
|
-
- Session-start: `java-app-core`, `architecture/boundaries`, `code-quality` (3–5).
|
|
7
|
+
- Session-start: `java-app-core`, `architecture/boundaries`, `code-quality`, `ai-local-overlay` (3–5).
|
|
8
|
+
- **Local overlay (session-start):** `ai-local-overlay` has no `paths:` and counts in the 3–5 budget. On every turn, probe `ls -la .ai.local`, apply `.ai.local/rules/*.md` and `.ai.local/conventions.md`, and acknowledge `Using .ai.local: <rule-name>`. Guide: `docs/LOCAL-OVERLAY.md`.
|
|
8
9
|
- Delivery: `architecture/feature-delivery.md` + skill `feature-delivery`.
|
|
9
10
|
- After Java edits: `tooling-and-review/post-change-test.md` (+ `java-tooling`).
|
|
10
11
|
- Integration tests: agents `integration-test-*` + skill `integration-testing` (never Playwright/XCUITest).
|
|
@@ -39,3 +40,4 @@ Init: `npx @bonesofspring/ai-rules init claude --preset java` (also copies `REPO
|
|
|
39
40
|
`git commit/push deny`; JS stacks also `npx jest* deny` and `npm/npx/pnpm/bun`
|
|
40
41
|
ask). Re-init overwrites the file (consumer can edit afterwards); mirror
|
|
41
42
|
with root `AGENTS.md` if you change the harness.
|
|
43
|
+
- **Pipeline hooks:** `.claude/settings.json` `hooks` wires `guard-shell-command.sh` (`PreToolUse` / `Bash`, `permissionDecision` `ask` or `allow`) and `chain-team-phases.sh` (`SubagentStop` for kebab-case `agent_type`). See `hooks/README.md`. No `hooks.json`.
|
|
@@ -69,4 +69,4 @@ A `.ai.local/` directory MAY exist at the repo root or at any nesting depth in m
|
|
|
69
69
|
|
|
70
70
|
Plain markdown rules under `.ai.local/rules/*.md` are read by the agent with higher priority than preset rules. Living gotchas live in `.ai.local/conventions.md`.
|
|
71
71
|
|
|
72
|
-
Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule
|
|
72
|
+
On every turn, probe `ls -la .ai.local`, apply `.ai.local/rules/*.md` and `.ai.local/conventions.md`, and acknowledge `Using .ai.local: <rule-name>`. Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule is always-on on Cursor and session-start on Claude (no `paths:`). Mavis and OpenCode have no native `alwaysApply`; this section plus the platform entry's essential-rules list is the reinforcement.
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
| `chain-team-phases.sh` | Pipeline chaining after subagent stop (`TEAM_ROOT=.ai.local/team`) |
|
|
6
6
|
| `guard-shell-command.sh` | Destructive git / JS package-manager guard; **allows** `mvn test / ./gradlew test` / `compiler/IDE inspections` / `configured static analysis` / `repo static analysis` |
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
No `hooks.json`. Default chain and shell guard are registered in `.claude/settings.json` (see **Shipped wiring**). Cookbook scripts in `hooks/examples/` stay unwired; keep stack-safe recipes (this preset: **java**).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Shipped wiring (Claude Code settings)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`.claude/settings.json` `hooks` (https://code.claude.com/docs/en/hooks) registers:
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- `PreToolUse` matcher `Bash` → `guard-shell-command.sh` (reads `tool_input.command`; emits `permissionDecision` `ask` or `allow`)
|
|
15
|
+
- `SubagentStop` → `chain-team-phases.sh` (kebab-case `agent_type` maps to `status: completed`; empty or non-kebab types are ignored; `stop_hook_active` does not recurse)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
There is no `hooks.json`. Cookbook scripts under `hooks/examples/` stay unwired. A hook crash is not a deny (Cursor `failClosed` has no Claude field); `ask` is the supported review decision.
|
|
@@ -22,6 +22,24 @@ try {
|
|
|
22
22
|
process.exit(0);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// Claude Code SubagentStop has hook_event_name / agent_type / stop_hook_active, not status.
|
|
26
|
+
// Kebab-case agent_type (preset roles) is the completed signal. Empty or non-kebab
|
|
27
|
+
// types (Claude internal agents) do not advance the pipeline. stop_hook_active
|
|
28
|
+
// means this hook already continued the turn — do not recurse.
|
|
29
|
+
// Manual pipes of {"status":"completed"} skip this block.
|
|
30
|
+
if (hookInput.hook_event_name === 'SubagentStop') {
|
|
31
|
+
if (hookInput.stop_hook_active === true) {
|
|
32
|
+
process.stdout.write('{}');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
const agentType = typeof hookInput.agent_type === 'string' ? hookInput.agent_type : '';
|
|
36
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentType)) {
|
|
37
|
+
process.stdout.write('{}');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
if (hookInput.status == null) hookInput.status = 'completed';
|
|
41
|
+
}
|
|
42
|
+
|
|
25
43
|
if (hookInput.status !== 'completed') {
|
|
26
44
|
process.stdout.write('{}');
|
|
27
45
|
process.exit(0);
|
|
@@ -10,6 +10,8 @@ Optional scripts under `hooks/examples/`. **Not** referenced from default `hooks
|
|
|
10
10
|
|
|
11
11
|
## Wiring (Claude Code)
|
|
12
12
|
|
|
13
|
+
Default `.claude/settings.json` already registers `guard-shell-command.sh` on `PreToolUse` (matcher `Bash`) and `chain-team-phases.sh` on `SubagentStop`. Cookbook scripts are not in that default set.
|
|
14
|
+
|
|
13
15
|
Claude Code has no preset `hooks.json`; hooks are registered in `.claude/settings.json` and fire on events such as `PreToolUse`, `PostToolUse`, and `Stop`.
|
|
14
16
|
|
|
15
17
|
1. Copy an example into `hooks/` (drop `.example` suffix), e.g. `cp hooks/examples/secret-guard.example.sh hooks/secret-guard.sh`.
|
|
@@ -20,20 +20,43 @@ try {
|
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const claudePreTool = event.hook_event_name === 'PreToolUse';
|
|
24
|
+
const command = String(
|
|
25
|
+
event.command
|
|
26
|
+
|| (event.input && event.input.command)
|
|
27
|
+
|| (event.tool_input && event.tool_input.command)
|
|
28
|
+
|| '',
|
|
29
|
+
);
|
|
28
30
|
|
|
29
|
-
function out(permission, userMessage
|
|
31
|
+
function out(permission, userMessage) {
|
|
32
|
+
if (claudePreTool) {
|
|
33
|
+
const decision = permission === 'ask' || permission === 'deny' ? permission : 'allow';
|
|
34
|
+
const hookSpecificOutput = {
|
|
35
|
+
hookEventName: 'PreToolUse',
|
|
36
|
+
permissionDecision: decision,
|
|
37
|
+
};
|
|
38
|
+
if (userMessage && decision !== 'allow') {
|
|
39
|
+
hookSpecificOutput.permissionDecisionReason = userMessage;
|
|
40
|
+
}
|
|
41
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput }));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!userMessage) {
|
|
45
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
30
48
|
process.stdout.write(JSON.stringify({
|
|
31
49
|
permission,
|
|
32
50
|
user_message: userMessage,
|
|
33
|
-
agent_message:
|
|
51
|
+
agent_message: userMessage,
|
|
34
52
|
}));
|
|
35
53
|
}
|
|
36
54
|
|
|
55
|
+
if (!command.trim()) {
|
|
56
|
+
out('allow');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
37
60
|
const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
|
|
38
61
|
if (dangerousGit.test(command)) {
|
|
39
62
|
out(
|
|
@@ -62,7 +85,7 @@ if (!expected && fs.existsSync('package.json')) {
|
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
if (!expected) {
|
|
65
|
-
|
|
88
|
+
out('allow');
|
|
66
89
|
process.exit(0);
|
|
67
90
|
}
|
|
68
91
|
|
|
@@ -76,5 +99,5 @@ if (used && used !== expected) {
|
|
|
76
99
|
process.exit(0);
|
|
77
100
|
}
|
|
78
101
|
|
|
79
|
-
|
|
102
|
+
out('allow');
|
|
80
103
|
NODE
|
|
@@ -12,7 +12,7 @@ Claude topic `.md` files are **derived** from Cursor SoT `presets/cursor/java/ru
|
|
|
12
12
|
|
|
13
13
|
## Loading budget
|
|
14
14
|
|
|
15
|
-
- **Session-start (no `paths:`):** 3–5 — `java-app-core`, `boundaries`, `code-quality`
|
|
15
|
+
- **Session-start (no `paths:`):** 3–5 — `java-app-core`, `boundaries`, `code-quality`, `ai-local-overlay`
|
|
16
16
|
- All others — with `paths:`
|
|
17
17
|
- **Twin depth:** domain rules target ≥15 body lines; thin aliases: `agent-team-intake`, `technical-retro`; **documented stub** (v1): `api-grpc`; `messaging-adapters` is **full** — see Cursor `presets/cursor/java/rules/README.md` Catalog (Depth column)
|
|
18
18
|
|
|
@@ -30,7 +30,7 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
30
30
|
- [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
|
|
31
31
|
- [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
|
|
32
32
|
- [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
|
|
33
|
-
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`
|
|
33
|
+
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, and `sync-dogfood-opencode.sh` when those platforms changed, or document an intentional skip, when maintaining this monorepo
|
|
34
34
|
- [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
|
|
35
35
|
|
|
36
36
|
## Pointers
|
|
@@ -40,6 +40,6 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
40
40
|
- Budget: `preset-token-budget`
|
|
41
41
|
- Leakage: `preset-no-cross-stack-leakage`
|
|
42
42
|
- Validation: stack `agents/build-verifier.md` → preset-structure section
|
|
43
|
-
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
43
|
+
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
44
44
|
- Drift script: `packages/ai-rules/scripts/check-shared-core-drift.sh`
|
|
45
45
|
- Orchestrator: when editing presets, load this checklist + twin-sync
|
|
@@ -6,5 +6,28 @@
|
|
|
6
6
|
"Bash(git push *)"
|
|
7
7
|
],
|
|
8
8
|
"ask": []
|
|
9
|
+
},
|
|
10
|
+
"hooks": {
|
|
11
|
+
"PreToolUse": [
|
|
12
|
+
{
|
|
13
|
+
"matcher": "Bash",
|
|
14
|
+
"hooks": [
|
|
15
|
+
{
|
|
16
|
+
"type": "command",
|
|
17
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-shell-command.sh"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"SubagentStop": [
|
|
23
|
+
{
|
|
24
|
+
"hooks": [
|
|
25
|
+
{
|
|
26
|
+
"type": "command",
|
|
27
|
+
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/chain-team-phases.sh"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
]
|
|
9
32
|
}
|
|
10
33
|
}
|
|
@@ -4,7 +4,8 @@ Preset for authoring TypeScript MCP servers with `@modelcontextprotocol/sdk`.
|
|
|
4
4
|
|
|
5
5
|
**Repo-root agents:** see [`AGENTS.md`](../../AGENTS.md) at the project root.
|
|
6
6
|
|
|
7
|
-
- Session-start: `mcp-ts-app-core`, `architecture/mcp-server-boundaries`, `code-quality` (3–5).
|
|
7
|
+
- Session-start: `mcp-ts-app-core`, `architecture/mcp-server-boundaries`, `code-quality`, `ai-local-overlay` (3–5).
|
|
8
|
+
- **Local overlay (session-start):** `ai-local-overlay` has no `paths:` and counts in the 3–5 budget. On every turn, probe `ls -la .ai.local`, apply `.ai.local/rules/*.md` and `.ai.local/conventions.md`, and acknowledge `Using .ai.local: <rule-name>`. Guide: `docs/LOCAL-OVERLAY.md`.
|
|
8
9
|
- Delivery: `architecture/feature-delivery.md` + skill `feature-delivery`.
|
|
9
10
|
- After TS edits: `tooling-and-review/post-change-test.md`.
|
|
10
11
|
- Contract checks: `mcp-contract-testing` rule (Phase 1: feature-developer owns verification).
|
|
@@ -23,3 +24,4 @@ Init: `npx @bonesofspring/ai-rules init claude --preset mcp-ts` (also copies `RE
|
|
|
23
24
|
`git commit/push deny`; JS stacks also `npx jest* deny` and `npm/npx/pnpm/bun`
|
|
24
25
|
ask). Re-init overwrites the file (consumer can edit afterwards); mirror
|
|
25
26
|
with root `AGENTS.md` if you change the harness.
|
|
27
|
+
- **Pipeline hooks:** `.claude/settings.json` `hooks` wires `guard-shell-command.sh` (`PreToolUse` / `Bash`, `permissionDecision` `ask` or `allow`) and `chain-team-phases.sh` (`SubagentStop` for kebab-case `agent_type`). See `hooks/README.md`. No `hooks.json`.
|
|
@@ -72,4 +72,4 @@ A `.ai.local/` directory MAY exist at the repo root or at any nesting depth in m
|
|
|
72
72
|
|
|
73
73
|
Plain markdown rules under `.ai.local/rules/*.md` are read by the agent with higher priority than preset rules. Living gotchas live in `.ai.local/conventions.md`.
|
|
74
74
|
|
|
75
|
-
Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule
|
|
75
|
+
On every turn, probe `ls -la .ai.local`, apply `.ai.local/rules/*.md` and `.ai.local/conventions.md`, and acknowledge `Using .ai.local: <rule-name>`. Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package. The `ai-local-overlay` rule is always-on on Cursor and session-start on Claude (no `paths:`). Mavis and OpenCode have no native `alwaysApply`; this section plus the platform entry's essential-rules list is the reinforcement.
|
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
| `guard-shell-command.sh` | Destructive git / JS package-manager mismatch; allows npm/npx/node/tsc |
|
|
6
6
|
| `chain-team-phases.sh` | Auto-chain pipeline steps on `subagentStop` (Phase 1: build-verifier, security-reviewer; **no** `contract-test-*`) |
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
No `hooks.json`. Default chain and shell guard are registered in `.claude/settings.json` (see **Shipped wiring**). Cookbook scripts in `hooks/examples/` stay unwired.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Shipped wiring (Claude Code settings)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`.claude/settings.json` `hooks` (https://code.claude.com/docs/en/hooks) registers:
|
|
13
|
+
|
|
14
|
+
- `PreToolUse` matcher `Bash` → `guard-shell-command.sh` (reads `tool_input.command`; emits `permissionDecision` `ask` or `allow`)
|
|
15
|
+
- `SubagentStop` → `chain-team-phases.sh` (kebab-case `agent_type` maps to `status: completed`; empty or non-kebab types are ignored; `stop_hook_active` does not recurse)
|
|
16
|
+
|
|
17
|
+
There is no `hooks.json`. Cookbook scripts under `hooks/examples/` stay unwired. A hook crash is not a deny (Cursor `failClosed` has no Claude field); `ask` is the supported review decision.
|
|
@@ -23,6 +23,24 @@ try {
|
|
|
23
23
|
process.exit(0);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// Claude Code SubagentStop has hook_event_name / agent_type / stop_hook_active, not status.
|
|
27
|
+
// Kebab-case agent_type (preset roles) is the completed signal. Empty or non-kebab
|
|
28
|
+
// types (Claude internal agents) do not advance the pipeline. stop_hook_active
|
|
29
|
+
// means this hook already continued the turn — do not recurse.
|
|
30
|
+
// Manual pipes of {"status":"completed"} skip this block.
|
|
31
|
+
if (hookInput.hook_event_name === 'SubagentStop') {
|
|
32
|
+
if (hookInput.stop_hook_active === true) {
|
|
33
|
+
process.stdout.write('{}');
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
const agentType = typeof hookInput.agent_type === 'string' ? hookInput.agent_type : '';
|
|
37
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentType)) {
|
|
38
|
+
process.stdout.write('{}');
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
if (hookInput.status == null) hookInput.status = 'completed';
|
|
42
|
+
}
|
|
43
|
+
|
|
26
44
|
if (hookInput.status !== 'completed') {
|
|
27
45
|
process.stdout.write('{}');
|
|
28
46
|
process.exit(0);
|
|
@@ -9,3 +9,8 @@ Optional cookbook scripts — **not** wired into default `hooks.json`.
|
|
|
9
9
|
| `test-on-save.example.sh` | Run scoped tests after edits |
|
|
10
10
|
|
|
11
11
|
Adapt commands to the repository package manager (`mcp-ts-tooling`).
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Wiring (Claude Code)
|
|
15
|
+
|
|
16
|
+
Default `.claude/settings.json` already registers `guard-shell-command.sh` on `PreToolUse` (matcher `Bash`) and `chain-team-phases.sh` on `SubagentStop`. The cookbook scripts above are not in that default set. There is no `hooks.json`.
|
|
@@ -19,20 +19,43 @@ try {
|
|
|
19
19
|
process.exit(0);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const claudePreTool = event.hook_event_name === 'PreToolUse';
|
|
23
|
+
const command = String(
|
|
24
|
+
event.command
|
|
25
|
+
|| (event.input && event.input.command)
|
|
26
|
+
|| (event.tool_input && event.tool_input.command)
|
|
27
|
+
|| '',
|
|
28
|
+
);
|
|
27
29
|
|
|
28
|
-
function out(permission, userMessage
|
|
30
|
+
function out(permission, userMessage) {
|
|
31
|
+
if (claudePreTool) {
|
|
32
|
+
const decision = permission === 'ask' || permission === 'deny' ? permission : 'allow';
|
|
33
|
+
const hookSpecificOutput = {
|
|
34
|
+
hookEventName: 'PreToolUse',
|
|
35
|
+
permissionDecision: decision,
|
|
36
|
+
};
|
|
37
|
+
if (userMessage && decision !== 'allow') {
|
|
38
|
+
hookSpecificOutput.permissionDecisionReason = userMessage;
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput }));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!userMessage) {
|
|
44
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
29
47
|
process.stdout.write(JSON.stringify({
|
|
30
48
|
permission,
|
|
31
49
|
user_message: userMessage,
|
|
32
|
-
agent_message:
|
|
50
|
+
agent_message: userMessage,
|
|
33
51
|
}));
|
|
34
52
|
}
|
|
35
53
|
|
|
54
|
+
if (!command.trim()) {
|
|
55
|
+
out('allow');
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
|
|
37
60
|
if (dangerousGit.test(command)) {
|
|
38
61
|
out(
|
|
@@ -61,7 +84,7 @@ if (!expected && fs.existsSync('package.json')) {
|
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
if (!expected) {
|
|
64
|
-
|
|
87
|
+
out('allow');
|
|
65
88
|
process.exit(0);
|
|
66
89
|
}
|
|
67
90
|
|
|
@@ -75,5 +98,5 @@ if (used && used !== expected) {
|
|
|
75
98
|
process.exit(0);
|
|
76
99
|
}
|
|
77
100
|
|
|
78
|
-
|
|
101
|
+
out('allow');
|
|
79
102
|
NODE
|
|
@@ -12,7 +12,7 @@ Claude topic `.md` files are **derived** from Cursor SoT `presets/cursor/mcp-ts/
|
|
|
12
12
|
|
|
13
13
|
## Loading budget
|
|
14
14
|
|
|
15
|
-
- **Session-start (no `paths:`):** 3–5 — `mcp-ts-app-core`, `mcp-server-boundaries`, `code-quality`
|
|
15
|
+
- **Session-start (no `paths:`):** 3–5 — `mcp-ts-app-core`, `mcp-server-boundaries`, `code-quality`, `ai-local-overlay`
|
|
16
16
|
- All others — with `paths:`
|
|
17
17
|
- **Twin depth:** domain rules target ≥15 body lines; thin aliases: `agent-team-intake`, `technical-retro`
|
|
18
18
|
|
|
@@ -30,7 +30,7 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
30
30
|
- [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
|
|
31
31
|
- [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
|
|
32
32
|
- [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
|
|
33
|
-
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`
|
|
33
|
+
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, and `sync-dogfood-opencode.sh` when those platforms changed, or document an intentional skip, when maintaining this monorepo
|
|
34
34
|
- [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
|
|
35
35
|
|
|
36
36
|
## Pointers
|
|
@@ -40,6 +40,6 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
40
40
|
- Budget: `preset-token-budget`
|
|
41
41
|
- Leakage: `preset-no-cross-stack-leakage`
|
|
42
42
|
- Validation: stack `agents/build-verifier.md` → preset-structure section
|
|
43
|
-
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
43
|
+
- Dogfood scripts: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`, `sync-dogfood-claude.sh`, `sync-dogfood-mavis.sh`, `sync-dogfood-opencode.sh`
|
|
44
44
|
- Drift script: `packages/ai-rules/scripts/check-shared-core-drift.sh`
|
|
45
45
|
- Orchestrator: when editing presets, load this checklist + twin-sync
|