claude-dev-env 2.22.0 → 2.23.0
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/.agents/skills/source-command-sr-loop/SKILL.md +10 -0
- package/.agents/skills/team-advisor/SKILL.md +2 -0
- package/AGENTS.md +2 -0
- package/_shared/advisor/advisor-protocol.md +1 -0
- package/_shared/advisor/reference/sol-rung.md +2 -2
- package/_shared/advisor/reference/third-party-bind.md +12 -0
- package/_shared/advisor/scripts/codex_sol_advisor.py +16 -4
- package/_shared/advisor/scripts/config/advisor_scripts_constants/sol_advisor_constants.py +4 -0
- package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +4 -5
- package/commands/sr-loop.md +10 -0
- package/docs/codex-compatibility.md +28 -0
- package/hooks/hooks.json +12 -0
- package/hooks/hooks_constants/AGENTS.md +1 -0
- package/hooks/hooks_constants/style_reminder_prompt_constants.py +9 -0
- package/hooks/session/AGENTS.md +3 -1
- package/hooks/session/style_reminder_prompt.py +41 -0
- package/hooks/session/test_style_reminder_prompt.py +32 -0
- package/package.json +1 -1
- package/rules/AGENTS.md +1 -0
- package/rules/few-words.md +3 -0
|
@@ -13,6 +13,13 @@ Run the converging cleanup loop on the target the user names (a PR URL,
|
|
|
13
13
|
a branch, or blank for the current branch's diff). Each phase invokes an
|
|
14
14
|
existing skill and repeats it until a pass returns zero new findings.
|
|
15
15
|
|
|
16
|
+
### Stack context
|
|
17
|
+
|
|
18
|
+
Before any fixes, load and review the full PR stack, from its base through the
|
|
19
|
+
target PR. Read every PR and diff in the stack. Use that full context to judge
|
|
20
|
+
each proposed simplify or code-review fix. Apply a fix only when it fits the
|
|
21
|
+
stack's design, intent, and changes.
|
|
22
|
+
|
|
16
23
|
### Phase A — loop simplify
|
|
17
24
|
|
|
18
25
|
1. Invoke the `simplify` skill (or its local equivalent, e.g. `e-simplify`)
|
|
@@ -44,6 +51,9 @@ existing skill and repeats it until a pass returns zero new findings.
|
|
|
44
51
|
|
|
45
52
|
### Finish
|
|
46
53
|
|
|
54
|
+
When both phases are clean, or only fixed nits remain, mark the target PR ready
|
|
55
|
+
with `gh pr ready`. Confirm that it is no longer a draft.
|
|
56
|
+
|
|
47
57
|
Report: passes run per phase, commits pushed with hashes, fixes applied, and
|
|
48
58
|
the standing skip list with reasons.
|
|
49
59
|
|
|
@@ -30,6 +30,8 @@ One warm advisor at the strongest tier this session can reach. This session is t
|
|
|
30
30
|
5. Skip the multi-consumer "who you are" opener — sole consumer.
|
|
31
31
|
6. When the bind or reply path fails, fail closed and report to the user. On a third-party host, only the bound Claude advisor issues ENDORSE / CORRECTION / PLAN / STOP.
|
|
32
32
|
|
|
33
|
+
**GOTCHA (Cursor / ThirdParty + Sol):** when the walk reaches Sol or the user asks for Sol, first tool call is `python ~/.claude/_shared/advisor/scripts/codex_sol_advisor.py --bind --enable-sol --cwd <repo-root>` with the charter on stdin — not Agent/Task, not a probe-path search. Details: [`third-party-bind.md`](../../_shared/advisor/reference/third-party-bind.md) GOTCHA and [`sol-rung.md`](../../_shared/advisor/reference/sol-rung.md).
|
|
34
|
+
|
|
33
35
|
Full walk, charter, consult packet, Sol routing, and drift re-bind live in the protocol read map and its authoritative `reference/` leaves.
|
|
34
36
|
|
|
35
37
|
## Consult
|
package/AGENTS.md
CHANGED
|
@@ -76,6 +76,7 @@ Assemble and paste each executor's Advisor block per the **Advisor block** secti
|
|
|
76
76
|
On a third-party (non-Claude, non-Codex) harness, the shared CLI Claude-chain is the one path to a Claude advisor: bind Fable through it, per [`reference/third-party-bind.md`](reference/third-party-bind.md).
|
|
77
77
|
The bound Claude session is the advisor; this third-party session stays the executor.
|
|
78
78
|
Walk `candidate_tiers = ["Fable"]`. When Fable is out of usage, the sol rung binds after Fable (`candidate_tiers = ["Fable", "Sol"]`).
|
|
79
|
+
**Cursor Sol first shot:** when the walk reaches Sol (or the user asks for Sol), bind through `codex_sol_advisor.py --bind --enable-sol` on the first tool call (see the GOTCHA in [`reference/third-party-bind.md`](reference/third-party-bind.md)) — not the Agent tool, and not a probe-path hunt.
|
|
79
80
|
**Fail closed:** when every candidate fails, set `selected_tier = null` and a `fallback_reason`, report that the advisor is unreachable, and **stop** — ENDORSE / CORRECTION / PLAN / STOP come only from a bound advisor.
|
|
80
81
|
Executors report to the orchestrating session; that session consults the bound advisor and relays the four-signal reply.
|
|
81
82
|
|
|
@@ -24,9 +24,9 @@ Flag on: run the Codex preflight first —
|
|
|
24
24
|
python ~/.claude/_shared/pr-loop/scripts/codex_usage_probe.py
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Repo home: `packages/claude-dev-env/_shared/pr-loop/scripts/`.
|
|
27
|
+
**GOTCHA — probe path:** that installed path is the only one. `codex_sol_advisor.resolve_usage_probe_path` builds `~/.claude/_shared/pr-loop/scripts/codex_usage_probe.py` and stops. Do not hunt `skills/codex-review/`, Codex worktrees under `C:\dev\.codex\worktrees\`, or other copies. Repo home: `packages/claude-dev-env/_shared/pr-loop/scripts/`.
|
|
28
28
|
|
|
29
|
-
The shared entry point is `~/.claude/_shared/advisor/scripts/codex_sol_advisor.py`; it calls the installed probe and owns Sol bind or resume parsing. Bind with `python ~/.claude/_shared/advisor/scripts/codex_sol_advisor.py --bind --cwd <repo-root>` and pipe the charter on stdin. Resume with `--resume <session_id>` and pipe the delta consult on stdin.
|
|
29
|
+
The shared entry point is `~/.claude/_shared/advisor/scripts/codex_sol_advisor.py`; it calls the installed probe and owns Sol bind or resume parsing. Bind with `python ~/.claude/_shared/advisor/scripts/codex_sol_advisor.py --bind --enable-sol --cwd <repo-root>` and pipe the charter on stdin. Resume with `--resume <session_id>` and pipe the delta consult on stdin.
|
|
30
30
|
|
|
31
31
|
The gate passes only when the probe exits 0, `percent_left` is finite numeric data, and `percent_left` is strictly greater than `WEEKLY_USAGE_GATE_THRESHOLD_PERCENT` from the existing probe. The exact-threshold case fails closed when Fable did not bind.
|
|
32
32
|
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
Detail behind the **Host profiles → Third-party host** section of [`advisor-protocol.md`](../advisor-protocol.md).
|
|
4
4
|
Open this when binding or re-binding the advisor from a third-party (non-Claude, non-Codex) harness.
|
|
5
5
|
|
|
6
|
+
## GOTCHA — Cursor Sol first shot
|
|
7
|
+
|
|
8
|
+
Cursor is a third-party host. When the walk reaches Sol (`ADVISOR_SOL=1` / `--enable-sol` after Fable is out of usage, or the user asks for Sol), bind Sol on the **first** tool call through the headless Codex helper. Do not use the Agent or Task tool, do not spawn Grok as a substitute, and do not search the filesystem for `codex_usage_probe.py`.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
python "$HOME/.claude/_shared/advisor/scripts/codex_sol_advisor.py" --bind --enable-sol --cwd <repo-root>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Pipe the standing-reviewer charter on stdin. Persist `session_id` from the JSON reply. Later consults: `--resume <session_id>` with the delta on stdin. Capture helper / `codex` stdout as UTF-8 on Windows (`encoding="utf-8"`, `errors="replace"`). Probe path and preflight: [`sol-rung.md`](sol-rung.md).
|
|
15
|
+
|
|
16
|
+
When the Sol flag is off, follow the Claude-chain steps below.
|
|
17
|
+
|
|
6
18
|
## Bind steps
|
|
7
19
|
|
|
8
20
|
1. Name the session identity first (protocol **Host profiles**). This path is for a ThirdParty profile.
|
|
@@ -34,6 +34,10 @@ from advisor_scripts_constants.sol_advisor_constants import ( # noqa: E402
|
|
|
34
34
|
CODEX_REASONING_CONFIG_TEMPLATE,
|
|
35
35
|
CODEX_RESUME_SUBCOMMAND,
|
|
36
36
|
CODEX_SANDBOX_FLAG,
|
|
37
|
+
USAGE_PROBE_FILENAME,
|
|
38
|
+
USAGE_PROBE_PACKAGE_DIRECTORY_NAME,
|
|
39
|
+
USAGE_PROBE_SCRIPTS_DIRECTORY_NAME,
|
|
40
|
+
USAGE_PROBE_SHARED_DIRECTORY_NAME,
|
|
37
41
|
SOL_BIND_FAILURE_REASON,
|
|
38
42
|
SOL_CODEX_TIMEOUT_REASON,
|
|
39
43
|
SOL_CODEX_TIMEOUT_SECONDS,
|
|
@@ -201,6 +205,14 @@ def resolve_advisor_effort(
|
|
|
201
205
|
def resolve_usage_probe_path(home_directory: Path) -> Path:
|
|
202
206
|
"""Return the installed Codex weekly usage probe path.
|
|
203
207
|
|
|
208
|
+
::
|
|
209
|
+
|
|
210
|
+
resolve_usage_probe_path(Path.home())
|
|
211
|
+
-> ~/.claude/_shared/pr-loop/scripts/codex_usage_probe.py
|
|
212
|
+
|
|
213
|
+
This is the only probe path the Sol helper uses. Do not search worktrees
|
|
214
|
+
or archived ``skills/codex-review`` trees for a second copy.
|
|
215
|
+
|
|
204
216
|
Args:
|
|
205
217
|
home_directory: Home directory used to construct the path.
|
|
206
218
|
|
|
@@ -210,10 +222,10 @@ def resolve_usage_probe_path(home_directory: Path) -> Path:
|
|
|
210
222
|
return (
|
|
211
223
|
home_directory
|
|
212
224
|
/ CLAUDE_CONFIG_DIRECTORY_NAME
|
|
213
|
-
/
|
|
214
|
-
/
|
|
215
|
-
/
|
|
216
|
-
/
|
|
225
|
+
/ USAGE_PROBE_SHARED_DIRECTORY_NAME
|
|
226
|
+
/ USAGE_PROBE_PACKAGE_DIRECTORY_NAME
|
|
227
|
+
/ USAGE_PROBE_SCRIPTS_DIRECTORY_NAME
|
|
228
|
+
/ USAGE_PROBE_FILENAME
|
|
217
229
|
)
|
|
218
230
|
|
|
219
231
|
|
|
@@ -14,6 +14,10 @@ CODEX_EXEC_SUBCOMMAND: str = "exec"
|
|
|
14
14
|
CODEX_RESUME_SUBCOMMAND: str = "resume"
|
|
15
15
|
CODEX_SANDBOX_FLAG: str = "--sandbox"
|
|
16
16
|
CLAUDE_CONFIG_DIRECTORY_NAME: str = ".claude"
|
|
17
|
+
USAGE_PROBE_SHARED_DIRECTORY_NAME: str = "_shared"
|
|
18
|
+
USAGE_PROBE_PACKAGE_DIRECTORY_NAME: str = "pr-loop"
|
|
19
|
+
USAGE_PROBE_SCRIPTS_DIRECTORY_NAME: str = "scripts"
|
|
20
|
+
USAGE_PROBE_FILENAME: str = "codex_usage_probe.py"
|
|
17
21
|
SOL_SESSION_ID_METAVAR: str = "SESSION_ID"
|
|
18
22
|
SOL_CODEX_TIMEOUT_SECONDS: float = 120.0
|
|
19
23
|
SOL_USAGE_PROBE_TIMEOUT_SECONDS: float = 30.0
|
|
@@ -31,9 +31,8 @@ def _load_sol_module() -> ModuleType:
|
|
|
31
31
|
sol_advisor = _load_sol_module()
|
|
32
32
|
SCRIPTS_ROOT = Path(__file__).parent.parent
|
|
33
33
|
USAGE_PROBE_PATH = (
|
|
34
|
-
SCRIPTS_ROOT.parents[
|
|
35
|
-
/ "
|
|
36
|
-
/ "codex-review"
|
|
34
|
+
SCRIPTS_ROOT.parents[1]
|
|
35
|
+
/ "pr-loop"
|
|
37
36
|
/ "scripts"
|
|
38
37
|
/ "codex_usage_probe.py"
|
|
39
38
|
)
|
|
@@ -134,8 +133,8 @@ def test_resolve_usage_probe_path_uses_supplied_home_directory(tmp_path: Path) -
|
|
|
134
133
|
assert probe_path == (
|
|
135
134
|
tmp_path
|
|
136
135
|
/ ".claude"
|
|
137
|
-
/ "
|
|
138
|
-
/ "
|
|
136
|
+
/ "_shared"
|
|
137
|
+
/ "pr-loop"
|
|
139
138
|
/ "scripts"
|
|
140
139
|
/ "codex_usage_probe.py"
|
|
141
140
|
)
|
package/commands/sr-loop.md
CHANGED
|
@@ -10,6 +10,13 @@ tool and repeats it until a pass returns zero new findings.
|
|
|
10
10
|
Use `rules/asd-ste100-language.md` for user-facing wording. Keep the loop's
|
|
11
11
|
cleanup, verification, commit, push, and finish-report fields.
|
|
12
12
|
|
|
13
|
+
## Stack context
|
|
14
|
+
|
|
15
|
+
Before any fixes, load and review the full PR stack, from its base through the
|
|
16
|
+
target PR. Read every PR and diff in the stack. Use that full context to judge
|
|
17
|
+
each proposed simplify or code-review fix. Apply a fix only when it fits the
|
|
18
|
+
stack's design, intent, and changes.
|
|
19
|
+
|
|
13
20
|
## Phase A — loop /simplify
|
|
14
21
|
|
|
15
22
|
1. Invoke the `simplify` skill on the target (the same review the user gets
|
|
@@ -41,6 +48,9 @@ cleanup, verification, commit, push, and finish-report fields.
|
|
|
41
48
|
|
|
42
49
|
## Finish
|
|
43
50
|
|
|
51
|
+
When both phases are clean, or only fixed nits remain, mark the target PR ready
|
|
52
|
+
with `gh pr ready`. Confirm that it is no longer a draft.
|
|
53
|
+
|
|
44
54
|
Report: passes run per phase, commits pushed with hashes, fixes applied, and
|
|
45
55
|
the standing skip list with reasons.
|
|
46
56
|
|
|
@@ -22,6 +22,34 @@ A missing or unreadable source root is an error, and the run changes nothing. An
|
|
|
22
22
|
|
|
23
23
|
Run `codex-compat bridge --surface <name> --payload '<json-object>'`. The bridge exposes the Python translation logic directly. `TaskCreate` and `TaskUpdate` map to `update_plan`; spawn, message, wait, and stop map to multi-agent surfaces. `ScheduleWakeup` is explicitly unsupported and requires manual review.
|
|
24
24
|
|
|
25
|
+
## Per-message context injection (manual wiring)
|
|
26
|
+
|
|
27
|
+
Codex reads the same `hookSpecificOutput.additionalContext` shape as Claude,
|
|
28
|
+
on its own `UserPromptSubmit` event. `hooks/session/style_reminder_prompt.py`
|
|
29
|
+
works for both, as is.
|
|
30
|
+
|
|
31
|
+
The install already points `$CODEX_HOME/hooks` at the shared hooks folder.
|
|
32
|
+
Once installed, the script sits at
|
|
33
|
+
`$CODEX_HOME/hooks/session/style_reminder_prompt.py`.
|
|
34
|
+
|
|
35
|
+
Add this by hand to `$CODEX_HOME/hooks.json` (merge it into an existing file):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"hooks": {
|
|
40
|
+
"UserPromptSubmit": [
|
|
41
|
+
{
|
|
42
|
+
"command": "python3 $CODEX_HOME/hooks/session/style_reminder_prompt.py"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Limits:
|
|
50
|
+
|
|
51
|
+
- The installer skips Codex `hooks.json` for now. Wire it by hand.
|
|
52
|
+
|
|
25
53
|
## Roots and safety
|
|
26
54
|
|
|
27
55
|
Both roots are caller-supplied. The tool never writes to `.agents` or `CODEX_HOME` automatically; pass those locations explicitly when desired. No personal paths or secrets are embedded in the package.
|
package/hooks/hooks.json
CHANGED
|
@@ -123,6 +123,18 @@
|
|
|
123
123
|
]
|
|
124
124
|
}
|
|
125
125
|
],
|
|
126
|
+
"UserPromptSubmit": [
|
|
127
|
+
{
|
|
128
|
+
"matcher": "",
|
|
129
|
+
"hooks": [
|
|
130
|
+
{
|
|
131
|
+
"type": "command",
|
|
132
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/session/style_reminder_prompt.py",
|
|
133
|
+
"timeout": 10
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
],
|
|
126
138
|
"SessionStart": [
|
|
127
139
|
{
|
|
128
140
|
"matcher": "",
|
|
@@ -81,6 +81,7 @@ Shared constant modules imported by hooks throughout the `hooks/` tree. Each fil
|
|
|
81
81
|
| `stale_comment_reference_blocker_constants.py` | Identifier pattern, comment stopwords, and denial text for the stale-comment-reference blocker |
|
|
82
82
|
| `state_description_blocker_constants.py` | The set of historical/comparative phrases the state-description blocker rejects, plus the docstring-extraction and mention-span patterns for its Python docstring scan |
|
|
83
83
|
| `stop_dispatcher_constants.py` | Ordered hosted-hook roster and Stop block payload field names for the Stop-chain dispatcher |
|
|
84
|
+
| `style_reminder_prompt_constants.py` | The style reminder text ("small words. few words. always. forever.") for the style_reminder_prompt hook |
|
|
84
85
|
| `stuttering_check_config.py` | Config for the stuttering (repeated-phrase) check |
|
|
85
86
|
| `stuttering_import_binding_constants.py` | Import-binding patterns for the stuttering check |
|
|
86
87
|
| `subprocess_budget_completeness_constants.py` | Required argument names for the subprocess-budget completeness check |
|
package/hooks/session/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# hooks/session
|
|
2
2
|
|
|
3
|
-
SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown.
|
|
3
|
+
SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown. Also holds the UserPromptSubmit hook. It adds a style reminder to each message.
|
|
4
4
|
|
|
5
5
|
The working-style projection uses `~/.claude/rules/asd-ste100-language.md` for
|
|
6
6
|
user-facing word choice, sentence style, tone, punctuation, and prose form.
|
|
@@ -21,6 +21,8 @@ user-facing word choice, sentence style, tone, punctuation, and prose form.
|
|
|
21
21
|
| `test_orchestrator_auto_starter.py` | — | Tests for `orchestrator_auto_starter.py` |
|
|
22
22
|
| `test_issue_tracker_session_starter.py` | — | Tests for `issue_tracker_session_starter.py` |
|
|
23
23
|
| `working_style_prompt.py` | SessionStart | Emits an `additionalContext` block with the fixed working-style prompt (running ledger, canonical language policy, outcome-first finish, scope discipline). Writes nothing and runs no tools itself. |
|
|
24
|
+
| `style_reminder_prompt.py` | UserPromptSubmit | Adds the style reminder ("small words. few words. always. forever.") to every message, as `hookSpecificOutput.additionalContext`. Codex reads the same shape, so a manually wired Codex `hooks.json` can reuse this script too (see `docs/codex-compatibility.md`). Prints text and stops. |
|
|
25
|
+
| `test_style_reminder_prompt.py` | — | Tests for `style_reminder_prompt.py` |
|
|
24
26
|
| `test_gh_pr_author_session_cleanup.py` | — | Tests for `gh_pr_author_session_cleanup.py` |
|
|
25
27
|
| `test_session_edit_tracker_cleanup.py` | — | Tests for `session_edit_tracker_cleanup.py` |
|
|
26
28
|
| `test_session_env_cleanup.py` | — | Tests for `session_env_cleanup.py` |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""UserPromptSubmit hook. Adds the style reminder to every message.
|
|
3
|
+
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
user sends a message
|
|
7
|
+
|
|
|
8
|
+
v
|
|
9
|
+
UserPromptSubmit fires -> additionalContext: "small words. few words. always. forever."
|
|
10
|
+
|
|
|
11
|
+
v
|
|
12
|
+
the model sees the reminder this turn, and each turn after
|
|
13
|
+
|
|
14
|
+
Claude Code and Codex CLI both read the same ``additionalContext`` shape on
|
|
15
|
+
their ``UserPromptSubmit`` event. One script serves both. The hook prints
|
|
16
|
+
text and stops.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import sys
|
|
23
|
+
|
|
24
|
+
import _path_setup # noqa: F401
|
|
25
|
+
|
|
26
|
+
from hooks_constants.style_reminder_prompt_constants import STYLE_REMINDER_PROMPT
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main() -> None:
|
|
30
|
+
"""Print the style reminder as UserPromptSubmit additionalContext."""
|
|
31
|
+
payload = {
|
|
32
|
+
"hookSpecificOutput": {
|
|
33
|
+
"hookEventName": "UserPromptSubmit",
|
|
34
|
+
"additionalContext": STYLE_REMINDER_PROMPT,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
sys.stdout.write(json.dumps(payload) + "\n")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Tests for style_reminder_prompt. Checks the hook adds the style reminder."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import sys
|
|
5
|
+
from io import StringIO
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from unittest.mock import patch
|
|
8
|
+
|
|
9
|
+
_SESSION_DIR = Path(__file__).resolve().parent
|
|
10
|
+
_HOOKS_ROOT = _SESSION_DIR.parent
|
|
11
|
+
for each_sys_path_entry in (str(_SESSION_DIR), str(_HOOKS_ROOT)):
|
|
12
|
+
if each_sys_path_entry not in sys.path:
|
|
13
|
+
sys.path.insert(0, each_sys_path_entry)
|
|
14
|
+
|
|
15
|
+
import style_reminder_prompt as reminder
|
|
16
|
+
from hooks_constants.style_reminder_prompt_constants import STYLE_REMINDER_PROMPT
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _run_main() -> str:
|
|
20
|
+
"""Return the text main() prints."""
|
|
21
|
+
captured_stdout = StringIO()
|
|
22
|
+
with patch("sys.stdout", captured_stdout):
|
|
23
|
+
reminder.main()
|
|
24
|
+
return captured_stdout.getvalue()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestStyleReminderPrompt:
|
|
28
|
+
def test_main_emits_user_prompt_submit_hook_specific_output(self) -> None:
|
|
29
|
+
emitted = json.loads(_run_main())
|
|
30
|
+
hook_output = emitted["hookSpecificOutput"]
|
|
31
|
+
assert hook_output["hookEventName"] == "UserPromptSubmit"
|
|
32
|
+
assert hook_output["additionalContext"] == STYLE_REMINDER_PROMPT
|
package/package.json
CHANGED
package/rules/AGENTS.md
CHANGED
|
@@ -29,6 +29,7 @@ Rule files installed into `~/.claude/rules/` by `bin/install.mjs`. A rule withou
|
|
|
29
29
|
| `explore-thoroughly.md` | Read relevant files and map existing patterns before proposing a change |
|
|
30
30
|
| `falsify-before-green.md` | A check's green counts as evidence only after that same check ran red on a named break, with a passing control beside it |
|
|
31
31
|
| `file-global-constants.md` | File-global constants need at least two same-file references; otherwise move value to `config/` |
|
|
32
|
+
| `few-words.md` | The style reminder. Syncs to Cursor as an always-on `.mdc` rule. |
|
|
32
33
|
| `filesystem-search.md` | Every filesystem search names a scope; `es.exe`, `Glob`, `Grep`, and `Read` are equally sanctioned, and the `unscoped_search_blocker` denies a walk from a root |
|
|
33
34
|
| `gh-cli-conventions.md` | `--body-file` for every `gh` body; `--paginate --slurp` piped to external `jq` for every paginated list read |
|
|
34
35
|
| `git-workflow.md` | PR workflow: always create as draft, one commit per review stage, never commit working docs or images; carries the review-response protocol and a See-also block for its seven siblings |
|