claude-dev-env 7.7.1 → 8.1.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 +5 -6
- package/.agents/agents/issue-tracker.md +1 -1
- package/.agents/agents/pr-description-writer.md +1 -1
- package/.agents/agents/skill-writer-agent.md +1 -12
- package/.agents/agents/test_agent_frontmatter.py +2 -19
- package/.agents/skills/issue-tracker/SKILL.md +1 -1
- package/.agents/skills/orchestrator/SKILL.md +4 -5
- package/.agents/skills/pull-request/SKILL.md +8 -7
- package/.agents/skills/pull-request/reference/publication-tasks.md +1 -1
- package/.agents/skills/team-advisor/SKILL.md +2 -3
- package/_shared/advisor/advisor-protocol.md +0 -1
- package/_shared/advisor/reference/lifecycle.md +0 -1
- package/_shared/advisor/reference/warm-up.md +1 -2
- 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-j-code-rules-compliance.md +1 -2
- package/audit-rubrics/prompts/category-e-dead-code.md +5 -5
- package/audit-rubrics/prompts/category-j-code-rules-compliance.md +1 -24
- package/bin/install-constants.mjs +0 -5
- package/bin/install-pstack-plugin.mjs +192 -0
- package/bin/install-pstack-plugin.test.mjs +181 -0
- package/bin/install.agents-home.test.mjs +0 -4
- package/bin/install.codex-rules.test.mjs +6 -0
- package/bin/install.cursor-rules.test.mjs +3 -253
- package/bin/install.mjs +55 -160
- package/bin/install.test.mjs +110 -149
- package/bin/prune-retired-pstack-store.mjs +83 -0
- package/bin/prune-retired-pstack-store.test.mjs +105 -0
- package/bin/prune-session-continuity.mjs +57 -0
- package/bin/prune-session-continuity.test.mjs +70 -0
- package/bin/resolve-install-root.mjs +2 -0
- package/bin/resolve-install-root.test.mjs +69 -0
- package/docs/CODE_RULES.md +1 -1
- package/docs/agent-spawn-protocol.md +1 -1
- package/docs/codex-compatibility.md +4 -16
- package/docs/nas-ssh-invocation.md +1 -1
- package/docs/references/prose-style-enforcement.md +2 -2
- package/hooks/HOOK_SPECS_PROMPT_WORKFLOW.md +1 -3
- package/hooks/blocking/code_rules_constants_config.py +1 -108
- package/hooks/blocking/code_rules_enforcer.py +9 -5
- package/hooks/blocking/code_rules_test_layout.py +6 -7
- package/hooks/blocking/test_code_rules_constants_config.py +13 -0
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +15 -0
- package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +0 -60
- package/hooks/blocking/test_context_control_policy_files.py +0 -11
- package/hooks/hooks_constants/blocking_check_limits.py +1 -1
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +0 -1
- package/hooks/hooks_constants/setup_project_paths_constants.py +1 -2
- package/hooks/session/test_untracked_repo_detector.py +1 -1
- package/hooks/validators/code_quality_checks.py +15 -2
- package/hooks/validators/test_code_quality_checks.py +22 -0
- package/package.json +1 -2
- package/rules/anti-corollary-tests.md +3 -1
- package/rules/archiving-agent-config.md +70 -0
- package/rules/asd-ste100-language.md +1 -1
- package/rules/ci-owns-the-gate.md +73 -0
- package/rules/cleanup-temp-files.md +1 -1
- package/rules/code-standards.md +3 -4
- package/rules/docstring-prose-matches-implementation.md +3 -3
- package/rules/explore-thoroughly.md +2 -2
- package/rules/failure-blast-radius.md +10 -9
- package/rules/git-workflow.md +27 -12
- package/rules/long-horizon-autonomy.md +3 -1
- package/rules/nas-ssh-invocation.md +1 -1
- package/rules/orphan-css-class.md +1 -1
- package/rules/paired-test-coverage.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 +4 -1
- package/rules/verify-runtime-state.md +2 -2
- package/rules/windows-filesystem-safe.md +1 -1
- package/rules/workflow-substitution-slots.md +1 -1
- package/scripts/Sync-RepoMain.ps1 +71 -6
- package/scripts/policy_lint/adapter_detectors.py +116 -10
- package/scripts/policy_lint/config/approved_test_pairs.py +12 -0
- package/scripts/policy_lint/config/constants.py +3 -0
- package/scripts/tests/Sync-RepoMain.Tests.ps1 +108 -0
- package/scripts/tests/test_codex_compat_materializer.py +3 -3
- package/scripts/tests/test_policy_lint_rules_validator_baseline.py +126 -0
- package/.agents/skills/session-continuity/AGENTS.md +0 -1
- package/.agents/skills/session-continuity/CLAUDE.md +0 -1
- package/.agents/skills/session-continuity/README.md +0 -223
- package/.agents/skills/session-continuity/SKILL.md +0 -125
- package/.agents/skills/session-continuity/continuity.mjs +0 -445
- package/.agents/skills/session-continuity/continuity.test.mjs +0 -381
- package/bin/install-session-continuity.mjs +0 -131
- package/bin/install-session-continuity.test.mjs +0 -106
- package/bin/install.pstack-plugin.test.mjs +0 -115
- package/bin/pstack-codex-discovery.test.mjs +0 -79
- package/bin/pstack-model-preferences.claude.json +0 -23
- package/bin/pstack-model-preferences.codex.json +0 -24
- package/bin/pstack.mjs +0 -392
- package/bin/pstack.test.mjs +0 -347
- package/bin/refresh-pstack-plugin-skills.test.mjs +0 -211
- package/bin/select-pstack-models.test.mjs +0 -776
- package/hooks/blocking/test_code_rules_enforcer_file_global_constants.py +0 -231
- package/rules/agent-spawn-protocol.md +0 -9
- package/rules/ask-user-question-required.md +0 -31
- package/rules/claims-as-quotes.md +0 -55
- package/rules/confirm-implementation-forks.md +0 -11
- package/rules/file-global-constants.md +0 -81
- package/rules/hedging-claims.md +0 -7
- package/rules/measurement-denominators.md +0 -39
- package/rules/prompt-workflow-context-controls.md +0 -19
- package/rules/pstack-host-mapping.md +0 -48
- package/rules/pstack-models.md +0 -142
- package/rules/vault-context.md +0 -5
- package/scripts/pstack-adapters/common.md +0 -17
- package/scripts/pstack-adapters/create-skill.md +0 -14
- package/scripts/pstack-adapters/host-claude.md +0 -7
- package/scripts/pstack-adapters/host-codex.md +0 -11
- package/scripts/pstack-adapters/host-cursor.md +0 -7
- package/scripts/pstack.lock.json +0 -11
- package/scripts/refresh_pstack_plugin_skills.mjs +0 -200
- package/scripts/select_pstack_models.mjs +0 -469
- /package/.agents/{skills → skills-archived}/source-command-logifix/SKILL.md +0 -0
|
@@ -127,3 +127,25 @@ class TestFileLength:
|
|
|
127
127
|
assert "400" in violations[0].message or "lines" in violations[0].message.lower()
|
|
128
128
|
finally:
|
|
129
129
|
temp_path.unlink()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class TestTestFileExemption:
|
|
133
|
+
def test_long_function_in_a_test_file_passes(self) -> None:
|
|
134
|
+
tree = ast.parse(BAD_LONG_FUNCTION)
|
|
135
|
+
violations = check_function_length(tree, "packages/app/test_widget.py")
|
|
136
|
+
assert violations == []
|
|
137
|
+
|
|
138
|
+
def test_long_function_outside_a_test_file_still_fails(self) -> None:
|
|
139
|
+
tree = ast.parse(BAD_LONG_FUNCTION)
|
|
140
|
+
violations = check_function_length(tree, "packages/app/widget.py")
|
|
141
|
+
assert len(violations) == 1
|
|
142
|
+
|
|
143
|
+
def test_long_test_file_passes(self, tmp_path: Path) -> None:
|
|
144
|
+
temp_path = tmp_path / "test_widget.py"
|
|
145
|
+
temp_path.write_text("x = 1\n" * 450, encoding="utf-8")
|
|
146
|
+
assert check_file_length(temp_path) == []
|
|
147
|
+
|
|
148
|
+
def test_long_conftest_passes(self, tmp_path: Path) -> None:
|
|
149
|
+
temp_path = tmp_path / "conftest.py"
|
|
150
|
+
temp_path.write_text("x = 1\n" * 450, encoding="utf-8")
|
|
151
|
+
assert check_file_length(temp_path) == []
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-dev-env",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"claude-dev-env": "bin/install.mjs",
|
|
8
|
-
"cde-pstack": "bin/pstack.mjs",
|
|
9
8
|
"codex-compat": "bin/codex-compat.mjs",
|
|
10
9
|
"cde": "bin/cde.mjs"
|
|
11
10
|
},
|
|
@@ -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,70 @@
|
|
|
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
|
+
Three 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.
|
|
54
|
+
|
|
55
|
+
**Add the archived name to the banned active-capability list.** The reference
|
|
56
|
+
checker in `scripts/active_capability_references.py` does not resolve a named
|
|
57
|
+
capability against the shipped inventory; it reports a name only when that name
|
|
58
|
+
sits on `ALL_BANNED_ACTIVE_CAPABILITY_NAMES`. Until the archived name is on that
|
|
59
|
+
list, every leftover mention of it passes.
|
|
60
|
+
|
|
61
|
+
**A renamed skill directory takes its tests out of the run.** The node test
|
|
62
|
+
command globs `.agents/skills/**/*.test.mjs`, so a suite under an archived skill
|
|
63
|
+
stops running without failing. Check that the count you expect still runs.
|
|
64
|
+
|
|
65
|
+
## Sibling rules
|
|
66
|
+
|
|
67
|
+
| Rule | Role |
|
|
68
|
+
|---|---|
|
|
69
|
+
| [`retired-hook-prose.md`](retired-hook-prose.md) | Prose names only hooks that run, and retiring a gate drops the detours it required |
|
|
70
|
+
| [`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
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# CI Owns the Gate
|
|
2
|
+
|
|
3
|
+
**When this applies:** Before pushing a branch, and any time a repository's full
|
|
4
|
+
check suite or policy gate is about to run on your own machine.
|
|
5
|
+
|
|
6
|
+
## Rule
|
|
7
|
+
|
|
8
|
+
The gate runs once, and it runs on CI. Push the branch, read the verdict, act on
|
|
9
|
+
what it says.
|
|
10
|
+
|
|
11
|
+
The inner development loop stays yours. Run the single test you are writing, as
|
|
12
|
+
often as it helps. That is how the change gets built. This rule governs the
|
|
13
|
+
second full pass, the one whose only product is a prediction of CI's answer.
|
|
14
|
+
Push instead, and spend the wait on the next piece of work.
|
|
15
|
+
|
|
16
|
+
## Why
|
|
17
|
+
|
|
18
|
+
**A pinned gate answers only from its pinned revision.** The workflow names an
|
|
19
|
+
exact revision of the policy package, and that revision decides which rules run.
|
|
20
|
+
The copy under your home directory is a separate artifact at its own revision. A
|
|
21
|
+
run against the home copy reports on those rules, which are a different question
|
|
22
|
+
from the one CI asks. Treat its exit code as information about the home copy
|
|
23
|
+
alone.
|
|
24
|
+
|
|
25
|
+
**Self-hosted runners often share your machine.** Where the runners execute on
|
|
26
|
+
the same host as your shell, a local suite run draws its processor time from the
|
|
27
|
+
runners, and it does so while they work on the branch you just pushed. Read
|
|
28
|
+
where the runners live, and count a local run against the same budget.
|
|
29
|
+
|
|
30
|
+
**One authoritative answer beats two.** Where both runs agree, the second one
|
|
31
|
+
restated the first. Where they differ, the environments differ, and CI is the
|
|
32
|
+
environment that decides.
|
|
33
|
+
|
|
34
|
+
## Running a gate locally
|
|
35
|
+
|
|
36
|
+
Clone the revision the workflow pins, then point the gate at that clone. That
|
|
37
|
+
run asks CI's question and its answer carries. Report a local result by naming
|
|
38
|
+
the revision it used, so a reader can tell which question it answered.
|
|
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
|
+
|
|
55
|
+
## The verdict belongs to CI
|
|
56
|
+
|
|
57
|
+
CI decides whether a change passed, from evidence CI gathered. Keep that loop
|
|
58
|
+
closed. A flag, trailer, receipt, or environment variable through which the
|
|
59
|
+
change under test announces its own result hands the verdict to the subject.
|
|
60
|
+
Where the runner and the agent share one host, a signature names the same party
|
|
61
|
+
twice, so it carries the claim no further.
|
|
62
|
+
|
|
63
|
+
A cache stays available on one condition. CI derives the key itself from the
|
|
64
|
+
tree it is about to test, looks for a previous run under that key, and
|
|
65
|
+
republishes that result. CI computes, CI verifies, CI decides.
|
|
66
|
+
|
|
67
|
+
## Sibling rules
|
|
68
|
+
|
|
69
|
+
| Rule | Role |
|
|
70
|
+
|---|---|
|
|
71
|
+
| [`git-workflow.md`](git-workflow.md) | Confirm each required context fired after the push |
|
|
72
|
+
| [`verify-runtime-state.md`](verify-runtime-state.md) | A status field is a report; read the thing the work was meant to make |
|
|
73
|
+
| [`falsify-before-green.md`](falsify-before-green.md) | A green counts as evidence once the check has run red on a deliberate break |
|
|
@@ -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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Canonical review contract:** [`CODE_RULES.md`](../docs/CODE_RULES.md) — the human and AI review contract for code quality, loaded on demand.
|
|
4
4
|
> **Checked-in pointer:** [`.cursor/BUGBOT.md`](../../../.cursor/BUGBOT.md) — the file Cursor BugBot reads; it points at `CODE_RULES.md`.
|
|
5
|
-
> **Production enforcement.** The staged policy lint runs `hooks/blocking/code_rules_enforcer.py` over each changed file. No write-time hook runs it.
|
|
5
|
+
> **Production enforcement.** The staged policy lint runs `hooks/blocking/code_rules_enforcer.py` over each changed file. No write-time hook runs it. CI runs that lint against the merge base. Each mechanical rule carries a synchronization test.
|
|
6
6
|
|
|
7
7
|
## Policy surface map
|
|
8
8
|
|
|
@@ -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
|
|
|
@@ -27,7 +27,6 @@ BDD is the outer process and TDD is the inner loop: [`bdd.md`](bdd.md) discovers
|
|
|
27
27
|
|
|
28
28
|
| Concern | Rule file |
|
|
29
29
|
|---|---|
|
|
30
|
-
| Question routing | [`ask-user-question-required.md`](ask-user-question-required.md) |
|
|
31
30
|
| Task tracking / worker completion | [`workers-done-before-complete.md`](workers-done-before-complete.md) |
|
|
32
31
|
| Multi-step task list | skill `task-build` (see agents catalog) |
|
|
33
32
|
|
|
@@ -28,15 +28,15 @@ Read the body and the docstring side by side. Apply each check that matches the
|
|
|
28
28
|
- **Gate-outcome status flags** — an outcome routed to a blocker (`blocker = ...; break`) reads as blocked everywhere, never as a bypass.
|
|
29
29
|
- **Returns / Raises / Note claims** — each free-form claim matches the body.
|
|
30
30
|
|
|
31
|
-
Many deterministic shapes of this drift are checked in `code_rules_docstrings.py` (and the JS and `.mjs` slices in `code_rules_imports_logging.py`). The staged policy lint reaches both through `code_rules_enforcer.py`, and
|
|
31
|
+
Many deterministic shapes of this drift are checked in `code_rules_docstrings.py` (and the JS and `.mjs` slices in `code_rules_imports_logging.py`). The staged policy lint reaches both through `code_rules_enforcer.py`, and CI runs it against the merge base. Free-form rest is judgment.
|
|
32
32
|
|
|
33
33
|
## Hook prose matches its detector
|
|
34
34
|
|
|
35
35
|
A hook module is the sharpest case of the same rule: its docstring lead narrative and its `CORRECTIVE_MESSAGE` describe exactly the shapes the detector flags, and claim no broader trigger surface than the regex enforces.
|
|
36
36
|
|
|
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
|
|
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,13 +58,13 @@ 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
|
|
|
67
|
-
`code_rules_blast_radius.py` runs inside `code_rules_enforcer.py`, which the staged policy lint applies to each changed file under its `code-rules` rule. No write-time hook runs it, so
|
|
67
|
+
`code_rules_blast_radius.py` runs inside `code_rules_enforcer.py`, which the staged policy lint applies to each changed file under its `code-rules` rule. No write-time hook runs it, so CI is where it reports. CI runs the same lint against the merge base.
|
|
68
68
|
|
|
69
69
|
The check requires each raised type written directly inside a loop body to end in `RunFatal` or `ItemBlocked`. The lexical check covers raises written directly in loop bodies. Shared helpers carry multiple caller contexts, so their callers classify the boundary.
|
|
70
70
|
|
|
@@ -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
|
@@ -29,9 +29,10 @@ opens with the bot's own marker line. The description rules in this file, the
|
|
|
29
29
|
failure signature in the release job log reads
|
|
30
30
|
`could not parse pull request body as a release PR`.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
The `pr-description-writer` agent writes a title and body from the diff when
|
|
33
|
+
you want one. Publish the title and body file through
|
|
34
|
+
`~/.agents/skills/pull-request/scripts/pull_request.py`. That path is under the
|
|
35
|
+
agents home, not the repository. A worktree holds no `.agents/` copy.
|
|
35
36
|
|
|
36
37
|
Resolve the active managed root (`CLAUDE_CONFIG_DIR` when set, `~/.claude`
|
|
37
38
|
otherwise), then run `<managed-root>/scripts/durable_post_lint.py` before any
|
|
@@ -50,14 +51,28 @@ untouched.
|
|
|
50
51
|
- Before push: `gh pr ready --undo`
|
|
51
52
|
- After review approved: `gh pr ready`
|
|
52
53
|
|
|
53
|
-
##
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
## Confirm the required checks fired, and let CI run them
|
|
55
|
+
|
|
56
|
+
The gate runs once, and it runs on CI. Push the branch and read its verdict.
|
|
57
|
+
[`ci-owns-the-gate.md`](ci-owns-the-gate.md) holds the reasoning and the shape
|
|
58
|
+
a local run takes when one is warranted.
|
|
59
|
+
|
|
60
|
+
Read the branch ruleset for the required check contexts before you push a
|
|
61
|
+
branch, or any level of a stack: `gh api repos/<owner>/<repo>/rules/branches/<trunk>`.
|
|
62
|
+
Read it to learn which checks must report. After the push, confirm each of those
|
|
63
|
+
contexts appears on that level's head. A required check that never fired is
|
|
64
|
+
invisible debt at every level, and it surfaces only after the whole stack is
|
|
65
|
+
pushed, when the repair costs a second pass over every branch.
|
|
66
|
+
|
|
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
|
|
74
|
+
single-file mypy call cannot see sibling modules and reports false import
|
|
75
|
+
errors, so it neither clears nor convicts a change.
|
|
61
76
|
|
|
62
77
|
A checks listing that reports nothing on the branch is a finding, not a neutral
|
|
63
78
|
state. Find out whether the workflow's event filters exclude the branch, or whether
|
|
@@ -82,7 +97,7 @@ what it calls.
|
|
|
82
97
|
Force-with-lease protects the ref. It protects nobody's understanding of what the
|
|
83
98
|
branch now holds. When a rewrite moves content between levels of a stack, or
|
|
84
99
|
otherwise changes what a branch contains, refresh that pull request's description
|
|
85
|
-
|
|
100
|
+
before you ask anyone to read or merge it.
|
|
86
101
|
|
|
87
102
|
## Never commit working documents or images
|
|
88
103
|
|
|
@@ -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 truly needs them: a destructive or irreversible action, a
|
|
15
|
+
Pause for the user only when the work truly 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`.
|
|
@@ -15,7 +15,7 @@ When you add a `class="..."` attribute, add its `.<class>` selector to the `<sty
|
|
|
15
15
|
|
|
16
16
|
## What the check covers
|
|
17
17
|
|
|
18
|
-
The `check_orphan_css_classes` check in `code_rules_orphan_css_class.py` reaches production Python through the staged policy lint, whose `code-rules` rule loads `code_rules_enforcer.py` and applies it to each changed file.
|
|
18
|
+
The `check_orphan_css_classes` check in `code_rules_orphan_css_class.py` reaches production Python through the staged policy lint, whose `code-rules` rule loads `code_rules_enforcer.py` and applies it to each changed file. CI runs that lint against the merge base. It:
|
|
19
19
|
|
|
20
20
|
1. Collects each class name referenced in a `class="..."` attribute across the file's string literals.
|
|
21
21
|
2. Collects each class selector defined in a `<style>` block — both in the file under edit and in every Python module beside it (its own directory and immediate child directories), since a markup module commonly imports its style constant from a companion package directory.
|
|
@@ -18,7 +18,7 @@ When you add a public function to a module whose test suite already exercises th
|
|
|
18
18
|
|
|
19
19
|
## What the check covers
|
|
20
20
|
|
|
21
|
-
Two complementary checks in `code_rules_paired_test.py` reach changed files through `code_rules_enforcer.py`, which the staged policy lint runs under its `code-rules` rule. No write-time hook runs them, so
|
|
21
|
+
Two complementary checks in `code_rules_paired_test.py` reach changed files through `code_rules_enforcer.py`, which the staged policy lint runs under its `code-rules` rule. No write-time hook runs them, so CI is where they report, against the merge base. The two checks cover the two write orders.
|
|
22
22
|
|
|
23
23
|
`check_public_function_missing_paired_test` runs on a production Python write or edit and flags a public function when all of these hold:
|
|
24
24
|
|
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.
|
|
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
|
|
|
@@ -27,7 +28,7 @@ Only after confirming the answer cannot be obtained through any available tool,
|
|
|
27
28
|
A path, port, branch name, or config value you recall from an earlier session counts as unanswered until a tool re-checks it this session. Memory records what was true when it was written; the file may have moved, the port may be down, the branch may have merged. Treat every recalled fact as a claim to re-ground, not an answer to reuse.
|
|
28
29
|
|
|
29
30
|
- When a tool can settle it, re-check in silence and act on the fresh result — no question to the user.
|
|
30
|
-
- When no tool can settle it and the user has a stake in the answer, ask through `AskUserQuestion
|
|
31
|
+
- When no tool can settle it and the user has a stake in the answer, ask through `AskUserQuestion`.
|
|
31
32
|
|
|
32
33
|
## Questions That Belong to the User
|
|
33
34
|
|
|
@@ -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.
|
|
@@ -12,6 +12,6 @@ Never call `shutil.rmtree` with `ignore_errors=True` — Windows `ReadOnly` file
|
|
|
12
12
|
|
|
13
13
|
In Node, call `mkdirSync(targetPath, { recursive: true })` on possibly-existing paths — `ReadOnly` directories break the non-recursive form. When the call must be non-recursive, strip the attribute first (`(Get-Item $path -Force).Attributes = "Directory"` / `os.chmod(path, stat.S_IWRITE)`).
|
|
14
14
|
|
|
15
|
-
The staged policy lint carries this check as its `rmtree-safety` rule. It reports the unsafe rmtree pattern and returns the full `force_rmtree` safe-pattern code.
|
|
15
|
+
The staged policy lint carries this check as its `rmtree-safety` rule. It reports the unsafe rmtree pattern and returns the full `force_rmtree` safe-pattern code. CI runs that lint against the merge base.
|
|
16
16
|
|
|
17
17
|
Define the safe handler trio (`_strip_read_only_and_retry`, `_force_remove_tree` / `force_rmtree`, and the `inspect.signature` onexc/onerror guard) once in a shared Windows-filesystem utility module, and import it from every call site. A second local copy drifts from the first, so a fix lands in one and the other keeps the bug (CODE_RULES.md, CORE PRINCIPLES, "Reuse before create"). The same `rmtree-safety` lint rule reports a local re-definition of any trio member outside the shared home and points the writer at the import. This complements the same-directory `check_duplicate_function_body_across_files` check, which a copy between two distant packages slips past.
|
|
@@ -9,4 +9,4 @@ In a `.workflow.js` agent-prompt template, every per-call or per-iteration value
|
|
|
9
9
|
|
|
10
10
|
When a loop builds a per-iteration path or output key, write the index as a slot — `cand_<i>` — or spell out `replace <i> with the iteration index 0, 1, 2` in the step text. Every per-call value in a `.workflow.js` template carries angle brackets so an agent fills in a fresh value per call.
|
|
11
11
|
|
|
12
|
-
The staged policy lint carries this check as its `workflow-substitution` rule. It reports a `.workflow.js` file whose looped content holds a bare `<word>_<i|j|k>` token as a per-iteration path segment.
|
|
12
|
+
The staged policy lint carries this check as its `workflow-substitution` rule. It reports a `.workflow.js` file whose looped content holds a bare `<word>_<i|j|k>` token as a per-iteration path segment. CI runs that lint against the merge base. No write-time hook reports this, so a bare token stays on disk until the lint runs.
|