Skip to content

Commit c4666e3

Browse files
Update Rules and hooks on the monitor workspace
1 parent 1f3d930 commit c4666e3

27 files changed

Lines changed: 1471 additions & 108 deletions

.cursor/hooks/README.md

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,45 @@
1-
# Cursor hooks (HPCPerfStats)
1+
# Cursor hooks (HPCPerfStats + monitor workspace)
22

33
Project hooks for Cursor Agent. Cursor loads `.cursor/hooks.json` from the **workspace root**.
44

5-
This workspace opens at the parent folder (contains `.venv/`). Symlinks at `<workspace>/.cursor/` point here:
5+
## Symlink setup
6+
7+
### Monitor-focused workspace (`.cursor/rules``monitor/cursor-rules/`)
8+
9+
From workspace root (contains `.venv/` and `HPCPerfStats/`):
610

711
```bash
8-
# From workspace root (one-time, if symlinks are missing)
9-
ln -sf ../HPCPerfStats/.cursor/hooks.json .cursor/hooks.json
10-
ln -sf ../HPCPerfStats/.cursor/hooks .cursor/hooks
12+
ln -sf HPCPerfStats/.cursor/hooks.json .cursor/hooks.json
13+
ln -sf HPCPerfStats/.cursor/hooks .cursor/hooks
1114
```
1215

16+
### Full-stack workspace (`.cursor/rules``hpcperfstats/cursor-rules/`)
17+
18+
From workspace root:
19+
20+
```bash
21+
ln -sf HPCPerfStats/.cursor/hooks.json .cursor/hooks.json
22+
ln -sf HPCPerfStats/.cursor/hooks .cursor/hooks
23+
```
24+
25+
Both layouts share the **same** hook scripts under `HPCPerfStats/.cursor/hooks/`.
26+
27+
## Profile detection
28+
29+
Hooks auto-detect workspace profile from the **`.cursor/rules` symlink target**:
30+
31+
| Symlink target | Profile | Rules dir label |
32+
|----------------|---------|-----------------|
33+
| `…/monitor/cursor-rules` | `monitor` | `HPCPerfStats/monitor/cursor-rules` |
34+
| `…/hpcperfstats/cursor-rules` | `hpcperfstats` | `hpcperfstats/cursor-rules` |
35+
36+
`hook_task_router.py` merges **`MONITOR_ROUTER_ENTRIES`** and **`HPCPERFSTATS_ROUTER_ENTRIES`** so authorized cross-edits can trigger rules from both trees.
37+
38+
Plan template paths accepted for Read verification:
39+
40+
- `HPCPerfStats/monitor/docs/plans/PLAN_TEMPLATE.md` (monitor workspace)
41+
- `HPCPerfStats/docs/plans/PLAN_TEMPLATE.md` (full-stack workspace)
42+
1343
## Hooks
1444

1545
| Event | Script | Behavior |
@@ -22,14 +52,24 @@ ln -sf ../HPCPerfStats/.cursor/hooks .cursor/hooks
2252

2353
1. Cursor **Settings → Hooks** tab should list both hooks after save/reload.
2454
2. Hooks output channel shows stdin/stdout when hooks fire.
25-
3. Manual smoke test:
55+
3. Unit tests: `cd HPCPerfStats && ../.venv/bin/python3 -m pytest hpcperfstats/tests/test_cursor_hooks.py -q`
56+
4. Manual smoke test:
2657

2758
```bash
28-
echo '{"status":"completed","loop_count":0,"transcript_path":"/path/to/transcript.jsonl"}' | \
59+
echo '{"status":"completed","loop_count":0,"transcript_path":"/path/to/transcript.jsonl","workspace_roots":["/path/to/workspace"]}' | \
2960
python3 HPCPerfStats/.cursor/hooks/check-close-gate.py
3061
```
3162

3263
## Requirements
3364

34-
- `python3` on `PATH` (macOS default)
65+
- `python3` on `PATH`
3566
- Trusted workspace (project hooks do not run in untrusted workspaces)
67+
68+
## Dual registration
69+
70+
New domain rules must appear in **both**:
71+
72+
1. Profile **`agent-discipline-core.mdc`** task router table
73+
2. **`hook_task_router.py`**`MONITOR_ROUTER_ENTRIES` or `HPCPERFSTATS_ROUTER_ENTRIES`
74+
75+
See monitor **`RULES_README.md`** or hpcperfstats **`RULES_README.md`** for always-on caps.

.cursor/hooks/check-close-gate.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
load_json_stdin,
1818
looks_like_task_close,
1919
parse_transcript_lines,
20+
profile_rules_dir_label,
2021
turn_had_closeable_work,
2122
turn_had_create_plan,
2223
turn_had_edits,
@@ -40,6 +41,9 @@ def main() -> int:
4041
emit_json({})
4142
return 0
4243

44+
workspace_roots = payload.get("workspace_roots") or []
45+
rules_dir = profile_rules_dir_label(workspace_roots=workspace_roots)
46+
4347
rows = parse_transcript_lines(transcript_path)
4448
turn_rows = last_turn_rows(rows)
4549
had_edits = turn_had_edits(turn_rows)
@@ -66,18 +70,19 @@ def main() -> int:
6670
if had_plan:
6771
plan_extra = (
6872
"\nPlan turns also require CreatePlan body sections per "
69-
"docs/plans/PLAN_TEMPLATE.md (Problem and facts, Approach, Testing, "
70-
"Implementation, Cursor rules, Final code review, post-implementation-review "
71-
"todo) and Read of plan-creation-contract.mdc + PLAN_TEMPLATE.md before "
72-
"CreatePlan.\n"
73+
f"{rules_dir}/../docs/plans/PLAN_TEMPLATE.md or "
74+
"HPCPerfStats/docs/plans/PLAN_TEMPLATE.md (Problem and facts, Approach, "
75+
"Testing, Implementation, Cursor rules, Final code review, "
76+
"post-implementation-review todo) and Read of plan-creation-contract.mdc + "
77+
"PLAN_TEMPLATE.md before CreatePlan.\n"
7378
)
7479
followup = (
7580
"Close gate incomplete (Cursor stop hook). This turn used %s but the "
7681
"final assistant message is missing required sections or listed rules were "
7782
"not Read via the Read tool.%s\n\n"
7883
"Add in order:\n"
7984
"1. ## Agent rule dispatch — list every triggered "
80-
"hpcperfstats/cursor-rules/*.mdc you Read (or N/A only when work did not "
85+
f"{rules_dir}/*.mdc you Read (or N/A only when work did not "
8186
"trigger domain rules). Each listed domain rule needs a Read tool call on "
8287
"that .mdc path BEFORE the first Write/StrReplace/CreatePlan in this turn. "
8388
"Auto-triggered rules from edited or plan-referenced paths must appear in "

.cursor/hooks/check-edit-triggered-rules.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
parse_transcript_lines,
2222
paths_from_plan_markdown,
2323
plan_template_read_issues,
24+
profile_rules_dir_label,
2425
)
2526
from hook_task_router import triggered_rules_for_paths # noqa: E402
2627

@@ -107,16 +108,20 @@ def main() -> int:
107108
emit_json({})
108109
return 0
109110

111+
rules_dir = profile_rules_dir_label(
112+
workspace_roots=payload.get("workspace_roots") or [],
113+
)
110114
action = "CreatePlan" if tool_name == "CreatePlan" else "this edit"
111115
emit_json(
112116
{
113117
"additional_context": (
114118
"RULE DISPATCH (pre-close): %s triggers domain or plan-authoring "
115119
f"rules that must be Read before further work. Issues: "
116120
f"{', '.join(issues)}. "
117-
"Use the Read tool on each listed hpcperfstats/cursor-rules/*.mdc "
118-
"and docs/plans/PLAN_TEMPLATE.md for plan turns, then list them "
119-
"under ## Agent rule dispatch at close."
121+
f"Use the Read tool on each listed {rules_dir}/*.mdc "
122+
"and the workspace PLAN_TEMPLATE.md "
123+
"(HPCPerfStats/monitor/docs/plans/ or HPCPerfStats/docs/plans/) "
124+
"for plan turns, then list them under ## Agent rule dispatch at close."
120125
)
121126
% action,
122127
},

.cursor/hooks/check-new-rule-router.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ def main() -> int:
7777
f"MANDATORY (agent-discipline-core.mdc): new/updated rule `{basename}` "
7878
f"is not fully dual-registered. Missing: {', '.join(missing)}. "
7979
"In the same task, add a row to `agent-discipline-core.mdc` "
80-
"(trigger paths → Read this rule), a matching `ROUTER_ENTRIES` row in "
81-
"`.cursor/hooks/hook_task_router.py`, and a one-line note in "
80+
"(trigger paths → Read this rule), a matching row in "
81+
"`.cursor/hooks/hook_task_router.py` (`MONITOR_ROUTER_ENTRIES` or "
82+
"`HPCPERFSTATS_ROUTER_ENTRIES`), and a one-line note in "
8283
"`RULES_README.md` if policy changes. Verify both routers in "
8384
"Final code review before close."
8485
),

0 commit comments

Comments
 (0)