claude-dev-env 2.8.0 → 2.9.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/CLAUDE.md +7 -1
- package/agents/clean-coder.md +9 -19
- package/agents/test_agent_frontmatter.py +26 -0
- package/docs/CODE_RULES.md +4 -2
- package/docs/references/CLAUDE.md +2 -2
- package/docs/references/advisor-tool.md +44 -6
- package/docs/references/team-advisor-skill.md +14 -8
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -0
- package/output-styles/CLAUDE.md +17 -0
- package/output-styles/caveman-agent.md +37 -0
- package/package.json +2 -1
- package/rules/code-standards.md +33 -7
- package/rules/eli11-replies.md +1 -1
- package/scripts/CLAUDE.md +2 -2
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
- package/scripts/dev_env_scripts_constants/grok_run_ledger_constants.py +50 -0
- package/scripts/dev_env_scripts_constants/grok_worker_constants.py +104 -0
- package/scripts/grok_patch_artifacts.py +123 -0
- package/scripts/grok_run_ledger.py +318 -0
- package/scripts/spawn_grok_batch.py +553 -9
- package/scripts/test_grok_patch_artifacts.py +82 -0
- package/scripts/test_grok_run_ledger.py +116 -0
- package/scripts/test_spawn_grok_batch.py +295 -0
- package/skills/CLAUDE.md +4 -2
- package/skills/_shared/CLAUDE.md +37 -4
- package/skills/_shared/advisor/CLAUDE.md +9 -0
- package/skills/_shared/advisor/advisor-protocol.md +5 -0
- package/skills/_shared/advisor/scripts/README.md +9 -0
- package/skills/_shared/end-of-run-gotcha-recommendations.md +156 -0
- package/skills/_shared/pr-loop/CLAUDE.md +18 -1
- package/skills/_shared/pr-loop/audit-contract.md +5 -0
- package/skills/_shared/pr-loop/audit-reply-template.md +5 -0
- package/skills/_shared/pr-loop/code-rules-gate.md +5 -0
- package/skills/_shared/pr-loop/fix-protocol.md +5 -0
- package/skills/_shared/pr-loop/gh-payloads.md +5 -0
- package/skills/_shared/pr-loop/post-audit-thread-contract.md +5 -0
- package/skills/_shared/pr-loop/precatch-rubric.md +5 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +8 -1
- package/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +29 -0
- package/skills/_shared/pr-loop/state-schema.md +5 -0
- package/skills/_shared/pr-loop/worker-spawn.md +5 -0
- package/skills/e-code-review/SKILL.md +6 -1
- package/skills/e-code-review/reference/runner-selection.md +40 -0
- package/skills/e-code-review/scripts/e_code_review_scripts_constants/__init__.py +1 -0
- package/skills/e-code-review/scripts/e_code_review_scripts_constants/grok_code_review_constants.py +55 -0
- package/skills/e-code-review/scripts/grok_code_review.py +221 -0
- package/skills/e-code-review/scripts/test_grok_code_review.py +212 -0
- package/skills/grok-spawn/SKILL.md +5 -0
- package/skills/orchestrator/SKILL.md +5 -0
- package/skills/task-build/reference/tool-routing.md +3 -0
- package/skills/team-advisor/SKILL.md +23 -44
- package/system-prompts/software-engineer.xml +6 -3
- package/skills/test_markdown_link_integrity.py +0 -107
package/CLAUDE.md
CHANGED
|
@@ -12,7 +12,13 @@ A runtime value that is itself private — a host, an SSH user or port, an owner
|
|
|
12
12
|
|
|
13
13
|
## Advisors
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
| Path | Holds |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `~/.claude/docs/references/advisor-tool.md` | When to call a stronger reviewer, hard rule before first write, how to treat advice |
|
|
18
|
+
| `/team-advisor` skill | Standing warm advisor bind (map: `docs/references/team-advisor-skill.md`) |
|
|
19
|
+
| `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, model floor, lifecycle |
|
|
20
|
+
|
|
21
|
+
When `advisor()` is available, use it under the rules in `advisor-tool.md`. When `advisor()` is unavailable, use `/team-advisor`.
|
|
16
22
|
|
|
17
23
|
## Files and workspaces
|
|
18
24
|
|
package/agents/clean-coder.md
CHANGED
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clean-coder
|
|
3
|
-
description: "Use PROACTIVELY for ALL code generation — feature development, bug fixes, refactoring, hook creation, automation scripts, and any task that produces code. Internalizes CODE_RULES.md and the 8-dimension readability standard so thoroughly that /check finds zero issues. The definitive code-writing agent."
|
|
3
|
+
description: "Use PROACTIVELY for ALL code generation — feature development, bug fixes, refactoring, hook creation, automation scripts, and any task that produces code. Internalizes AGENTS.md (canonical) via the CODE_RULES.md projection and the 8-dimension readability standard so thoroughly that /check finds zero issues. The definitive code-writing agent."
|
|
4
4
|
tools: Read, Write, Edit, Bash, Grep, Glob, Task, Skill, SendMessage
|
|
5
5
|
color: green
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Clean Coder — Zero-Defect Code Generation
|
|
9
9
|
|
|
10
|
-
You are the definitive code-writing agent. You produce code so clean that reviewers find nothing.
|
|
10
|
+
You are the definitive code-writing agent. You produce code so clean that reviewers find nothing. Canonical policy is repository-root `AGENTS.md`; `CODE_RULES.md` is its compact projection. Every dimension from the readability rubric is internalized into your generation process. The goal: `/check` returns CLEAN on every file you touch.
|
|
11
11
|
|
|
12
|
-
**Announce at start:** "Using clean-coder agent —
|
|
12
|
+
**Announce at start:** "Using clean-coder agent — AGENTS.md / CODE_RULES projection internalized, targeting 160/160 readability."
|
|
13
13
|
|
|
14
14
|
## First Action (MANDATORY)
|
|
15
15
|
|
|
16
|
-
Before writing a single line:
|
|
16
|
+
Before writing a single line — **task-local discovery only** (no project-wide preload):
|
|
17
17
|
|
|
18
18
|
1. **Read project CLAUDE.md** (when one exists) — load project-specific rules, naming overrides, and any extended ruleset.
|
|
19
|
-
2. **
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- `**/config/selectors.py`
|
|
23
|
-
- `**/config.py`
|
|
24
|
-
- `**/settings.py`
|
|
25
|
-
- `**/.env`
|
|
26
|
-
- `**/.env.*`
|
|
27
|
-
3. **Read every config file the globs return.** Extract every `UPPER_SNAKE_CASE` binding into a local name → value table. Before writing any constant in the new code:
|
|
28
|
-
- Exact value match in the table → import the existing name.
|
|
29
|
-
- Semantic match → reuse the existing name.
|
|
30
|
-
- No match → add the constant to the appropriate `config/` file.
|
|
31
|
-
4. **Read the file you are about to edit** (when editing existing code). Note every existing comment so you can leave each one untouched on lines that remain otherwise unchanged.
|
|
19
|
+
2. **Read the file you are about to edit** (when editing existing code). Note every existing comment so you can leave each one untouched on lines that remain otherwise unchanged.
|
|
20
|
+
3. **Discover config only next to the task files.** From each file you will write or edit, walk up to the nearest package or repo root and open only the config modules that package already uses for constants — typically `config/constants.py`, `config/timing.py`, `config/selectors.py`, or a sibling `*_constants` package. Do **not** glob the whole tree for every config file. Do **not** glob or open `.env`, `.env.*`, or other secret files.
|
|
21
|
+
4. **Reuse constants from that local table.** Exact value match → import the existing name. Semantic match → reuse it. No match → add the constant to the appropriate `config/` file for that package.
|
|
32
22
|
|
|
33
23
|
## The 8 Generation Laws
|
|
34
24
|
|
|
@@ -171,7 +161,7 @@ Hooks under `~/.claude/hooks/` are standalone scripts; module-level `UPPER_SNAKE
|
|
|
171
161
|
|
|
172
162
|
### Reuse before create
|
|
173
163
|
|
|
174
|
-
Search first. Import second. Create last. Before writing a constant, scan the name → value table built in First Action step
|
|
164
|
+
Search first. Import second. Create last. Before writing a constant, scan the name → value table built in First Action step 4.
|
|
175
165
|
|
|
176
166
|
### File-global constants use-count rule
|
|
177
167
|
|
|
@@ -422,7 +412,7 @@ When reading transcripts under the user projects directory, pass explicit file p
|
|
|
422
412
|
|
|
423
413
|
Decision tree before writing any constant:
|
|
424
414
|
|
|
425
|
-
1. Search the existing `config/` directory (using the table from First Action step
|
|
415
|
+
1. Search the existing `config/` directory (using the table from First Action step 4).
|
|
426
416
|
2. Found exact value → **import it**.
|
|
427
417
|
3. Found semantic match → **reuse the existing name**.
|
|
428
418
|
4. Config file exists for this category → **add to the existing file**.
|
|
@@ -422,3 +422,29 @@ def test_agent_frontmatter_carries_no_model_key(
|
|
|
422
422
|
"the caller supplies the model on every spawn, so agent definitions "
|
|
423
423
|
"carry no model key at all, not even model: inherit"
|
|
424
424
|
)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def _clean_coder_body() -> str:
|
|
428
|
+
return (Path(__file__).parent / "clean-coder.md").read_text(encoding="utf-8")
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def test_clean_coder_never_globs_or_reads_dotenv_files() -> None:
|
|
432
|
+
body = _clean_coder_body()
|
|
433
|
+
assert "`**/.env`" not in body
|
|
434
|
+
assert "`**/.env.*`" not in body
|
|
435
|
+
assert "Never open `.env`" in body or "Do **not** glob or open `.env`" in body
|
|
436
|
+
assert re.search(r"(?i)glob.*\.env|\.env.*glob", body) is None or "Do **not** glob or open `.env`" in body
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def test_clean_coder_uses_task_local_config_discovery() -> None:
|
|
440
|
+
body = _clean_coder_body()
|
|
441
|
+
assert "task-local" in body.lower()
|
|
442
|
+
assert "project-wide preload" in body.lower() or "Do **not** glob the whole tree" in body
|
|
443
|
+
assert "Issue all five Glob calls" not in body
|
|
444
|
+
assert "Issue all seven Glob calls" not in body
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def test_clean_coder_examples_import_constants_from_config() -> None:
|
|
448
|
+
body = _clean_coder_body()
|
|
449
|
+
assert "from config.timing import MAXIMUM_RETRIES" in body
|
|
450
|
+
assert re.search(r"(?m)^MAXIMUM_RETRIES\s*=\s*\d+", body) is None
|
package/docs/CODE_RULES.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Code Rules Reference
|
|
2
2
|
|
|
3
|
-
Compact
|
|
3
|
+
Compact **projection** of the repository-root canonical policy [`AGENTS.md`](../../../AGENTS.md). When this file and `AGENTS.md` disagree, **`AGENTS.md` wins** — update this projection in the same change.
|
|
4
|
+
|
|
5
|
+
⚡ marks rules enforced by hand-maintained `code_rules_enforcer.py` — the hook blocks the Write/Edit and returns the corrective detail at violation time, so this document lists those rules by name only. Session policy (question routing, task tracking) lives in `rules/*.md`; see [`code-standards.md`](../rules/code-standards.md).
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
@@ -46,7 +48,7 @@ Full words only (`context`, not `ctx`). Exceptions: `i`/`j`/`k` in loops, `e` fo
|
|
|
46
48
|
|
|
47
49
|
## 6. COMPLETE TYPE HINTS
|
|
48
50
|
|
|
49
|
-
ALL parameters typed, ALL returns typed. No `Any
|
|
51
|
+
ALL parameters typed, ALL returns typed. No `Any`. A `# type: ignore` is allowed only with a second trailing `#` justification of at least five characters (e.g. `# type: ignore[misc] # stubs missing in foo library`); bare ignores are blocked by `code_rules_enforcer.py`. Prefer fixing the type over an ignore when a real annotation is available.
|
|
50
52
|
|
|
51
53
|
## 6.5 FILE LENGTH GUIDANCE
|
|
52
54
|
|
|
@@ -8,8 +8,8 @@ Pointer documents to external sources, standard terminology, and internal tool o
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| `dead-code-elimination.md` | External sources and standard terms behind CODE_RULES §9.8 (remove code you orphan): DCE, tree shaking, reachability analysis, and the Lava Flow anti-pattern |
|
|
10
10
|
| `code-review-enforcement.md` | How the code-review gates work: the two required efforts (push at low, PR creation at xhigh), the stamp bound to the branch-surface hash, the single sanctioned minter, the two-layer stamp-directory guard, and the bypass surfaces the gates leave open |
|
|
11
|
-
| `advisor-tool.md` |
|
|
12
|
-
| `team-advisor-skill.md` |
|
|
11
|
+
| `advisor-tool.md` | Canonical consult bones for any stronger reviewer: when to call, hard rule before first write, how to treat advice; maps to the Anthropic advisor tool |
|
|
12
|
+
| `team-advisor-skill.md` | `/team-advisor` map: sole-consumer warm bind, ref index, and how it pairs with `advisor()` |
|
|
13
13
|
|
|
14
14
|
## Role
|
|
15
15
|
|
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
# Advisor Tool
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Canonical consult timing and weight for any stronger-reviewer path: the native `advisor()` tool, `/team-advisor`, and the shared warm advisor.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Source bones: [Anthropic Advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool) (Suggested system prompt for coding tasks). API shape, model pairs, cost, and caching live there. This file carries only the call rules a session needs every time.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What it is
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`advisor()` is a no-parameter review call. The platform forwards the full conversation (task, tool calls, results) to a stronger model. The executor continues with that guidance.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
When `advisor()` is absent, use `/team-advisor` (see `team-advisor-skill.md`).
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## When to call
|
|
14
|
+
|
|
15
|
+
Call **before substantive work** — before writing, before locking an interpretation, before building on an assumption.
|
|
16
|
+
|
|
17
|
+
If the task needs orientation first (find files, fetch a source, see what exists), do that, then call. Orientation is not substantive work. Writing, editing, and declaring an answer are.
|
|
18
|
+
|
|
19
|
+
Also call:
|
|
20
|
+
|
|
21
|
+
- **When you believe the task is complete.** Before this call, make the deliverable durable: write the file, save the result, commit the change. The call takes time; if the session ends during it, a durable result survives and an unwritten one does not.
|
|
22
|
+
- **When stuck** — errors recur, approach does not converge, results do not fit.
|
|
23
|
+
- **When considering a change of approach.**
|
|
24
|
+
|
|
25
|
+
On tasks longer than a few steps, call at least once before committing to an approach and once before declaring done. On short reactive tasks where the next action is dictated by tool output you just read, you do not need repeated calls — most value is on the first call, before the approach hardens.
|
|
26
|
+
|
|
27
|
+
Call for design, architecture, and risk questions where you will not touch a file. If the response would be analysis or a recommendation with no other tool calls, call first. That judgment is where a second opinion is highest value. Simple factual lookups and arithmetic do not need a call.
|
|
28
|
+
|
|
29
|
+
## Hard rule
|
|
30
|
+
|
|
31
|
+
Your first write, edit, or state-changing shell call on a task must be preceded by an advisor call in the same or an earlier turn. Read-only orientation (`ls`, `cat`, `grep`, `find`, and harness equivalents) is not state-changing. This is a checkpoint, not a difficulty judgment. It applies to one-line edits too.
|
|
32
|
+
|
|
33
|
+
## How to treat advice
|
|
34
|
+
|
|
35
|
+
Give the advice serious weight. If a step fails empirically, or primary-source evidence contradicts a claim (the file says X, the paper states Y), adapt. A passing self-test is not evidence the advice is wrong — it is evidence the test does not check what the advice is checking.
|
|
36
|
+
|
|
37
|
+
If your data points one way and the advisor points another: do not silently switch. Surface the conflict in one more call — "I found X, you suggest Y, which constraint breaks the tie?" A reconcile call is cheaper than the wrong branch.
|
|
38
|
+
|
|
39
|
+
## Brevity cue
|
|
40
|
+
|
|
41
|
+
When the consult path supports a free-text brief, append:
|
|
42
|
+
|
|
43
|
+
`(Advisor: please keep your guidance under 80 words — I need a focused starting point, not a comprehensive plan.)`
|
|
44
|
+
|
|
45
|
+
## Related
|
|
46
|
+
|
|
47
|
+
| Doc | Holds |
|
|
48
|
+
|---|---|
|
|
49
|
+
| [Anthropic Advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool) | API shape, model pairs, cost, caching, full best practices |
|
|
50
|
+
| `team-advisor-skill.md` | Standing warm advisor when `advisor()` is missing |
|
|
51
|
+
| `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, floor walk, lifecycle, executor paste blocks |
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
# Team-Advisor Skill
|
|
1
|
+
# Team-Advisor Skill
|
|
2
2
|
|
|
3
|
-
`/team-advisor`
|
|
3
|
+
`/team-advisor` binds one standing warm advisor for this session at the strongest reachable tier. Use it when `advisor()` is absent, or when you want a standing four-signal reviewer across many decision points.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Codex session -> consult Sol xhigh
|
|
5
|
+
## Refs
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
| Doc | Holds |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `skills/team-advisor/SKILL.md` | Sole-consumer bind wiring and constraints |
|
|
10
|
+
| `advisor-tool.md` | Consult timing, hard rule, how to treat advice |
|
|
11
|
+
| `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, floor, lifecycle |
|
|
12
|
+
| `agents/session-advisor.md` | ENDORSE / CORRECTION / PLAN / STOP |
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
## When to use
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
Follow the call rules in `advisor-tool.md` (orientation first, then consult before substantive work; durable deliverable before the completion consult; stuck or reapproach; long tasks twice).
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Relation to `advisor()`
|
|
19
|
+
|
|
20
|
+
`/team-advisor` works with no `advisor()` tool. When both exist: `advisor()` for a fast history-forwarded check; `/team-advisor` for a standing named reviewer consulted at the same cadence.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# output-styles
|
|
2
|
+
|
|
3
|
+
Output-style instruction files installed into `~/.claude/output-styles/` by `bin/install.mjs`. Each file instructs an agent or session to respond in a specific voice or format.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
| File | Style | Effect |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `caveman-agent.md` | Caveman Agent | Terse fragments, lead with answer, smallest artifact that solves the stated problem, question premise before building |
|
|
10
|
+
|
|
11
|
+
## Format
|
|
12
|
+
|
|
13
|
+
Each file uses YAML frontmatter (`name`, `description`, optional `keep-coding-instructions`) followed by Markdown instructions. The `keep-coding-instructions: true` flag tells Claude Code to keep the session's coding rules even when this style is active.
|
|
14
|
+
|
|
15
|
+
## Adding a style
|
|
16
|
+
|
|
17
|
+
Create a `.md` file with frontmatter and behavioral instructions, then run `bin/install.mjs` to copy it to `~/.claude/output-styles/`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Caveman Agent
|
|
3
|
+
description: Caveman voice + caveman work. Terse replies, minimum viable artifacts, pushback before build.
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Caveman voice. Caveman work.
|
|
8
|
+
|
|
9
|
+
## Voice
|
|
10
|
+
|
|
11
|
+
Lead with answer. Drop articles, filler, hedging, preamble, recap.
|
|
12
|
+
Fragments OK. Pattern: `[thing] [action] [reason]. [next step].`
|
|
13
|
+
Keep code, paths, commands, errors, JSON unchanged.
|
|
14
|
+
Bullets/tables only when scan beats prose.
|
|
15
|
+
|
|
16
|
+
## Work ethos
|
|
17
|
+
|
|
18
|
+
Smallest artifact that solves stated problem. Nothing more.
|
|
19
|
+
One file beats three. Functions beat classes. Concrete beats abstract.
|
|
20
|
+
No planning docs, no speculative tests, no future-proof params, no README unless asked.
|
|
21
|
+
Question premise before building — if existing tool covers it, say so and stop.
|
|
22
|
+
|
|
23
|
+
## Pushback rule
|
|
24
|
+
|
|
25
|
+
Before any new file, ask:
|
|
26
|
+
- Does existing tool already do this? If yes → say so, stop.
|
|
27
|
+
- Is the scaffolding earning its keep right now? If no → drop it.
|
|
28
|
+
- One file or many? → one, unless many is forced.
|
|
29
|
+
|
|
30
|
+
## Escape hatch
|
|
31
|
+
|
|
32
|
+
Normal language and normal care for:
|
|
33
|
+
- Safety, destructive ops, irreversible actions
|
|
34
|
+
- Money, credentials, production systems
|
|
35
|
+
- Genuine confusion risk
|
|
36
|
+
|
|
37
|
+
Caveman voice is for speed, not for hazards.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-dev-env",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"docs/",
|
|
17
17
|
"commands/",
|
|
18
18
|
"agents/",
|
|
19
|
+
"output-styles/",
|
|
19
20
|
"skills/",
|
|
20
21
|
"hooks/",
|
|
21
22
|
"system-prompts/",
|
package/rules/code-standards.md
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
# Code Standards
|
|
2
2
|
|
|
3
|
-
> **
|
|
4
|
-
>
|
|
3
|
+
> **Canonical policy:** repository-root [`AGENTS.md`](../../../AGENTS.md) — the human and AI review contract for code quality.
|
|
4
|
+
> **Compact projection:** [`CODE_RULES.md`](../docs/CODE_RULES.md) — validated summary for generation load.
|
|
5
|
+
> **Production enforcement:** `hooks/blocking/code_rules_enforcer.py` — hand-maintained Write/Edit gates; each mechanical rule carries a synchronization test.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
## Policy surface map
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
| Layer | Path | Role |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Canonical | `AGENTS.md` (repo root) | Full review criteria for PR agents; BugBot sync source |
|
|
12
|
+
| Projection | `docs/CODE_RULES.md` | Compact always-load reference; must not diverge from AGENTS |
|
|
13
|
+
| Enforcer | `hooks/blocking/code_rules_enforcer.py` | Hand-maintained blockers; not generated from the docs |
|
|
14
|
+
| Session rules | `rules/*.md` | Runtime session policy (questions, tasks, shell) |
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
- **Right-sized engineering** — CODE_RULES §7 is canonical: functions over classes, concrete over abstract, an abstraction added at the commit that introduces its second concrete implementation.
|
|
16
|
+
Load `AGENTS.md` when reviewing a PR or resolving a policy conflict. Load `CODE_RULES.md` when generating code under the compact checklist. Prefer linking these refs over restating rules.
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
Two standards live in the canonical policy in full (and in the projection by name):
|
|
19
|
+
|
|
20
|
+
- **TDD** — CODE_RULES §8 / AGENTS Tests: red, green, refactor; no production code before a failing test.
|
|
21
|
+
- **Right-sized engineering** — CODE_RULES §7 / AGENTS Design: functions over classes; concrete over abstract; add an abstraction at the commit that introduces its second concrete implementation.
|
|
22
|
+
|
|
23
|
+
BDD is the outer process and TDD is the inner loop: [`bdd.md`](bdd.md) discovers and formulates the behavior a feature needs, then each formulated behavior is built through the TDD cycle.
|
|
24
|
+
|
|
25
|
+
## Session policies (ref docs, not restated here)
|
|
26
|
+
|
|
27
|
+
| Concern | Rule file |
|
|
28
|
+
|---|---|
|
|
29
|
+
| Question routing | [`ask-user-question-required.md`](ask-user-question-required.md) |
|
|
30
|
+
| Task tracking / worker completion | [`workers-done-before-complete.md`](workers-done-before-complete.md) |
|
|
31
|
+
| Multi-step task list | skill `task-build` (see agents catalog) |
|
|
32
|
+
|
|
33
|
+
## Synchronization
|
|
34
|
+
|
|
35
|
+
Mechanical enforcer coverage is checked by `tests/test_agents_policy_parity.py` and the existing `hooks/blocking/test_code_rules_enforcer*.py` suite. BugBot projection drift is checked with:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
python .github/scripts/sync_ai_rules.py --check
|
|
39
|
+
```
|
package/rules/eli11-replies.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
## Rules
|
|
22
22
|
|
|
23
|
-
- **One command per block** — a command the user runs goes in its own `bash`-tagged fenced block, so the Run button appears. That tag gives the user a Run button; [`shell-invocation-policy`](shell-invocation
|
|
23
|
+
- **One command per block** — a command the user runs goes in its own `bash`-tagged fenced block, so the Run button appears. That tag gives the user a Run button; [`shell-invocation-policy`](shell-invocation.md) stays in charge of the agent's own Bash-tool calls, which run pwsh-only.
|
|
24
24
|
- **One line per status** — each background-work update gets a single line.
|
|
25
25
|
- **Cut findings first** — when a reply runs long, drop findings and keep the action steps.
|
|
26
26
|
- **Skim test** — reading only the bold words tells the whole story.
|
package/scripts/CLAUDE.md
CHANGED
|
@@ -12,7 +12,7 @@ Utility scripts installed into `~/.claude/scripts/` by `bin/install.mjs`. Each s
|
|
|
12
12
|
| `grok_headless_runner.py` | Runs one worker as headless `grok`: builds argv with no turn cap (the timeout is the only bound), mints a unique leader socket, captures streams, refuses a timeout that is missing, below `MIN_WORKER_TIMEOUT_SECONDS`, or above the `MAXIMUM_WORKER_TIMEOUT_SECONDS` (5400) ceiling, kills the whole process tree on timeout with grace and retries the kill-and-drain round once, classifies ok/usage_limit/auth_failure/timeout/kill_failed/error; exports `require_timeout_within_bounds` so a dispatcher can apply the same bounds without launching; imported by `spawn_grok_batch.py` and `resolve_worker_spawn.py` |
|
|
13
13
|
| `grok_worker_preflight.py` | Soft gate for the headless grok tier: binary on PATH, `grok models` auth, install manifest + role agents, opt-in cached live ping; non-zero exit is fallthrough, not failure |
|
|
14
14
|
| `setup_project_paths.py` | One-time bootstrap: discovers git repos via `es.exe` (Everything) and writes `~/.claude/project-paths.json`; never hardcodes scan roots |
|
|
15
|
-
| `spawn_grok_batch.py` | Launches a fleet of headless grok workers from a JSON batch spec: gates once through the preflight, refuses a spec whose `timeout_seconds` exceeds `MAXIMUM_WORKER_TIMEOUT_SECONDS` (5400) rather than clamping it, assembles each prompt from part files, staggers starts, runs each through `grok_headless_runner.py`, and emits one batch summary JSON |
|
|
15
|
+
| `spawn_grok_batch.py` | Launches a fleet of headless grok workers from a JSON batch spec: gates once through the preflight, refuses a spec whose `timeout_seconds` exceeds `MAXIMUM_WORKER_TIMEOUT_SECONDS` (5400) rather than clamping it, assembles each prompt from part files, optionally binds a unique worker advisor per role via the lead-supplied `advisor.launcher` (placeholder default in constants), injects `advisor_session_id`, requires the same session ENDORSE or bounded CORRECTION/PLAN then ENDORSE, classifies bind/verdict/timeout/missing-launcher failures as `advisor_blocked`, staggers starts, runs each through `grok_headless_runner.py`, and emits one batch summary JSON |
|
|
16
16
|
| `sweep_empty_dirs.py` | Deletes empty directories older than a configurable age under a given root; runs once (`--once`) or in continuous-watch mode |
|
|
17
17
|
| `sync_to_cursor.py` | Entry point for syncing Claude rules to Cursor `.mdc` files; delegates to the `sync_to_cursor/` package |
|
|
18
18
|
| `resolve_worker_spawn.py` | Dispatches a worker role through grok then claude fallback tiers (preflight, headless grok, `claude_agent_required` handoff, optional claude headless); applies `require_timeout_within_bounds` before the preflight, so an out-of-bounds `--timeout-seconds` prints a `timeout_out_of_bounds` outcome and exits 3 on every tier; protocol: [`../_shared/pr-loop/worker-spawn.md`](../_shared/pr-loop/worker-spawn.md) |
|
|
@@ -33,7 +33,7 @@ Utility scripts installed into `~/.claude/scripts/` by `bin/install.mjs`. Each s
|
|
|
33
33
|
|
|
34
34
|
| Entry | Description |
|
|
35
35
|
|---|---|
|
|
36
|
-
| `dev_env_scripts_constants/` | Named constants (`timing.py`) for scripts in this directory |
|
|
36
|
+
| `dev_env_scripts_constants/` | Named constants (`timing.py`, `grok_worker_constants.py`, …) for scripts in this directory, including worker-advisor placeholder launcher/model/effort, four verdict signals, correction cap, and advisor timeout |
|
|
37
37
|
| `sync_to_cursor/` | Package that builds Cursor `.mdc` files from Claude rules and docs |
|
|
38
38
|
| `tests/` | pytest suite for the Python scripts and Pester (`*.Tests.ps1`) suite for the PowerShell scripts in this directory |
|
|
39
39
|
|
|
@@ -10,7 +10,7 @@ Named constants for scripts in `scripts/`. Follows the project convention that t
|
|
|
10
10
|
| `gh_artifact_upload_constants.py` | `gh_artifact_upload.py` - the `artifacts` release tag, title, and notes body, the GitHub CLI binary name, the asset-name timestamp format and template, the asset download URL template, the notes-file suffix, and the text encoding |
|
|
11
11
|
| `claude_chain_constants.py` | `claude_chain_runner.py` - the chain config filename and home subdirectory, the usage-limit signature text, the per-binary status labels, routing-mode tokens (`usage_ranked` / `ordered_account`), outcome `terminal_status` values (`served` / `advisor_blocked` / `chain_exhausted` / `timeout`), the default timeout, CLI flag and separator tokens, config JSON keys (including optional `credentials_path`), invalid-shape reason text, config-error and exhausted-chain message templates, and CLI exit codes (including advisor-blocked); `invoke_code_review.py` and `resolve_worker_spawn.py` - the text-codec keyword names and the `collect_forwarded_text_codec` helper that forwards them to the subprocess runner for text-mode capture |
|
|
12
12
|
| `claude_chain_usage_constants.py` | `claude_chain_usage.py` - full weekly percent scale, usage-pause skill path segments, CLI config-path flag, JSON report keys, and probe error message templates |
|
|
13
|
-
| `grok_worker_constants.py` | `grok_worker_preflight.py`, `grok_headless_runner.py`, `spawn_grok_batch.py`, and `resolve_worker_spawn.py` - the `grok` binary name and CLI flags, model and subcommand tokens, leader-socket and scratch-file name parts, auth and usage-limit signature lists, outcome classifications, fallthrough reasons, tool-profile names and prompt headers, worker timeouts (default, plus the floor and the `MAXIMUM_WORKER_TIMEOUT_SECONDS` ceiling that the batch spec parse, the headless runner, and the spawn dispatcher all enforce, each bound carrying one rejection template shared by those sites, plus launch-failure return code and post-kill grace), the process-tree kill attempt limit and kill-failed classification, the preflight ping's single-turn cap, ping-cache keys and TTL, batch-spec and summary JSON keys, the prompt-part and report-stream join separators, and the CLI launch-error stderr prefix |
|
|
13
|
+
| `grok_worker_constants.py` | `grok_worker_preflight.py`, `grok_headless_runner.py`, `spawn_grok_batch.py`, and `resolve_worker_spawn.py` - the `grok` binary name and CLI flags, model and subcommand tokens, leader-socket and scratch-file name parts, auth and usage-limit signature lists, outcome classifications, fallthrough reasons, tool-profile names and prompt headers, worker timeouts (default, plus the floor and the `MAXIMUM_WORKER_TIMEOUT_SECONDS` ceiling that the batch spec parse, the headless runner, and the spawn dispatcher all enforce, each bound carrying one rejection template shared by those sites, plus launch-failure return code and post-kill grace), the process-tree kill attempt limit and kill-failed classification, the preflight ping's single-turn cap, ping-cache keys and TTL, batch-spec and summary JSON keys, worker-advisor placeholder launcher/model/effort tokens, four verdict signals, MAXIMUM_WORKER_ADVISOR_CORRECTIONS, advisor_blocked classification, and advisor_session_id report keys, the prompt-part and report-stream join separators, and the CLI launch-error stderr prefix |
|
|
14
14
|
| `code_review_constants.py` | `invoke_code_review.py` - the `/code-review ultra --fix` prompt, opus model alias, permission-mode flag and value, result mode and JSON keys, session-model CLI flag, git dirty-check tokens, and in-session return markers; finding severity tokens (`blocker` / `high` / `medium` / `low` / `nit`), verification verdict tokens, loop terminal tokens (`clean` / `nits_fixed` / `advisor_blocked`), and pure helpers for retained-finding checks, head recording, terminal resolution, and terminal encoding |
|
|
15
15
|
| `__init__.py` | Empty package marker |
|
|
16
16
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Named constants for the host-neutral Grok run ledger and patch artifacts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
LEDGER_SCHEMA_VERSION: str = "1.0.0"
|
|
6
|
+
"""Schema version stamped on every ledger document and task record."""
|
|
7
|
+
|
|
8
|
+
LEDGER_FILENAME: str = "grok-run-ledger.json"
|
|
9
|
+
"""Default ledger filename under a run-state directory."""
|
|
10
|
+
|
|
11
|
+
PATCH_MANIFEST_FILENAME: str = "patch-manifest.json"
|
|
12
|
+
"""Default patch-manifest filename under a run-state directory."""
|
|
13
|
+
|
|
14
|
+
TASK_STATUS_PENDING: str = "pending"
|
|
15
|
+
"""Task is recorded and waiting for dispatch."""
|
|
16
|
+
|
|
17
|
+
TASK_STATUS_IN_PROGRESS: str = "in_progress"
|
|
18
|
+
"""Task has exactly one live owner and is being worked."""
|
|
19
|
+
|
|
20
|
+
TASK_STATUS_COMPLETED: str = "completed"
|
|
21
|
+
"""Task reached a successful terminal state."""
|
|
22
|
+
|
|
23
|
+
TASK_STATUS_ADVISOR_BLOCKED: str = "advisor_blocked"
|
|
24
|
+
"""Task stopped because the advisor bind or verdict failed closed."""
|
|
25
|
+
|
|
26
|
+
TASK_STATUS_PENDING_REVIEW: str = "pending_review"
|
|
27
|
+
"""Task was invalidated by snapshot drift and needs re-review."""
|
|
28
|
+
|
|
29
|
+
ALL_LEGAL_TASK_STATUSES: frozenset[str] = frozenset(
|
|
30
|
+
{
|
|
31
|
+
TASK_STATUS_PENDING,
|
|
32
|
+
TASK_STATUS_IN_PROGRESS,
|
|
33
|
+
TASK_STATUS_COMPLETED,
|
|
34
|
+
TASK_STATUS_ADVISOR_BLOCKED,
|
|
35
|
+
TASK_STATUS_PENDING_REVIEW,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
"""Every legal task status the ledger accepts."""
|
|
39
|
+
|
|
40
|
+
UTF8_ENCODING: str = "utf-8"
|
|
41
|
+
"""Text encoding for ledger and patch-manifest files."""
|
|
42
|
+
|
|
43
|
+
JSON_INDENT: int = 2
|
|
44
|
+
"""Indent width for pretty-printed ledger and patch-manifest JSON."""
|
|
45
|
+
|
|
46
|
+
TEMPORARY_LEDGER_PREFIX: str = ".ledger-"
|
|
47
|
+
"""Prefix for atomic ledger temp files before replace."""
|
|
48
|
+
|
|
49
|
+
TEMPORARY_LEDGER_SUFFIX: str = ".tmp"
|
|
50
|
+
"""Suffix for atomic ledger temp files before replace."""
|
|
@@ -503,3 +503,107 @@ CLI_ENABLE_CLAUDE_TIER_FLAG: str = "--enable-claude-tier"
|
|
|
503
503
|
|
|
504
504
|
EMPTY_OUTPUT: str = ""
|
|
505
505
|
"""Empty captured output when no tier produced stdout."""
|
|
506
|
+
|
|
507
|
+
BATCH_SPEC_ADVISOR_KEY: str = "advisor"
|
|
508
|
+
"""JSON key for the optional batch-level worker-advisor block."""
|
|
509
|
+
|
|
510
|
+
ADVISOR_SPEC_LAUNCHER_KEY: str = "launcher"
|
|
511
|
+
"""JSON key for the lead-supplied advisor launcher executable name."""
|
|
512
|
+
|
|
513
|
+
ADVISOR_SPEC_MODEL_KEY: str = "model"
|
|
514
|
+
"""JSON key for the advisor model name."""
|
|
515
|
+
|
|
516
|
+
ADVISOR_SPEC_EFFORT_KEY: str = "effort"
|
|
517
|
+
"""JSON key for the advisor effort level."""
|
|
518
|
+
|
|
519
|
+
DEFAULT_ADVISOR_LAUNCHER_PLACEHOLDER: str = "ADVISOR_LAUNCHER_PLACEHOLDER"
|
|
520
|
+
"""Committed placeholder; real launcher arrives only from the lead's batch spec."""
|
|
521
|
+
|
|
522
|
+
DEFAULT_ADVISOR_MODEL: str = "opus"
|
|
523
|
+
"""Default advisor model when the batch advisor block omits model."""
|
|
524
|
+
|
|
525
|
+
DEFAULT_ADVISOR_EFFORT: str = "high"
|
|
526
|
+
"""Default advisor effort when the batch advisor block omits effort."""
|
|
527
|
+
|
|
528
|
+
MAXIMUM_WORKER_ADVISOR_CORRECTIONS: int = 3
|
|
529
|
+
"""Maximum CORRECTION/PLAN re-consults per worker before advisor_blocked."""
|
|
530
|
+
|
|
531
|
+
MAXIMUM_ADVISOR_TIMEOUT_SECONDS: int = 600
|
|
532
|
+
"""Timeout for one advisor launcher subprocess call, in seconds."""
|
|
533
|
+
|
|
534
|
+
ADVISOR_SIGNAL_ENDORSE: str = "ENDORSE"
|
|
535
|
+
"""Opening signal that accepts a worker report."""
|
|
536
|
+
|
|
537
|
+
ADVISOR_SIGNAL_CORRECTION: str = "CORRECTION"
|
|
538
|
+
"""Opening signal that requires a re-consult up to the correction cap."""
|
|
539
|
+
|
|
540
|
+
ADVISOR_SIGNAL_PLAN: str = "PLAN"
|
|
541
|
+
"""Opening signal treated like CORRECTION for re-consult counting."""
|
|
542
|
+
|
|
543
|
+
ADVISOR_SIGNAL_STOP: str = "STOP"
|
|
544
|
+
"""Opening signal that ends the worker as advisor_blocked immediately."""
|
|
545
|
+
|
|
546
|
+
ALL_KNOWN_ADVISOR_SIGNALS: frozenset[str] = frozenset(
|
|
547
|
+
{
|
|
548
|
+
ADVISOR_SIGNAL_ENDORSE,
|
|
549
|
+
ADVISOR_SIGNAL_CORRECTION,
|
|
550
|
+
ADVISOR_SIGNAL_PLAN,
|
|
551
|
+
ADVISOR_SIGNAL_STOP,
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
"""The four allowed first tokens of an advisor reply."""
|
|
555
|
+
|
|
556
|
+
CLASSIFICATION_ADVISOR_BLOCKED: str = "advisor_blocked"
|
|
557
|
+
"""Worker classification when advisor bind, resume, or verdict fails closed."""
|
|
558
|
+
|
|
559
|
+
PENDING_BIND_SENTINEL: str = "PENDING_BIND"
|
|
560
|
+
"""Unbound advisor session or signal sentinel; must fail closed before launch."""
|
|
561
|
+
|
|
562
|
+
ADVISOR_PROMPT_HEADER_TEMPLATE: str = (
|
|
563
|
+
"Worker advisor session: {session_id}\n"
|
|
564
|
+
"Advisor model: {model}\n"
|
|
565
|
+
"Advisor effort: {effort}\n"
|
|
566
|
+
"Report only after the same session endorses or corrections are applied.\n\n"
|
|
567
|
+
)
|
|
568
|
+
"""Prefix injected into each worker prompt after a successful pre-dispatch bind."""
|
|
569
|
+
|
|
570
|
+
SUMMARY_ADVISOR_SESSION_ID_KEY: str = "advisor_session_id"
|
|
571
|
+
"""Per-worker report JSON key for the unique advisor session id."""
|
|
572
|
+
|
|
573
|
+
SUMMARY_ADVISOR_SIGNAL_KEY: str = "advisor_completion_signal"
|
|
574
|
+
"""Per-worker report JSON key for the final advisor opening signal."""
|
|
575
|
+
|
|
576
|
+
SUMMARY_ADVISOR_LAUNCHER_KEY: str = "advisor_launcher"
|
|
577
|
+
"""Per-worker report JSON key for the spec-supplied launcher (runtime only)."""
|
|
578
|
+
|
|
579
|
+
ADVISOR_CLI_PRINT_FLAG: str = "-p"
|
|
580
|
+
"""Print/non-interactive flag passed to the advisor launcher."""
|
|
581
|
+
|
|
582
|
+
ADVISOR_CLI_MODEL_FLAG: str = "--model"
|
|
583
|
+
"""Model flag passed to the advisor launcher."""
|
|
584
|
+
|
|
585
|
+
ADVISOR_CLI_EFFORT_FLAG: str = "--effort"
|
|
586
|
+
"""Effort flag passed to the advisor launcher."""
|
|
587
|
+
|
|
588
|
+
ADVISOR_CLI_OUTPUT_FORMAT_FLAG: str = "--output-format"
|
|
589
|
+
"""Output-format flag passed to the advisor launcher."""
|
|
590
|
+
|
|
591
|
+
ADVISOR_CLI_OUTPUT_FORMAT_JSON: str = "json"
|
|
592
|
+
"""JSON output format value for advisor launcher calls."""
|
|
593
|
+
|
|
594
|
+
ADVISOR_CLI_RESUME_FLAG: str = "--resume"
|
|
595
|
+
"""Resume flag for post-report advisor consults."""
|
|
596
|
+
|
|
597
|
+
ADVISOR_BIND_PROMPT_TEMPLATE: str = (
|
|
598
|
+
"You are the unique worker advisor for role {role_name}. "
|
|
599
|
+
"Answer only. Open with exactly one of: ENDORSE | CORRECTION | PLAN | STOP. "
|
|
600
|
+
"Pre-dispatch: ENDORSE this worker assignment if safe, else CORRECTION."
|
|
601
|
+
)
|
|
602
|
+
"""Prompt body used for the pre-dispatch advisor bind."""
|
|
603
|
+
|
|
604
|
+
ADVISOR_VERDICT_PROMPT_TEMPLATE: str = (
|
|
605
|
+
"You are the unique worker advisor for role {role_name}, session {session_id}. "
|
|
606
|
+
"Answer only. Open with exactly one of: ENDORSE | CORRECTION | PLAN | STOP. "
|
|
607
|
+
"Post-report review of the worker report follows.\n\n{report_text}"
|
|
608
|
+
)
|
|
609
|
+
"""Prompt body used for the post-report advisor verdict."""
|