claude-dev-env 8.0.0 → 8.2.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/agents/clean-coder.md +4 -4
- package/.agents/agents/code-quality-agent.md +4 -4
- package/.agents/agents/plan-packet-validator.md +2 -2
- package/.agents/agents/session-advisor.md +1 -1
- package/.agents/skills/cert-classification-rule/SKILL.md +3 -3
- package/.agents/skills/e-code-review/SKILL.md +2 -2
- package/.agents/skills/e-code-review/reference/fix.md +1 -1
- package/.agents/skills/e-code-review/reference/loop.md +1 -1
- package/.agents/skills/e-code-review/reference/medium.md +4 -4
- package/.agents/skills/e-code-review/reference/xhigh.md +5 -5
- package/.agents/skills/everything-search/SKILL.md +3 -3
- package/.agents/skills/issue-tracker/SKILL.md +1 -1
- package/.agents/skills/orchestrator/SKILL.md +3 -3
- package/.agents/skills/orchestrator/reference/consult-the-orchestrator.md +1 -1
- package/.agents/skills/orchestrator/reference/executor-consult-block.md +1 -1
- package/.agents/skills/orchestrator-refresh/SKILL.md +2 -2
- package/.agents/skills/plugin-eval-standalone-skill/SKILL.md +96 -0
- package/.agents/skills/plugin-eval-standalone-skill/reference/graders-and-commands.md +108 -0
- package/.agents/skills/privacy-hygiene/SKILL.md +5 -6
- package/.agents/skills/privacy-hygiene/reference/sweep-procedure.md +5 -6
- package/.agents/skills/repairing-hook-boundaries/SKILL.md +1 -1
- package/.agents/skills/syncing-submodules/SKILL.md +1 -1
- package/.agents/skills/team-advisor/SKILL.md +9 -7
- package/.agents/skills/team-advisor/reference/advisor-docs-review.md +28 -1
- package/.agents/skills/usage-pause/SKILL.md +3 -3
- package/_shared/advisor/advisor-protocol.md +7 -3
- package/_shared/advisor/reference/advisor-block.md +8 -1
- package/audit-rubrics/audit-categories.json +0 -4
- package/audit-rubrics/category_rubrics/category-e-dead-code.md +1 -1
- package/audit-rubrics/category_rubrics/category-f-silent-failures.md +2 -2
- package/audit-rubrics/category_rubrics/category-i-concurrency.md +1 -1
- package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +1 -2
- package/audit-rubrics/category_rubrics/category-m-producer-consumer-cardinality.md +1 -1
- package/audit-rubrics/category_rubrics/category-n-test-name-scenario-verifier.md +5 -5
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +5 -5
- package/audit-rubrics/category_rubrics/category-p-name-vs-behavior-contract.md +3 -3
- package/audit-rubrics/category_rubrics/category-q-cross-surface-claims.md +1 -1
- package/audit-rubrics/prompts/category-a-api-contracts.md +2 -2
- package/audit-rubrics/prompts/category-b-selector-engine-compat.md +3 -3
- package/audit-rubrics/prompts/category-c-resource-cleanup.md +3 -3
- package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +1 -1
- package/audit-rubrics/prompts/category-e-dead-code.md +5 -5
- package/audit-rubrics/prompts/category-f-silent-failures.md +12 -12
- package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +2 -2
- package/audit-rubrics/prompts/category-h-security-boundaries.md +4 -4
- package/audit-rubrics/prompts/category-i-concurrency.md +6 -6
- package/audit-rubrics/prompts/category-j-code-rules-compliance.md +6 -29
- package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +1 -1
- package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +7 -7
- package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
- package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +3 -3
- package/audit-rubrics/prompts/category-q-cross-surface-claims.md +2 -2
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/ever-shipped-skills.test.mjs +4 -0
- package/docs/BDD_SCENARIO_QUALITY.md +2 -2
- package/docs/CODE_RULES.md +7 -7
- package/docs/TEST_QUALITY.md +1 -1
- package/docs/nas-ssh-invocation.md +1 -1
- package/docs/references/advisor-tool.md +2 -2
- package/docs/references/prose-style-enforcement.md +1 -1
- package/docs/references/team-advisor-skill.md +2 -2
- package/docs/references/weak-executor-advisor.md +1 -1
- package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
- package/package.json +1 -1
- package/rules/anti-corollary-tests.md +3 -1
- package/rules/archiving-agent-config.md +67 -0
- package/rules/asd-ste100-language.md +1 -1
- package/rules/ci-owns-the-gate.md +15 -0
- package/rules/cleanup-temp-files.md +1 -1
- package/rules/code-standards.md +2 -2
- package/rules/docstring-prose-matches-implementation.md +1 -1
- package/rules/explore-thoroughly.md +2 -2
- package/rules/failure-blast-radius.md +9 -8
- package/rules/git-workflow.md +7 -4
- package/rules/long-horizon-autonomy.md +3 -1
- package/rules/nas-ssh-invocation.md +1 -1
- package/rules/research-mode.md +3 -1
- package/rules/retired-hook-prose.md +10 -2
- package/rules/testing.md +3 -3
- package/rules/verify-before-asking.md +3 -0
- package/rules/verify-runtime-state.md +2 -2
- package/scripts/active_capability_references.py +74 -19
- package/scripts/banned_prose_words.py +159 -0
- package/scripts/dev_env_scripts_constants/active_capability_constants.py +12 -10
- package/scripts/dev_env_scripts_constants/banned_prose_word_constants.py +95 -0
- package/scripts/policy_lint/adapter_retired_hook_prose.py +17 -7
- package/scripts/policy_lint/adapters.py +6 -6
- package/scripts/policy_lint/config/constants.py +8 -0
- package/scripts/policy_lint/registry.py +1 -1
- package/scripts/sync_to_cursor/rules.py +1 -1
- package/scripts/test_active_capability_references.py +100 -33
- package/scripts/tests/test_banned_prose_words.py +103 -0
- package/scripts/tests/test_codex_compat_materializer.py +3 -3
- package/scripts/tests/test_engine.py +1 -1
- package/scripts/tests/test_policy_lint_rules_retired_hook_prose.py +46 -0
- package/scripts/tests/test_rules.py +12 -1
- package/system-prompts/software-engineer.xml +7 -7
package/docs/CODE_RULES.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The canonical review-criteria instruction set for every AI agent that audits pull requests in this repository, loaded on demand. [`.cursor/BUGBOT.md`](../../../.cursor/BUGBOT.md) is the checked-in pointer file Cursor BugBot reads; it points here.
|
|
4
4
|
|
|
5
|
-
⚡ marks rules
|
|
5
|
+
⚡ marks rules the hand-maintained `code_rules_enforcer.py` carries. The staged policy lint runs it over each changed file and returns the corrective detail, 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).
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -25,9 +25,9 @@ Production and tests follow one rule. Changed directive, TODO, FIXME, HACK, XXX,
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
## ⚡
|
|
28
|
+
## ⚡ LINT-ENFORCED RULES
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
The staged policy lint reports each of these through `code_rules_enforcer.py` and names the specific breach; exact patterns and exemption lists live in that module:
|
|
31
31
|
|
|
32
32
|
no new comments · imports at top · logging format args (`log_*("...", arg)`) · no `%s`/`%d` printf tokens in a `str.format`-logger message (`log_*` imported from `automation_logging`; `str.format` drops the args — use `{}`) · no magic values in production bodies (0, 1, -1 exempt) · UPPER_SNAKE constants only in `config/` (exempt: `config/*`; `/migrations/`; Workflow registries: path contains any of these substrings — `/workflow/`, `_tab.py`, `/states.py`, or `/modules.py`, each matching independently as a substring, so `pkg/states.py` qualifies while a top-level `states.py` follows the standard `config/` rule; test files — path or filename matches `test_`, `_test.`, `.spec.`, `conftest`, or `/tests/`) · no hardcoded user home paths · guarded `sys.path.insert` · banned identifiers (`ctx`, `cfg`, `msg`, `btn`, `idx`, `cnt`, `tmp`, `elem`, `val`) · banned function prefixes (`handle_`, `process_`, `manage_`, `do_`) · no type escape hatches (`Any` import, `cast()`, inline `Any`, a parameter typed bare `object` whose body reads `param.attribute`) outside boundary files · no bare/broad `except` · no `Any` in signatures or class attributes · no stub bodies (`pass`/`...`/`raise NotImplementedError`) outside abstract/Protocol · TypedDict `_encode_*`/`_decode_*` companions in the same module · no test-mode branching in production (use dependency injection) · no thin wrapper modules · Google-style docstrings on public functions with `Args:` matching the signature · boolean names prefixed `is_`/`has_`/`should_`/`can_`/`was_`/`did_` (assignments AND bool-typed parameters) · must-check returns (`find_and_click`, `write_outcome`) assigned and checked · known pytest fixture parameters in test files annotated with their single documented type (`tmp_path: Path`, `monkeypatch: pytest.MonkeyPatch`, `capsys`, `caplog`, `request`, …) · known pytest fixture parameters a test function declares but never references (drop the unused parameter — pytest still pays its setup cost) · JavaScript/TypeScript boolean declarations (`const`/`let`/`var` bound to a boolean literal or negation) and `@param {boolean}` JSDoc names prefixed `is`/`has`/`should`/`can`/`was`/`did` (camelCase forms) · banned identifiers as `.mjs`/`.js` declaration names (`result`, `data`, `ctx`, `msg`, …), scoped to changed lines · in test files, banned identifiers fire on changed lines, and pytest-collectable `test_*` functions need a return annotation · unused module-level imports and unsorted import blocks are ruff's job (F401, isort I001), not this hook's · a `hooks/blocking/` command classifier anchors its multi-word command regex to the command start (`^`/`\A`) or tokenizes the first word (`shlex.split`), never matching a command as a bare substring
|
|
33
33
|
|
|
@@ -53,7 +53,7 @@ The banned-noun check applies to public function definitions, parameters, and bo
|
|
|
53
53
|
|
|
54
54
|
## 6. COMPLETE TYPE HINTS
|
|
55
55
|
|
|
56
|
-
ALL parameters typed, ALL returns typed. No `Any`. Avoid `# type: ignore`; remove it and use a typed boundary or
|
|
56
|
+
ALL parameters typed, ALL returns typed. No `Any`. Avoid `# type: ignore`; remove it and use a typed boundary or the type. Prefer fixing the type over an ignore when an annotation is available.
|
|
57
57
|
|
|
58
58
|
## 6.5 FILE LENGTH GUIDANCE
|
|
59
59
|
|
|
@@ -83,7 +83,7 @@ Components own their complete feature (state, modals, overlays, toasts). Parents
|
|
|
83
83
|
|
|
84
84
|
## 9.5 NO THIN WRAPPER MODULES
|
|
85
85
|
|
|
86
|
-
A non-`__init__.py` module whose body is only imports (optionally `__all__`) is indirection without payload — callers import the
|
|
86
|
+
A non-`__init__.py` module whose body is only imports (optionally `__all__`) is indirection without payload — callers import the module. `__init__.py` is the canonical re-export surface and is exempt.
|
|
87
87
|
|
|
88
88
|
## 9.6 NO BACKWARDS-COMPATIBILITY SHIMS
|
|
89
89
|
|
|
@@ -111,7 +111,7 @@ If you already have the data, don't fetch it again.
|
|
|
111
111
|
|
|
112
112
|
## 11.5 VALIDATION-PHASE PRECEDENCE
|
|
113
113
|
|
|
114
|
-
`code_rules_enforcer.py`
|
|
114
|
+
A staged policy lint run of `code_rules_enforcer.py` selects what it checks and reports along three independent axes. Each axis filters a narrower scope than the one before it; none widens what the axis before it already decided.
|
|
115
115
|
|
|
116
116
|
1. **Phase selects the roster.** `EDIT_LANE_PHASE` or `FULL_GATE_PHASE` decides which checks exist in the lane at all. `validate_content_for_phase` takes `phase` keyword-only with no default, so every caller names its lane explicitly.
|
|
117
117
|
2. **Target classification filters within a lane.** The hook-infrastructure patterns and the ephemeral-path check decide whether a target is validated, and with which subset. Classification narrows a lane; it never adds a check the phase already excluded.
|
|
@@ -127,6 +127,6 @@ Hook-infrastructure targets run three checks in the edit lane — `check_same_fi
|
|
|
127
127
|
|
|
128
128
|
Three surfaces report on the roster, and each reports a specific thing:
|
|
129
129
|
|
|
130
|
-
- `hooks/validators/hook_timing_harness.py` builds a `Write` payload against a target that already holds content. `_contents_for_validation` returns `None` for that payload, so the harness times interpreter start and hook dispatch. Time an `Edit` payload against a
|
|
130
|
+
- `hooks/validators/hook_timing_harness.py` builds a `Write` payload against a target that already holds content. `_contents_for_validation` returns `None` for that payload, so the harness times interpreter start and hook dispatch. Time an `Edit` payload against a file to measure the checks.
|
|
131
131
|
- `~/.claude/logs/hook-blocks.log` records the denials raised by fixtures in `test_code_rules_enforcer_*.py` and by the timing harness's default target.
|
|
132
132
|
- `hooks/validators/run_all_validators.py` stages the target under a temporary root and rebuilds the shortest path tail that carries every exemption signal. The walk starts at the target's own project root and skips a directory pytest generated for its own scratch tree, so the staged path reads the same wherever `--basetemp` places that tree.
|
package/docs/TEST_QUALITY.md
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
|
|
86
86
|
**Mock too much** - Prefer integration tests
|
|
87
87
|
- Bad: Mock every hook and function
|
|
88
|
-
- Good: Render with
|
|
88
|
+
- Good: Render with unmocked hooks, mock only API calls
|
|
89
89
|
|
|
90
90
|
**Test implementation details** - Test what user experiences
|
|
91
91
|
- Bad: Assert on state values, hook return values
|
|
@@ -66,7 +66,7 @@ running anything.
|
|
|
66
66
|
The NAS is a Linux box and this machine is Windows, so two classes of difference show up only there:
|
|
67
67
|
syntax newer than the NAS interpreter accepts, and tests that assert Windows paths.
|
|
68
68
|
|
|
69
|
-
**Always separate a
|
|
69
|
+
**Always separate a break in the code from a platform-only one.** Run the same test file at the branch head
|
|
70
70
|
and at the commit the work started from. Identical failures at both mean the environment, not the
|
|
71
71
|
change. Report both numbers rather than the head alone.
|
|
72
72
|
|
|
@@ -6,7 +6,7 @@ Source bones: [Anthropic Advisor tool](https://platform.claude.com/docs/en/agent
|
|
|
6
6
|
|
|
7
7
|
## What it is
|
|
8
8
|
|
|
9
|
-
`/team-advisor` is the repository's advisor implementation.
|
|
9
|
+
`/team-advisor` is the repository's advisor implementation. On a Claude host with the built-in `advisor` tool on, it calls `advisor()`, which reads the whole transcript. Otherwise it carries the full first packet explicitly, sends later deltas, and owns the warm Agent/SendMessage or read-only Astra CLI lifecycle.
|
|
10
10
|
|
|
11
11
|
See `team-advisor-skill.md` for the bind and lifecycle map.
|
|
12
12
|
|
|
@@ -57,7 +57,7 @@ When the consult path supports a free-text brief, append:
|
|
|
57
57
|
|
|
58
58
|
`(Advisor: please keep your guidance under 80 words — I need a focused starting point, not a comprehensive plan.)`
|
|
59
59
|
|
|
60
|
-
Size the ask at roughly 80 percent of the
|
|
60
|
+
Size the ask at roughly 80 percent of the ceiling; direct address to the advisor lands more reliably than a third-person description.
|
|
61
61
|
|
|
62
62
|
## Related
|
|
63
63
|
|
|
@@ -10,7 +10,7 @@ The flag is `PROSE_STYLE_ENFORCEMENT_ENABLED` in `hooks/blocking/config/prose_st
|
|
|
10
10
|
|
|
11
11
|
## Always on
|
|
12
12
|
|
|
13
|
-
Historical
|
|
13
|
+
Historical and comparative language detection lives in `state_description_blocker.py`, which the staged policy lint applies under its state-description rule whatever this flag holds. Apply `rules/asd-ste100-language.md` for user-facing word choice and sentence style. Code-rules and security blockers are out of scope for this switch.
|
|
14
14
|
|
|
15
15
|
## Hedging claims
|
|
16
16
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Team-advisor skill
|
|
2
2
|
|
|
3
|
-
`/team-advisor` binds one
|
|
3
|
+
`/team-advisor` binds one advisor for this session. On a Claude host with the built-in `advisor` tool on, it calls `advisor()`. Otherwise it binds a standing warm advisor at the strongest reachable tier and sends explicit packets to a warm Agent/SendMessage advisor or the read-only `codex_astra_advisor.py` helper.
|
|
4
4
|
|
|
5
5
|
## Refs
|
|
6
6
|
|
|
@@ -17,4 +17,4 @@ Follow the call rules in `advisor-tool.md` (orientation first, then consult befo
|
|
|
17
17
|
|
|
18
18
|
## Selected path
|
|
19
19
|
|
|
20
|
-
`/team-advisor` is the repository's advisor implementation. It provides explicit first-consult packets, delta consults, a standing warm reviewer, an in-session Astra spawn on Codex, and a read-only Astra CLI option.
|
|
20
|
+
`/team-advisor` is the repository's advisor implementation. It uses the built-in advisor tool when the session has it. Without the tool, it provides explicit first-consult packets, delta consults, a standing warm reviewer, an in-session Astra spawn on Codex, and a read-only Astra CLI option.
|
|
@@ -30,7 +30,7 @@ carries its own packet:
|
|
|
30
30
|
|
|
31
31
|
- **First consult** — use the complete packet in
|
|
32
32
|
`~/.claude/_shared/advisor/reference/consult-format.md`: assignment,
|
|
33
|
-
desired outcome, constraints and exclusions, actions taken in order,
|
|
33
|
+
desired outcome, constraints and exclusions, actions taken in order,
|
|
34
34
|
output and current state, decision or blocker, validation evidence,
|
|
35
35
|
unresolved risks, and load-bearing paths or excerpts.
|
|
36
36
|
- **Later consults** — the delta since the last consult.
|
package/package.json
CHANGED
|
@@ -28,12 +28,14 @@ When the code reduces each input to a canonical form and then compares the forms
|
|
|
28
28
|
|
|
29
29
|
Name the degenerate value a dead implementation would return — empty string, `None`, `False`, a blanket refusal, an empty collection. When the test's expected value equals that default, the test passes whether the mechanism works or not. On its own it proves nothing.
|
|
30
30
|
|
|
31
|
-
**Do this:** keep at least one case that expects the **non-default** answer, and drive the
|
|
31
|
+
**Do this:** keep at least one case that expects the **non-default** answer, and drive the production code path — not a mock that only records that a call happened.
|
|
32
32
|
|
|
33
33
|
### 3. What single change to the code would make this test fail?
|
|
34
34
|
|
|
35
35
|
When the honest answer is "none," or "only a change that also breaks everything else," the test is decoration. Drop it or rewrite it so one named mutation kills it.
|
|
36
36
|
|
|
37
|
+
**The policy-surface case.** A test that asserts a policy's own wording appears in the file that declares the policy has one mutation available: editing that sentence. It cannot report whether anything obeys the policy, so a suite full of such tests measures how many files repeat a rule, which is the duplication the reader was already complaining about. Assert instead that the surfaces the policy governs comply with it, and let the declaring file be the input rather than the subject.
|
|
38
|
+
|
|
37
39
|
## What a mechanism with a degenerate failure mode needs
|
|
38
40
|
|
|
39
41
|
1. **At least one non-default case** that exercises the live path and expects the non-default answer.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Archiving a Rule, Skill, Agent, or Command
|
|
2
|
+
|
|
3
|
+
**When this applies:** Pruning agent configuration in this package — moving a
|
|
4
|
+
rule, skill, agent, or command out of service, and deciding whether one is
|
|
5
|
+
still used at all.
|
|
6
|
+
|
|
7
|
+
## Prove disuse before you remove
|
|
8
|
+
|
|
9
|
+
A prune is only as good as the usage evidence behind it, and three habits give
|
|
10
|
+
confident wrong answers here.
|
|
11
|
+
|
|
12
|
+
**Grepping the file's own name measures documentation, not use.** Enforcement in
|
|
13
|
+
this package is rarely named after the file that describes it. Resolve what the
|
|
14
|
+
file names instead: does the script exist, does the lint rule id appear in the
|
|
15
|
+
registry, does the check run. A rule with no mention of its slug anywhere can
|
|
16
|
+
still have a live checker behind it under a different name.
|
|
17
|
+
|
|
18
|
+
**Three files name every capability and prove nothing about any of them.**
|
|
19
|
+
`CHANGELOG.md` records history. The `README.md` inventory table lists what
|
|
20
|
+
ships. `bin/ever-shipped-skills.mjs` is a registry the prune reads, and it keeps
|
|
21
|
+
archived names on purpose. Subtract all three before you read a referrer count.
|
|
22
|
+
|
|
23
|
+
**A path this tree does not hold is not by itself a stale reference.** This
|
|
24
|
+
package installs into other repositories, so a rule or skill naming a file that
|
|
25
|
+
lives in the host repository is working as intended. Ask whether the specific
|
|
26
|
+
script or id it names resolves where it would run, not whether the path exists
|
|
27
|
+
here.
|
|
28
|
+
|
|
29
|
+
## Archive rather than delete
|
|
30
|
+
|
|
31
|
+
Move the file with `git mv` into the archive sibling: `rules-archived/` beside
|
|
32
|
+
`rules/`, `.agents/skills-archived/` beside `.agents/skills/`. The archive is a
|
|
33
|
+
sibling and never a child, because the installer copies a content directory
|
|
34
|
+
whole.
|
|
35
|
+
|
|
36
|
+
Archives ship nothing by omission. `CONTENT_DIRECTORIES` in `bin/install.mjs`
|
|
37
|
+
names the directories the installer writes, and no archive sibling is on that
|
|
38
|
+
list; skills are enumerated from `.agents/skills` alone. So an archived file
|
|
39
|
+
leaves every install without any further step, and it comes back with the
|
|
40
|
+
reverse `git mv`.
|
|
41
|
+
|
|
42
|
+
Record a row in the archive manifest for each file: why it went, the `git mv`
|
|
43
|
+
that restores it, and every other edit a restore has to undo. A restore that has
|
|
44
|
+
to be reconstructed from the diff is not recoverable in any useful sense.
|
|
45
|
+
|
|
46
|
+
## Make the archive stick
|
|
47
|
+
|
|
48
|
+
Two things do not follow the file on their own.
|
|
49
|
+
|
|
50
|
+
**A skill's name stays in `bin/ever-shipped-skills.mjs`.** The prune computes
|
|
51
|
+
the retired set as every name ever shipped minus the names installed now, and
|
|
52
|
+
that is how a stale copy is moved out of a host's agents home. Delete the name
|
|
53
|
+
and the copy is stranded on every machine that has it. The reference checker in
|
|
54
|
+
`scripts/active_capability_references.py` derives its retired set the same way,
|
|
55
|
+
so the registry entry is also what makes a leftover mention of the archived
|
|
56
|
+
name report. No second list needs the name.
|
|
57
|
+
|
|
58
|
+
**A renamed skill directory takes its tests out of the run.** The node test
|
|
59
|
+
command globs `.agents/skills/**/*.test.mjs`, so a suite under an archived skill
|
|
60
|
+
stops running without failing. Check that the count you expect still runs.
|
|
61
|
+
|
|
62
|
+
## Sibling rules
|
|
63
|
+
|
|
64
|
+
| Rule | Role |
|
|
65
|
+
|---|---|
|
|
66
|
+
| [`retired-hook-prose.md`](retired-hook-prose.md) | Prose names only hooks that run, and retiring a gate drops the detours it required |
|
|
67
|
+
| [`doc-inventory-integrity.md`](doc-inventory-integrity.md) | Inventory tables stay in step with what ships |
|
|
@@ -26,7 +26,7 @@ definitions and dictionary decisions.
|
|
|
26
26
|
- Use inclusive, neutral language.
|
|
27
27
|
- Use periods, commas, colons, and bullets to show structure.
|
|
28
28
|
- Preserve exact quoted labels, identifiers, formulas, titles, and interface text.
|
|
29
|
-
- Use `WARNING` for a
|
|
29
|
+
- Use `WARNING` for a risk of injury or death. Use `CAUTION` for a risk of equipment, tool, or machine damage. State the command or condition first, then state the result.
|
|
30
30
|
- Aim for 20 words or fewer in a procedure sentence when the technical content allows.
|
|
31
31
|
- Aim for 25 words or fewer in a descriptive sentence when the technical content allows.
|
|
32
32
|
|
|
@@ -37,6 +37,21 @@ Clone the revision the workflow pins, then point the gate at that clone. That
|
|
|
37
37
|
run asks CI's question and its answer carries. Report a local result by naming
|
|
38
38
|
the revision it used, so a reader can tell which question it answered.
|
|
39
39
|
|
|
40
|
+
The selection flag decides which question the staged policy lint answers.
|
|
41
|
+
`--staged` and `--base <revision>` carry each file's prior text, so the lint
|
|
42
|
+
subtracts what the prior text already reported and only a breach the change
|
|
43
|
+
introduced survives. `--files` and `--repository` carry no prior text, so every
|
|
44
|
+
breach in the file reports and the command exits non-zero on debt the change
|
|
45
|
+
never touched. CI runs the merge-base form, so reproduce a CI verdict with it:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
git merge-base HEAD origin/main
|
|
49
|
+
python packages/claude-dev-env/scripts/cde_lint.py --base <the revision that printed>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A `--files` run that comes back red on a file you touched has answered a
|
|
53
|
+
different question. Read the reported line before you treat it as yours.
|
|
54
|
+
|
|
40
55
|
## The verdict belongs to CI
|
|
41
56
|
|
|
42
57
|
CI decides whether a change passed, from evidence CI gathered. Keep that loop
|
|
@@ -7,7 +7,7 @@ Source: [Anthropic — Reduce file creation in agentic coding](https://platform.
|
|
|
7
7
|
## During a task
|
|
8
8
|
|
|
9
9
|
- Prefer working in memory over creating scratchpad files. Use variables and tool results instead of writing intermediate data to disk.
|
|
10
|
-
- When a temporary file is
|
|
10
|
+
- When a temporary file is needed (e.g., a helper script, a test fixture, a debug output), track it mentally for cleanup.
|
|
11
11
|
|
|
12
12
|
## When a task is complete
|
|
13
13
|
|
package/rules/code-standards.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| Contract | `docs/CODE_RULES.md` | Full review criteria for PR agents, loaded on demand |
|
|
12
12
|
| Pointer | `.cursor/BUGBOT.md` | Checked-in file Cursor BugBot reads; points at `CODE_RULES.md` |
|
|
13
13
|
| Enforcer | `hooks/blocking/code_rules_enforcer.py` | Hand-maintained checks the staged policy lint runs; not generated from the docs |
|
|
14
|
-
| Lint | `scripts/cde_lint.py` | Runs the enforcer and the other policy rules over staged or changed files |
|
|
14
|
+
| Lint | `scripts/cde_lint.py` | Runs the enforcer and the other policy rules over staged or changed files, grading each against the file's prior text; see [`ci-owns-the-gate.md`](ci-owns-the-gate.md) for what each selection flag reports |
|
|
15
15
|
| Session rules | `rules/*.md` | Runtime session policy (questions, tasks, shell) |
|
|
16
16
|
|
|
17
17
|
Load `CODE_RULES.md` when reviewing a PR, resolving a policy conflict, or generating code. Prefer linking this ref over restating rules.
|
|
@@ -19,7 +19,7 @@ Load `CODE_RULES.md` when reviewing a PR, resolving a policy conflict, or genera
|
|
|
19
19
|
Two standards live in `CODE_RULES.md` in full:
|
|
20
20
|
|
|
21
21
|
- **TDD** — CODE_RULES §8 / AGENTS Tests: red, green, refactor; no production code before a failing test.
|
|
22
|
-
- **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
|
+
- **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. That count is a house call, one occurrence earlier than the rule of three Fowler credits to Don Roberts. The direction comes from the literature; the number does not, so read it as this package's setting rather than as a cited standard.
|
|
23
23
|
|
|
24
24
|
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.
|
|
25
25
|
|
|
@@ -36,7 +36,7 @@ A hook module is the sharpest case of the same rule: its docstring lead narrativ
|
|
|
36
36
|
|
|
37
37
|
The staged policy lint carries this as its `hook-prose-consistency` rule, covering hook modules and their `*_constants.py` companions. It reports prose that claims a trigger the detector never fires on, and names the fix. No write-time hook runs it, so CI is where it reports.
|
|
38
38
|
|
|
39
|
-
After writing a hook, ask: would a token matching every word of this message
|
|
39
|
+
After writing a hook, ask: would a token matching every word of this message trip the detector? When the message names a shape the regex skips, rewrite the message to name only what the regex catches. The path-shape case is the common overstatement — a detector that keys off a path separator must not claim it blocks an "output-key segment". The corrective message spells the rewrite.
|
|
40
40
|
|
|
41
41
|
## Full standard
|
|
42
42
|
|
|
@@ -13,7 +13,7 @@ Note: This deliberately chooses exploration depth over the "commit and execute q
|
|
|
13
13
|
|
|
14
14
|
## Exploration scales with risk
|
|
15
15
|
|
|
16
|
-
- Small change to a familiar file: a quick read of the file and its immediate neighbors is
|
|
16
|
+
- Small change to a familiar file: a quick read of the file and its immediate neighbors is enough.
|
|
17
17
|
- New feature or cross-cutting change: read broadly across the codebase to understand how similar things are done.
|
|
18
18
|
- Architectural decision: explore the full landscape before recommending a direction.
|
|
19
19
|
|
|
@@ -23,4 +23,4 @@ The depth budget shrinks once the evidence is in hand. When you can already name
|
|
|
23
23
|
|
|
24
24
|
## Relationship to other rules
|
|
25
25
|
|
|
26
|
-
- **research-mode.md** ensures factual claims are grounded. This rule ensures implementation plans are grounded in the
|
|
26
|
+
- **research-mode.md** ensures factual claims are grounded. This rule ensures implementation plans are grounded in the codebase.
|
|
@@ -47,7 +47,7 @@ The re-raise comes first, sending an escalation directly through the boundary.
|
|
|
47
47
|
An agent that hits a member failure keeps working the problem. Three things bound how:
|
|
48
48
|
|
|
49
49
|
- **Repair in place.** The current run preserves every completed member.
|
|
50
|
-
- **Three
|
|
50
|
+
- **Three attempts, then park.** An attempt is a theory of the cause, acted on. Re-running the same code on the same input counts as one attempt. Three theories cover the obvious cause, the second guess, and the cause revealed by the first two attempts. Judgment selects each theory; the third attempt sets the stopping point. After the third theory fails, park the member with its reason and move to the next. Parked members return after the batch.
|
|
51
51
|
- **The batch always reaches a deliverable.** Complete every member that can complete, produce the packaged artifact, then work the parked list. A run with 34 of 37 members complete and 3 parked records progress and continues to delivery.
|
|
52
52
|
|
|
53
53
|
## Three alike means one cause
|
|
@@ -58,9 +58,9 @@ The run report groups parked members by that signature and names every group of
|
|
|
58
58
|
|
|
59
59
|
## Close the run with every outcome
|
|
60
60
|
|
|
61
|
-
Every issue the run hit gets one line in the closing report: what failed, and how it ended — repaired, worked around, or parked. Members that finished after a repair belong in that list beside the parked ones. A workaround patched past mid-run is the likeliest
|
|
61
|
+
Every issue the run hit gets one line in the closing report: what failed, and how it ended — repaired, worked around, or parked. Members that finished after a repair belong in that list beside the parked ones. A workaround patched past mid-run is the likeliest defect in the batch, because the closing report becomes its durable record.
|
|
62
62
|
|
|
63
|
-
The report then presents each candidate to the owner for a durable-fix decision
|
|
63
|
+
The report then presents each candidate to the owner for a durable-fix decision and names the fix the run recommends for each one. The report is a statement, not a gate: the current run completes its deliverable and ends. A later run builds whichever fixes the owner selects, and the recommendation stands as the default for any the owner does not rule on.
|
|
64
64
|
|
|
65
65
|
## Enforcement
|
|
66
66
|
|
|
@@ -82,7 +82,7 @@ scope, and the deliverable remains the run priority.
|
|
|
82
82
|
|
|
83
83
|
Repair in place and preserve every completed asset in the current run.
|
|
84
84
|
|
|
85
|
-
Three
|
|
85
|
+
Three attempts, then park. An attempt is a theory of the cause, acted
|
|
86
86
|
on. Repeated execution of one theory remains one attempt.
|
|
87
87
|
Three theories cover the obvious cause, the second guess, and the cause
|
|
88
88
|
revealed by the first two attempts. Use your judgment to select each theory;
|
|
@@ -108,11 +108,12 @@ stops. For an asset-level stop, put the handling inside the loop body.
|
|
|
108
108
|
Close the run by reporting what broke and what you did about it. Every issue
|
|
109
109
|
gets one line: what failed, and how it ended — repaired, worked around, or
|
|
110
110
|
parked. Include the ones you solved; a workaround you patched past in attempt
|
|
111
|
-
two is the likeliest
|
|
111
|
+
two is the likeliest defect in the list, because the closing report becomes
|
|
112
112
|
its durable record.
|
|
113
|
-
Present each candidate for the owner's durable-fix decision
|
|
114
|
-
you recommend and why
|
|
115
|
-
|
|
113
|
+
Present each candidate for the owner's durable-fix decision and state which
|
|
114
|
+
fix you recommend for each and why. Do not wait on the answer. Complete this
|
|
115
|
+
run's deliverable and end. A later run builds whichever fixes the owner
|
|
116
|
+
selects, and your recommendation stands as the default for the rest.
|
|
116
117
|
|
|
117
118
|
Report as: N of M complete, K parked, and what you are working now.
|
|
118
119
|
Close with: what broke, how each one ended, and which of them deserve a
|
package/rules/git-workflow.md
CHANGED
|
@@ -64,10 +64,13 @@ contexts appears on that level's head. A required check that never fired is
|
|
|
64
64
|
invisible debt at every level, and it surfaces only after the whole stack is
|
|
65
65
|
pushed, when the repair costs a second pass over every branch.
|
|
66
66
|
|
|
67
|
-
A red required check blocks the branch, whoever owns the failing line. The
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
A red required check blocks the branch, whoever owns the failing line. The
|
|
68
|
+
staged policy lint grades a change against the file's prior text, so a finding
|
|
69
|
+
that survives is one the change introduced or made worse. Fix that line in the
|
|
70
|
+
next push or report the branch blocked. A finding the change did not introduce
|
|
71
|
+
is a gate-scoping defect: report it against the lint and leave the file's shape
|
|
72
|
+
alone. Restructuring a file to satisfy a mis-scoped check trades one finding for
|
|
73
|
+
a set of new ones. Read the gate's own report rather than a narrower substitute. A
|
|
71
74
|
single-file mypy call cannot see sibling modules and reports false import
|
|
72
75
|
errors, so it neither clears nor convicts a change.
|
|
73
76
|
|
|
@@ -12,7 +12,9 @@ This is the autonomous-run partner to the ambiguous case: research and recommend
|
|
|
12
12
|
|
|
13
13
|
## Do not end a turn on a promise
|
|
14
14
|
|
|
15
|
-
Pause for the user only when the work
|
|
15
|
+
Pause for the user only when the work needs them: a destructive or irreversible action, a scope change, or input only they can give. When you hit one, ask through `AskUserQuestion` and end the turn. Do not end on a promise about work you have not done.
|
|
16
|
+
|
|
17
|
+
A pause is a request you deliver, not a state you enter. Put it in the channel the user reads, name the one input you need and what resumes the moment it arrives, and shape it so a single word answers it. A decision recorded in a status line, a checklist, a working document, or a side thread is a note; the user never learns they are the bottleneck, and the work sits. Keep everything that does not depend on the answer moving while it is outstanding.
|
|
16
18
|
|
|
17
19
|
Before you end any turn, read your last paragraph. If it is a plan, an analysis, a list of next steps, or a statement of intent ("I'll run the tests", "next I'll wire it up"), do that work with tool calls before you stop. End the turn only when the task is done or you are blocked on input only the user can give.
|
|
18
20
|
|
|
@@ -25,5 +25,5 @@ Host, ssh port and ssh user are constants inside the runner and are also under t
|
|
|
25
25
|
|
|
26
26
|
To copy a file, write it inside the script with a quoted heredoc rather than reaching for `scp`.
|
|
27
27
|
|
|
28
|
-
The `/tmp` size limit, how to tell a
|
|
28
|
+
The `/tmp` size limit, how to tell a break in the code from a platform-only one, and a failure-to-cause
|
|
29
29
|
table: `@~/.claude/docs/nas-ssh-invocation.md`.
|
package/rules/research-mode.md
CHANGED
|
@@ -16,8 +16,10 @@ Every recommendation, claim, or piece of advice must cite a specific source:
|
|
|
16
16
|
|
|
17
17
|
If you generate a claim and cannot find a supporting source, retract it. Do not present it.
|
|
18
18
|
|
|
19
|
+
A citation is checked against what the source says, not against whether the source exists. A named authority attached to a claim the authority does not make is weaker than no citation at all, because it stops the reader from asking. This bites hardest on numbers: a threshold that runs stricter or looser than its source is a house call, so label it as one and leave the attribution to the direction the source does support.
|
|
20
|
+
|
|
19
21
|
## 3. Direct quotes for factual grounding
|
|
20
|
-
When working from documents, extract the
|
|
22
|
+
When working from documents, extract the text first before analyzing. Ground your response in word-for-word quotes, not paraphrased summaries. Reference the quote when making your point.
|
|
21
23
|
|
|
22
24
|
## How citations appear in a chat reply
|
|
23
25
|
|
|
@@ -5,12 +5,20 @@ paths:
|
|
|
5
5
|
|
|
6
6
|
# Rules Prose Names Only Hooks That Run
|
|
7
7
|
|
|
8
|
-
A hook module runs when `hooks/hooks.json` registers it or a dispatcher roster hosts it. A module can survive on disk while appearing in neither place, and it then reaches no tool call. Prose that gives such a module a present-tense action describes a gate the reader never faces, and a reader who trusts it skips the check they were meant to run by hand.
|
|
8
|
+
A hook module runs when `hooks/hooks.json` registers it or a dispatcher roster hosts it. A module can survive on disk while appearing in neither place, and it then reaches no tool call. Presence on disk settles nothing in either direction. The installer writes an inert stand-in at a retired hook path when a host's stale `settings.json` still names it, because a registered path that resolves to nothing makes the interpreter exit 2 and the harness reads a PreToolUse exit 2 as a block. A retired hook can also keep working through a different door: its logic moves into a `*_parts/` package that a live module imports, so the hook name is dead while the check it carried still fires. Prose that gives such a module a present-tense action describes a gate the reader never faces, and a reader who trusts it skips the check they were meant to run by hand.
|
|
9
9
|
|
|
10
|
-
The staged policy lint carries this check as its `retired-hook-prose` rule. It reads each Markdown file under a `rules/` directory, takes every backticked hook module name, and reports the ones that are registered nowhere and that carry a present-tense action verb in the rest of the sentence. CI runs that lint against the merge base.
|
|
10
|
+
The staged policy lint carries this check as its `retired-hook-prose` rule. It reads each Markdown file under a `rules/` directory, takes every backticked hook module name, and reports the ones that are registered nowhere and that carry a present-tense action verb in the rest of the sentence. CI runs that lint against the merge base. Its reach stops at that directory. Skill manifests, agent definitions, commands, `docs/` and `_shared/` all carry prose about hooks and none of it is read, so a stale claim there passes CI and reaches every reader. Sweep those trees by hand against the retired roster whenever you retire a hook.
|
|
11
11
|
|
|
12
12
|
A module name counts as a hook when it ends in one of the hook families, such as `_blocker`, `_enforcer`, `_gate`, `_tracker`, or `_dispatcher`, and when it either sits under `hooks/` or appears in `RETIRED_HOOK_REGISTRATION_RELATIVE_PATHS` in `bin/install.mjs`. A support module inside the hooks tree carries no such family suffix, so it stays out of the check. A hook deleted from disk without an entry in that roster resolves nowhere, so add the roster entry when you retire a hook.
|
|
13
13
|
|
|
14
14
|
Two shapes pass. A past-tense sentence that records what a hook once did makes no live claim. A sentence that names the staged policy lint, `cde_lint`, or a repository check tells the reader where the work runs now, so the module name reads as a pointer to code.
|
|
15
15
|
|
|
16
|
+
## Retiring a gate drops the detours it required
|
|
17
|
+
|
|
18
|
+
A gate and the standing orders written to satisfy it are one unit. An order that says to spawn a named agent first, to carry a magic token into a spawn, or to route through an extra step exists because some check demanded it. When the check goes, that order is a toll every later session pays for nothing, and it costs more than a stale sentence does, because a reader obeys it.
|
|
19
|
+
|
|
20
|
+
So retiring a hook is finished only when the detours it required are gone in the same change. Search for the order, not for the module: the module name is what the lint looks for, and a detour usually names the agent, the step, or the token instead, which is how these survive a lint that reads the same file. Drop the requirement and keep the agent, the skill, or the command itself; a capability nobody is forced to call costs nothing, while a forced call costs every run.
|
|
21
|
+
|
|
22
|
+
The same duty covers every lane a withdrawn standard rode on. A threshold enforced by a hook is often also stated in an audit rubric, an agent's instruction table, or a review prompt. Withdraw all of them together, and name the lanes in the archive entry. Removing the fast mechanical lane and leaving the slow judgment lane keeps the standard in force while deleting the text that a reader could argue with.
|
|
23
|
+
|
|
16
24
|
When the rule reports a line, say what the reader faces now. Name the harness permission prompt, the staged policy lint, or the repository check that carries the work, or drop the claim.
|
package/rules/testing.md
CHANGED
|
@@ -14,14 +14,14 @@ paths:
|
|
|
14
14
|
|
|
15
15
|
## Complete Mocks for Testability
|
|
16
16
|
|
|
17
|
-
**Mocks must include all fields the component
|
|
17
|
+
**Mocks must include all fields the component uses.**
|
|
18
18
|
|
|
19
19
|
If a component renders field X, the mock must have field X with a valid value.
|
|
20
20
|
Incomplete mocks make it impossible to distinguish "broken code" from "missing data".
|
|
21
21
|
|
|
22
|
-
## Tests Exercise
|
|
22
|
+
## Tests Exercise Production Behavior
|
|
23
23
|
|
|
24
|
-
Tests exercise
|
|
24
|
+
Tests exercise production behavior, production data, and production code paths. A test that asserts on a stand-in for the production path proves the stand-in works.
|
|
25
25
|
|
|
26
26
|
## No Gate Holds the Test-First Order
|
|
27
27
|
|
|
@@ -19,6 +19,7 @@ Before writing any AskUserQuestion or asking a clarifying question in chat, eval
|
|
|
19
19
|
| Is the answer determined by file naming patterns or contents? | Glob a sample and inspect. |
|
|
20
20
|
| Is the answer a value in a config or environment variable? | Read the config or check the env. |
|
|
21
21
|
| Is the answer retrievable from any available MCP tool? | Use the tool. |
|
|
22
|
+
| Did the user already state a criterion, standard, or line that decides this? | Apply it, state the call and the reason, and keep going. |
|
|
22
23
|
|
|
23
24
|
Only after confirming the answer cannot be obtained through any available tool, ask the user.
|
|
24
25
|
|
|
@@ -37,6 +38,8 @@ Reserve user questions for:
|
|
|
37
38
|
- **Judgment calls** — tradeoffs the user needs to evaluate.
|
|
38
39
|
- **Scope decisions** — what to include or exclude from a piece of work.
|
|
39
40
|
|
|
41
|
+
A preference question is one where the user has not yet given the line. Once they have, every case under that line is yours to decide. Handing back each application of a stated criterion turns one decision into many and stalls the work, because the person who set the standard does not hold the individual answers. Apply the criterion, name the call and the reason it went that way, and escalate only what the criterion cannot settle: a new axis it never covered, or a step nobody can undo. [`long-horizon-autonomy.md`](long-horizon-autonomy.md) carries the same duty for authority the task already granted.
|
|
42
|
+
|
|
40
43
|
## Examples
|
|
41
44
|
|
|
42
45
|
**Wrong:** "Are there multiple images per folder, or just one image + one mp4?"
|
|
@@ -23,7 +23,7 @@ Before stating a runtime claim, gather the matching live signal:
|
|
|
23
23
|
| The server is up | Probe the port; a refused connection means it is down. |
|
|
24
24
|
| The process is running | List processes and match the name or PID. |
|
|
25
25
|
| The change took effect | Drive the flow and watch the new behavior. A script that proves a branch's behavior names the module file it loaded, as its first step, because an installed copy of the same package shadows the checkout you meant to test. |
|
|
26
|
-
| The dependency is reachable | Send one
|
|
26
|
+
| The dependency is reachable | Send one request and read the response. |
|
|
27
27
|
| The release or deploy shipped | Read what it makes: the tag, the published version, the file on disk. |
|
|
28
28
|
| The pipeline did the work | Read each job's own result. A run reports success while a job inside it is skipped. |
|
|
29
29
|
| The automation works | Drive the branch that matters. A green run of the do-nothing branch proves nothing. |
|
|
@@ -39,4 +39,4 @@ Only after a live signal backs the claim do you state it.
|
|
|
39
39
|
**Right:** Tail the request log and confirm the retry fired, or report that no retry line appears.
|
|
40
40
|
|
|
41
41
|
**Wrong:** "The config sets the timeout to 30 seconds, so the timeout is fine."
|
|
42
|
-
**Right:** Print the loaded config at runtime and report the value the process
|
|
42
|
+
**Right:** Print the loaded config at runtime and report the value the process holds.
|