claude-dev-env 2.18.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/AGENTS.md +4 -4
- package/.agents/skills/_shared/AGENTS.md +1 -0
- package/.agents/skills/_shared/pr-loop/AGENTS.md +1 -0
- package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +119 -0
- package/.agents/skills/_shared/pr-loop/preflight-proposal.md +5 -0
- package/.agents/skills/e-code-review/SKILL.md +12 -1
- package/.agents/skills/e-code-review/reference/fix.md +5 -1
- package/.agents/skills/e-code-review/reference/loop.md +4 -0
- package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +66 -0
- package/.agents/skills/e-code-review/reference/preflight-proposal.md +40 -0
- package/.agents/skills/e-code-review/reference/runner-selection.md +1 -0
- package/.agents/skills/pr-cleanup/SKILL.md +105 -75
- package/.agents/skills/pr-cleanup/reference/process-inventory.md +15 -0
- package/.agents/skills/pr-cleanup/reference/task-seeds.md +20 -0
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/SKILL.md +18 -12
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/offense-examples.md +1 -1
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/task-seeds.md +3 -2
- package/.agents/skills/pr-refinement/SKILL.md +31 -0
- package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/SKILL.md +24 -7
- package/.agents/skills/{small-cl → pr-small-cl}/SKILL.md +1 -1
- package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +33 -5
- package/.agents/skills/skill-builder/SKILL.md +1 -0
- package/.agents/skills-archived/bugteam/SKILL.md +1 -1
- package/.agents/skills-archived/bugteam/test_skill_additions.py +1 -1
- package/.agents/skills-archived/comments/SKILL.md +1 -1
- package/.agents/skills-archived/descriptions/SKILL.md +1 -1
- package/.agents/skills-archived/reviews/SKILL.md +1 -1
- package/AGENTS.md +1 -1
- package/_shared/pr-loop/AGENTS.md +2 -1
- package/_shared/pr-loop/preflight-proposal.md +56 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +29 -6
- package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_arguments.py +15 -3
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +47 -4
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +4 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +47 -0
- package/bin/ever-shipped-skills.mjs +14 -0
- package/bin/install-constants.mjs +5 -0
- package/bin/install.agents-home.test.mjs +23 -0
- package/bin/install.codex-rules.test.mjs +61 -6
- package/bin/install.mjs +57 -9
- package/bin/install.prune.test.mjs +65 -3
- package/bin/install.test.mjs +202 -2
- package/docs/CODE_RULES.md +6 -0
- package/hooks/advisory/conftest.py +10 -0
- package/hooks/advisory/migration_safety_advisor.py +14 -14
- package/hooks/advisory/refactor_guard.py +250 -144
- package/hooks/advisory/refactor_guard_test_support.py +46 -0
- package/hooks/advisory/test_migration_safety_advisor.py +120 -0
- package/hooks/advisory/test_refactor_guard_advisory.py +171 -0
- package/hooks/advisory/test_refactor_guard_eligibility.py +166 -0
- package/hooks/atomic_file_writer.py +81 -0
- package/hooks/blocking/AGENTS.md +2 -1
- package/hooks/blocking/block_main_commit.py +66 -33
- package/hooks/blocking/code_rules_banned_identifiers.py +55 -4
- package/hooks/blocking/code_rules_blast_radius.py +194 -0
- package/hooks/blocking/code_rules_enforcer.py +12 -0
- package/hooks/blocking/code_rules_enforcer_test_support.py +92 -0
- package/hooks/blocking/destructive_command_blocker.py +8 -7
- package/hooks/blocking/pre_tool_use_dispatcher.py +11 -7
- package/hooks/blocking/precommit_code_rules_gate.py +14 -139
- package/hooks/blocking/sensitive_file_protector.py +8 -6
- package/hooks/blocking/session_edit_stage_gate.py +31 -1
- package/hooks/blocking/test_block_main_commit.py +145 -0
- package/hooks/blocking/test_claude_md_orphan_file_blocker.py +171 -1
- package/hooks/blocking/test_code_rules_blast_radius.py +161 -0
- package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +37 -12
- package/hooks/blocking/test_code_rules_enforcer_banned_noun_word.py +54 -0
- package/hooks/blocking/test_code_rules_enforcer_duplicate_body_hook_routing.py +15 -53
- package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +13 -62
- package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +309 -0
- package/hooks/blocking/test_code_rules_enforcer_precheck_forecast.py +14 -71
- package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +14 -16
- package/hooks/blocking/test_code_rules_enforcer_split_entry_2.py +31 -46
- package/hooks/blocking/test_code_rules_enforcer_stage.py +192 -0
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +13 -59
- package/hooks/blocking/test_destructive_command_blocker.py +154 -138
- package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +85 -25
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +58 -38
- package/hooks/blocking/test_destructive_command_blocker_patterns.py +133 -0
- package/hooks/blocking/test_docstring_rule_gate_count_blocker.py +113 -1
- package/hooks/blocking/test_env_var_table_code_drift_blocker.py +70 -3
- package/hooks/blocking/test_hook_subprocess_support.py +296 -0
- package/hooks/blocking/test_package_inventory_stale_blocker.py +1 -1
- package/hooks/blocking/test_pii_scanner.py +81 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +32 -3
- package/hooks/blocking/test_precommit_code_rules_gate.py +11 -16
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +234 -0
- package/hooks/blocking/test_pytest_testpaths_orphan_blocker.py +25 -18
- package/hooks/blocking/test_sensitive_file_protector.py +145 -5
- package/hooks/blocking/test_session_edit_stage_gate_staging.py +64 -0
- package/hooks/blocking/test_session_edit_stage_gate_support.py +204 -0
- package/hooks/blocking/test_session_edit_stage_gate_tracker.py +116 -0
- package/hooks/blocking/test_shared_stdin_adoption.py +31 -20
- package/hooks/blocking/test_test_preflight_check.py +80 -0
- package/hooks/git-hooks/AGENTS.md +1 -1
- package/hooks/git-hooks/git_hooks_constants/__init__.py +1 -0
- package/hooks/git-hooks/post_commit.py +160 -51
- package/hooks/git-hooks/pre_commit.py +9 -5
- package/hooks/git-hooks/test_post_commit.py +203 -0
- package/hooks/git-hooks/test_pre_commit.py +2 -2
- package/hooks/git-hooks/test_pre_push.py +57 -0
- package/hooks/hooks_constants/AGENTS.md +3 -1
- package/hooks/hooks_constants/atomic_file_writer_constants.py +4 -0
- package/hooks/hooks_constants/banned_identifiers_constants.py +1 -0
- package/hooks/hooks_constants/blast_radius_constants.py +14 -0
- package/hooks/hooks_constants/destructive_command_environment_constants.py +18 -0
- package/hooks/hooks_constants/destructive_command_segment_constants.py +1 -11
- package/hooks/hooks_constants/hardcoded_user_path_constants.py +9 -3
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +1 -1
- package/hooks/hooks_constants/refactor_guard_constants.py +75 -0
- package/hooks/hooks_constants/sensitive_file_protector_constants.py +2 -4
- package/hooks/hooks_constants/test_refactor_guard_constants.py +21 -0
- package/hooks/json_file_reader.py +22 -0
- package/hooks/observability/test_instructions_loaded_logger.py +54 -0
- package/hooks/pending_sidecars.py +33 -0
- package/hooks/session/test_plugin_data_dir_cleanup.py +70 -0
- package/hooks/session/test_session_edit_tracker_cleanup.py +16 -3
- package/hooks/test_atomic_file_writer.py +73 -0
- package/hooks/test_json_file_reader.py +24 -0
- package/hooks/test_pending_sidecars.py +25 -0
- package/hooks/validation/mypy_validator.py +213 -80
- package/hooks/validation/test_mypy_validator.py +288 -13
- package/hooks/workflow/auto_formatter.py +225 -93
- package/hooks/workflow/investigation_tracker_reset.py +2 -0
- package/hooks/workflow/test_auto_formatter.py +261 -12
- package/hooks/workflow/test_investigation_tracker_reset.py +90 -0
- package/package.json +1 -1
- package/rules/failure-blast-radius.md +126 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/fetch-commands.md +0 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/report-template.md +0 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/rule-checklist.md +0 -0
- /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/examples.md +0 -0
- /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/offense-taxonomy.md +0 -0
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: name-by-capability
|
|
2
|
+
name: pr-name-by-capability
|
|
3
3
|
description: >-
|
|
4
4
|
Audit a GitHub PR for name-by-capability violations: driver/motive words on
|
|
5
5
|
reusable capability modules (queues and report routers may keep the driver
|
|
6
6
|
word), then apply capability-oriented renames by default. Triggers:
|
|
7
|
-
/name-by-capability
|
|
7
|
+
/pr-name-by-capability, name-by-capability audit, audit PR for naming, name
|
|
8
8
|
by capability, capability naming review, cert_fix rename check, driver word in
|
|
9
9
|
package name.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Name-by-Capability Audit
|
|
13
13
|
|
|
14
|
-
Audit a GitHub PR against the **name-by-capability** rule. Inspect paths and title wording for driver
|
|
14
|
+
Audit a GitHub PR against the **name-by-capability** rule. Inspect paths and title wording for driver or motive words on reusable capability code, and report violations with capability-oriented rename directions.
|
|
15
|
+
|
|
16
|
+
## Mode routing
|
|
17
|
+
|
|
18
|
+
First-match routing selects the mode before the audit steps:
|
|
19
|
+
|
|
20
|
+
1. `preflight-proposal` runs `pr-name-by-capability preflight-proposal <pr_number> --base-sha <base_sha> --head-sha <head_sha> --worktree <isolated_worktree>` under the [shared preflight proposal contract](../_shared/pr-loop/preflight-proposal.md). Record each finding with violation or OK-driver classification.
|
|
21
|
+
2. `audit-only` is report-only and ends after the findings report.
|
|
22
|
+
3. A user-supplied rename or fix direction follows the existing normal fix workflow.
|
|
23
|
+
4. Normal mode applies the suggested rename direction by default.
|
|
15
24
|
|
|
16
25
|
## Gotchas
|
|
17
26
|
|
|
@@ -21,15 +30,10 @@ Audit a GitHub PR against the **name-by-capability** rule. Inspect paths and tit
|
|
|
21
30
|
|
|
22
31
|
## When this applies
|
|
23
32
|
|
|
24
|
-
- User invokes `/name-by-capability
|
|
33
|
+
- User invokes `/pr-name-by-capability <PR>` or asks to audit a PR for name-by-capability / capability naming.
|
|
25
34
|
- PR adds or renames packages/modules, or frames a general shared operation with a driver/motive word (`cert_fix`, `cert_closeout`, `portal`, `export`, …).
|
|
26
35
|
|
|
27
|
-
**
|
|
28
|
-
|
|
29
|
-
- Missing PR number or URL → respond exactly: `Give a GitHub PR number or URL to audit for name-by-capability.`
|
|
30
|
-
- User requests audit-only → finish the audit report and stop.
|
|
31
|
-
- User gives a rename or fix direction → finish the audit report, then apply the direction they gave.
|
|
32
|
-
- A violation with no user-supplied direction → finish the audit report, then apply the suggested rename direction by default.
|
|
36
|
+
A missing PR number or URL returns exactly: `Give a GitHub PR number or URL to audit for name-by-capability.` Resolved targets follow **Mode routing**.
|
|
33
37
|
|
|
34
38
|
## Constraints
|
|
35
39
|
|
|
@@ -39,7 +43,7 @@ Audit a GitHub PR against the **name-by-capability** rule. Inspect paths and tit
|
|
|
39
43
|
|
|
40
44
|
## Process
|
|
41
45
|
|
|
42
|
-
Register every bullet from `reference/task-seeds.md`
|
|
46
|
+
Register every bullet from `reference/task-seeds.md` with `update_plan`. Mark each complete with evidence. Follow those seeds in order — do not restate them here.
|
|
43
47
|
|
|
44
48
|
Load order for the rule: if `docs/agents/name-by-capability.md` exists, read it first; always keep `reference/rule-checklist.md` as the fallback when the doc is missing. On disagreement after the docs PR merges, prefer the repo doc and update the skill checklist in a follow-up.
|
|
45
49
|
|
|
@@ -47,7 +51,7 @@ Load order for the rule: if `docs/agents/name-by-capability.md` exists, read it
|
|
|
47
51
|
|
|
48
52
|
| Peer | Relationship |
|
|
49
53
|
|------|----------------|
|
|
50
|
-
| `shared-extraction
|
|
54
|
+
| `pr-shared-extraction` | Layering and extraction (where code lives). Invoke when a path’s *role* is unclear; this skill only scores the *name*. |
|
|
51
55
|
| `reviews` / PR review skills | May invoke this skill by name when naming is in scope |
|
|
52
56
|
|
|
53
57
|
## File index
|
|
@@ -60,6 +64,8 @@ Load order for the rule: if `docs/agents/name-by-capability.md` exists, read it
|
|
|
60
64
|
| `reference/fetch-commands.md` | Minimal `gh` fetch for PR naming surface |
|
|
61
65
|
| `reference/report-template.md` | Compact report shape |
|
|
62
66
|
| `reference/task-seeds.md` | Ordered task seeds for the audit run |
|
|
67
|
+
| `../_shared/pr-loop/preflight-proposal.md` | Shared isolated proposal mode and evidence record |
|
|
68
|
+
| `../_shared/pr-loop/preflight-proposal.contract.test.mjs` | Cross-skill mode and contract test |
|
|
63
69
|
|
|
64
70
|
## Folder map
|
|
65
71
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Offense examples (this repo)
|
|
2
2
|
|
|
3
|
-
Classify by **role** — the reusable work the surface performs — not by matching a string list. For whether code belongs in `shared_utils` vs a workflow package, invoke `shared-extraction
|
|
3
|
+
Classify by **role** — the reusable work the surface performs — not by matching a string list. For whether code belongs in `shared_utils` vs a workflow package, invoke `pr-shared-extraction`; this map only scores names.
|
|
4
4
|
|
|
5
5
|
## Quick classifier
|
|
6
6
|
|
package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/task-seeds.md
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Task seeds
|
|
2
2
|
|
|
3
|
-
Register each item
|
|
3
|
+
Register each item with `update_plan` at audit start. Complete with evidence.
|
|
4
4
|
|
|
5
5
|
1. Load the rule: `docs/agents/name-by-capability.md` when present, else `reference/rule-checklist.md` (always keep the skill checklist as fallback).
|
|
6
6
|
2. Fetch PR title, body, and changed/renamed paths via `reference/fetch-commands.md`.
|
|
7
7
|
3. Classify each naming signal as violation, OK driver, or skip (`reference/offense-examples.md` classifier first).
|
|
8
8
|
4. Emit report from `reference/report-template.md`.
|
|
9
|
-
5.
|
|
9
|
+
5. After the report, continue with `SKILL.md` **Mode routing**.
|
|
10
|
+
6. For `preflight-proposal`, complete the shared contract referenced by `SKILL.md` **Mode routing**.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-refinement
|
|
3
|
+
description: Coordinate shared-extraction and capability-naming audits, then update an existing pull request or publish a required focused GitHub pull-request stack. Use when a user asks to turn a PR architecture audit into extracted shared code and small pull requests.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PR Refinement
|
|
7
|
+
|
|
8
|
+
Turn audit findings into a focused existing pull-request update or a required dependency-ordered GitHub pull-request stack.
|
|
9
|
+
|
|
10
|
+
## Peer skills
|
|
11
|
+
|
|
12
|
+
1. Run `pr-shared-extraction` for reusable-code placement, canonical shared homes, and extraction findings.
|
|
13
|
+
2. Run `pr-name-by-capability` for module, symbol, path, branch, and pull-request naming findings.
|
|
14
|
+
3. Use `pr-small-cl` to divide approved fixes into coherent, independently reviewable pull requests.
|
|
15
|
+
|
|
16
|
+
The peer skills own their audit rules and finding priorities.
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. Run both audits in parallel against the same pull request. Keep their findings, locations, priorities, destinations, API directions, and naming directions.
|
|
21
|
+
2. Build one change map. Group findings by shared capability and dependency.
|
|
22
|
+
3. Use `pr-small-cl` to choose the delivery shape. Update the existing pull request when it remains one coherent, reviewable outcome.
|
|
23
|
+
4. Create a replacement pull-request stack when the focused-change review identifies independent increments. Give each pull request one coherent outcome, related tests, a clear verification boundary, and a capability-oriented branch and title. Close the original pull request as superseded and link the replacement stack.
|
|
24
|
+
5. Implement the existing pull request or the replacement stack in dependency order. Earlier pull requests create stable shared foundations. Later pull requests migrate consumers and remove replaced code.
|
|
25
|
+
6. Run scoped production-path tests for each pull request. Record commands and results.
|
|
26
|
+
7. Commit and push each branch. Update the existing pull request, or open draft replacement pull requests in stack order and set every child pull request base to its parent.
|
|
27
|
+
8. Include scope, verification, risks, and stack dependencies in every pull-request body.
|
|
28
|
+
|
|
29
|
+
## Completion
|
|
30
|
+
|
|
31
|
+
Deliver a focused, tested, pushed existing pull request, or a replacement stack with explicit parent-child links. Keep merge authority with the user.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: shared-extraction
|
|
2
|
+
name: pr-shared-extraction
|
|
3
3
|
description: Audits pull requests and packages for general helpers living in workflow-specific code instead of shared_utils, then applies extraction fixes by default in small tested CLs. Use when reviewing PRs for architectural layering, migrating utilities out of cert_fix_queue/theme_dialer_pipeline/skills, auditing "similar offenses", or when the user mentions extraction audit, shared_utils migration, orchestration-only packages, thin wrappers, or layer inversions.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Shared Extraction Audit
|
|
7
7
|
|
|
8
|
-
Audit PRs and packages
|
|
8
|
+
Audit PRs and packages for reusable behavior placed in workflow code. Keep **orchestration packages thin** and **shared_utils canonical**.
|
|
9
9
|
|
|
10
10
|
## When to use
|
|
11
11
|
|
|
@@ -13,6 +13,14 @@ Audit PRs and packages, report findings, and apply extraction fixes by default t
|
|
|
13
13
|
- A package grew `fix_one`, `_default_*`, backup upload, rembg session, or residual gates alongside orchestration
|
|
14
14
|
- Before merge: confirm consumers are adapters, not second implementations
|
|
15
15
|
|
|
16
|
+
## Mode routing
|
|
17
|
+
|
|
18
|
+
Resolve the first matching mode before the audit steps:
|
|
19
|
+
|
|
20
|
+
1. `preflight-proposal` runs `pr-shared-extraction preflight-proposal <pr_number> --base-sha <base_sha> --head-sha <head_sha> --worktree <isolated_worktree>` under the [shared preflight proposal contract](../_shared/pr-loop/preflight-proposal.md). Record each finding with priority and target.
|
|
21
|
+
2. `audit-only` is report-only and ends after the findings report.
|
|
22
|
+
3. Normal mode follows the existing audit workflow and applies the prioritized fix band by default.
|
|
23
|
+
|
|
16
24
|
## Target architecture
|
|
17
25
|
|
|
18
26
|
| Layer | Holds | Examples |
|
|
@@ -25,7 +33,7 @@ Audit PRs and packages, report findings, and apply extraction fixes by default t
|
|
|
25
33
|
|
|
26
34
|
## Audit workflow
|
|
27
35
|
|
|
28
|
-
|
|
36
|
+
Register this checklist with `update_plan` and mark each step complete with evidence:
|
|
29
37
|
|
|
30
38
|
```
|
|
31
39
|
Shared extraction audit:
|
|
@@ -33,9 +41,10 @@ Shared extraction audit:
|
|
|
33
41
|
- [ ] 2. Map canonical homes already in shared_utils
|
|
34
42
|
- [ ] 3. Grep for offense patterns (see reference/offense-taxonomy.md)
|
|
35
43
|
- [ ] 4. Write prioritized findings (P0–P3)
|
|
36
|
-
- [ ] 5. Apply
|
|
44
|
+
- [ ] 5. Apply **Mode routing** after the report
|
|
37
45
|
- [ ] 6. Extract in small CLs (~100 lines) + move/adjust tests
|
|
38
|
-
- [ ] 7. Run scoped pytest,
|
|
46
|
+
- [ ] 7. Run scoped pytest, then follow the selected mode's mutation boundary
|
|
47
|
+
- [ ] 8. When the mode is `preflight-proposal`, record proposal evidence from the [shared preflight proposal contract](../_shared/pr-loop/preflight-proposal.md) and require downstream owner selection before reapplication
|
|
39
48
|
```
|
|
40
49
|
|
|
41
50
|
### Step 1 — Scope
|
|
@@ -97,8 +106,6 @@ Use [reference/offense-taxonomy.md](reference/offense-taxonomy.md). Assign prior
|
|
|
97
106
|
1. …
|
|
98
107
|
```
|
|
99
108
|
|
|
100
|
-
Apply the prioritized fixes after the report by default. An explicit audit-only request ends after the report.
|
|
101
|
-
|
|
102
109
|
## Fix workflow
|
|
103
110
|
|
|
104
111
|
### Extraction rules
|
|
@@ -158,3 +165,13 @@ Provide evidence: pytest output counts, not "should work".
|
|
|
158
165
|
## Examples
|
|
159
166
|
|
|
160
167
|
See [reference/examples.md](reference/examples.md) for cert_fix_queue (#1965) and background_removal (#1954) audits.
|
|
168
|
+
|
|
169
|
+
## File index
|
|
170
|
+
|
|
171
|
+
| File | Purpose |
|
|
172
|
+
|------|---------|
|
|
173
|
+
| `SKILL.md` | Hub — architecture, routing, audit checklist, and fix workflow |
|
|
174
|
+
| `reference/offense-taxonomy.md` | Offense signals and priority guide |
|
|
175
|
+
| `reference/examples.md` | Audit examples and fix order |
|
|
176
|
+
| `../_shared/pr-loop/preflight-proposal.md` | Shared isolated proposal mode and evidence record |
|
|
177
|
+
| `../_shared/pr-loop/preflight-proposal.contract.test.mjs` | Cross-skill mode and contract test |
|
|
@@ -33,6 +33,7 @@ from prototype_scripts_constants.config.probe_sandbox_safety_constants import (
|
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
SCRIPTS_DIRECTORY = Path(__file__).resolve().parent
|
|
36
|
+
BUILDER_PATH = SCRIPTS_DIRECTORY / "build_sandbox_settings.py"
|
|
36
37
|
PROBE_PATH = SCRIPTS_DIRECTORY / "probe_sandbox_safety.py"
|
|
37
38
|
HOOKS_BLOCKING_DIRECTORY = SCRIPTS_DIRECTORY.parents[3] / "hooks" / "blocking"
|
|
38
39
|
|
|
@@ -52,13 +53,21 @@ ASK_HOOK_SOURCE = (
|
|
|
52
53
|
ALLOW_HOOK_SOURCE = "import sys\nsys.exit(0)\n"
|
|
53
54
|
|
|
54
55
|
|
|
55
|
-
def
|
|
56
|
-
spec = importlib.util.spec_from_file_location(
|
|
56
|
+
def load_module_from_path(module_name: str, module_path: Path) -> ModuleType:
|
|
57
|
+
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
|
57
58
|
assert spec is not None
|
|
58
59
|
assert spec.loader is not None
|
|
59
|
-
|
|
60
|
-
spec.loader.exec_module(
|
|
61
|
-
return
|
|
60
|
+
loaded_module = importlib.util.module_from_spec(spec)
|
|
61
|
+
spec.loader.exec_module(loaded_module)
|
|
62
|
+
return loaded_module
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def load_probe_module() -> ModuleType:
|
|
66
|
+
return load_module_from_path("probe_sandbox_safety", PROBE_PATH)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def load_builder_module() -> ModuleType:
|
|
70
|
+
return load_module_from_path("build_sandbox_settings", BUILDER_PATH)
|
|
62
71
|
|
|
63
72
|
|
|
64
73
|
def quoted_command(script_path: Path) -> str:
|
|
@@ -123,6 +132,25 @@ def test_main_exits_zero_when_the_real_destructive_hook_denies_in_deny_mode(
|
|
|
123
132
|
assert exit_code == PROBE_SUCCESS_EXIT_CODE
|
|
124
133
|
|
|
125
134
|
|
|
135
|
+
def test_built_deny_environment_denies_real_destructive_hook() -> None:
|
|
136
|
+
builder_module = load_builder_module()
|
|
137
|
+
settings_document = builder_module.build_minimal_settings(
|
|
138
|
+
builder_module.resolve_safety_hook_entries(real_hook_settings_document())
|
|
139
|
+
)
|
|
140
|
+
probe_module = load_probe_module()
|
|
141
|
+
probe_payload = probe_module.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
|
|
142
|
+
destructive_hook_path = HOOKS_BLOCKING_DIRECTORY / DESTRUCTIVE_HOOK_BASENAME
|
|
143
|
+
destructive_hook_tokens = probe_module.parse_command_argv(
|
|
144
|
+
quoted_command(destructive_hook_path)
|
|
145
|
+
)
|
|
146
|
+
is_hook_blocking = probe_module.hook_blocks_probe(
|
|
147
|
+
destructive_hook_tokens,
|
|
148
|
+
probe_payload,
|
|
149
|
+
settings_document["env"],
|
|
150
|
+
)
|
|
151
|
+
assert is_hook_blocking is True
|
|
152
|
+
|
|
153
|
+
|
|
126
154
|
def test_pii_basename_probe_payload_carries_the_secret() -> None:
|
|
127
155
|
probe = load_probe_module()
|
|
128
156
|
probe_payload = probe.build_probe_payload_for_basename(PII_HOOK_BASENAME)
|
|
@@ -35,7 +35,7 @@ Use the [review guide](../reviews/SKILL.md#review-workflow) to decide whether a
|
|
|
35
35
|
changed behavior is a finding. Use the [comment guide](../comments/SKILL.md#writing-useful-review-comments)
|
|
36
36
|
for posted findings and replies, the [description guide](../descriptions/SKILL.md#reviewing-a-description)
|
|
37
37
|
for final PR context, the [emergency guide](../emergencies/SKILL.md#while-the-incident-is-active)
|
|
38
|
-
for active incidents, and the [small-change guide](
|
|
38
|
+
for active incidents, and the [small-change guide](../../skills/pr-small-cl/SKILL.md#reviewable-scope)
|
|
39
39
|
when the diff needs a narrower review boundary.
|
|
40
40
|
|
|
41
41
|
## Pre-flight
|
|
@@ -26,4 +26,4 @@ def test_skill_routes_judgment_to_canonical_guides() -> None:
|
|
|
26
26
|
assert "../comments/SKILL.md#writing-useful-review-comments" in skill_text
|
|
27
27
|
assert "../descriptions/SKILL.md#reviewing-a-description" in skill_text
|
|
28
28
|
assert "../emergencies/SKILL.md#while-the-incident-is-active" in skill_text
|
|
29
|
-
assert "
|
|
29
|
+
assert "../../skills/pr-small-cl/SKILL.md#reviewable-scope" in skill_text
|
|
@@ -59,7 +59,7 @@ needed. Record the resulting decision in the pull request thread.
|
|
|
59
59
|
|
|
60
60
|
- Use [reviews](../reviews/SKILL.md#review-workflow) for substantive code
|
|
61
61
|
assessment.
|
|
62
|
-
- Use [small-cl](
|
|
62
|
+
- Use [pr-small-cl](../../skills/pr-small-cl/SKILL.md#responding-to-review) for author-side
|
|
63
63
|
review responses and focused follow-up work.
|
|
64
64
|
- Use [emergencies](../emergencies/SKILL.md#while-the-incident-is-active) for
|
|
65
65
|
urgent production-change communication.
|
|
@@ -47,5 +47,5 @@ summary, scope, verification, and risk information aligned with the pull
|
|
|
47
47
|
request's current contents.
|
|
48
48
|
|
|
49
49
|
Use [reviews](../reviews/SKILL.md#review-workflow) for substantive code
|
|
50
|
-
assessment and [small-cl](
|
|
50
|
+
assessment and [pr-small-cl](../../skills/pr-small-cl/SKILL.md#what-a-focused-pull-request-contains)
|
|
51
51
|
to establish a focused scope.
|
|
@@ -81,5 +81,5 @@ the pull request record.
|
|
|
81
81
|
or assess pull request context.
|
|
82
82
|
- Use [emergencies](../emergencies/SKILL.md#emergency-classification) to classify
|
|
83
83
|
an urgent production change.
|
|
84
|
-
- Use [small-cl](
|
|
84
|
+
- Use [pr-small-cl](../../skills/pr-small-cl/SKILL.md#when-to-use-this-guide) to focus or split
|
|
85
85
|
a change that exceeds a clear review boundary.
|
package/AGENTS.md
CHANGED
|
@@ -76,7 +76,7 @@ Use full capability names for files, modules, functions, variables, branches, an
|
|
|
76
76
|
|
|
77
77
|
When planning work or opening a pull request, size the change first: one self-contained change, around 100 lines, with its tests. Read the small-changelists guide for the numbers, the allowed exceptions, and how to split.
|
|
78
78
|
|
|
79
|
-
Use `~/.claude/skills/small-cl/SKILL.md` for change-size guidance and review-sized boundaries.
|
|
79
|
+
Use `~/.claude/skills/pr-small-cl/SKILL.md` for change-size guidance and review-sized boundaries.
|
|
80
80
|
|
|
81
81
|
## Execution and delegation
|
|
82
82
|
|
|
@@ -11,6 +11,7 @@ Runtime documents and scripts shared by every PR-loop skill. Changes here affect
|
|
|
11
11
|
| `post-audit-thread-contract.md` | Single source of truth for the `post_audit_thread.py` invocation string, exit-code table, and per-caller policy (bugteam exit 2 = hard blocker; autoconverge clean-audit failed post = recorded bypass) |
|
|
12
12
|
| `fix-protocol.md` | Ordered sequence a fix lens follows: read, capture SHA, TDD, apply, validate, self-audit, commit, push, reply + resolve |
|
|
13
13
|
| `gh-payloads.md` | How to build GitHub review and reply payloads via MCP tools; describes the one-review-per-loop pattern |
|
|
14
|
+
| `preflight-proposal.md` | Shared immutable proposal evidence and mutation-boundary contract for audit preflight worktrees |
|
|
14
15
|
| `state-schema.md` | Fields each PR-loop workflow tracks across iterations; documents common fields and per-skill extensions |
|
|
15
16
|
| `code-rules-gate.md` | Reference for the CODE_RULES pre-commit gate check; describes what the gate blocks and when it runs |
|
|
16
17
|
| `precatch-rubric.md` | Shared pre-catch lane checklist — deterministic sweep, doc-vs-code parity, test-assertion completeness, PR-description parity, adversarial audit — that autoconverge's lenses and pr-converge's CODE_REVIEW step read on demand |
|
|
@@ -24,4 +25,4 @@ Runtime documents and scripts shared by every PR-loop skill. Changes here affect
|
|
|
24
25
|
|
|
25
26
|
## Breaking-change rule
|
|
26
27
|
|
|
27
|
-
Any shape change in
|
|
28
|
+
Any shape change in a canonical contract listed under **Key documents** requires updating every consuming skill in the same commit.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Preflight proposal contract
|
|
2
|
+
|
|
3
|
+
Audit skills use this contract when the caller selects `preflight-proposal`. The mode prepares a local candidate and returns evidence for downstream selection.
|
|
4
|
+
|
|
5
|
+
Each skill hub defines its command name and finding classification. Commands use this shape:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
<audit-skill> preflight-proposal <pr_number> --base-sha <base_sha> --head-sha <head_sha> --worktree <isolated_worktree>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Required inputs
|
|
12
|
+
|
|
13
|
+
| Input | Contract |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `pr_number` | Resolved open pull-request number |
|
|
16
|
+
| `--base-sha` | Full immutable base commit SHA |
|
|
17
|
+
| `--head-sha` | Full immutable head commit SHA |
|
|
18
|
+
| `--worktree` | Caller-supplied isolated worktree path |
|
|
19
|
+
|
|
20
|
+
## Contract
|
|
21
|
+
|
|
22
|
+
1. Validate every required input before the first audit command.
|
|
23
|
+
2. Run `git rev-parse HEAD` in the supplied worktree and require exact equality with the head SHA.
|
|
24
|
+
3. Gather changed paths and audit scope from the exact `base_sha...head_sha` range. Use the resolved PR number for PR metadata.
|
|
25
|
+
4. Run the complete audit and findings against the immutable range and worktree.
|
|
26
|
+
5. Keep every audit edit and test inside the caller-supplied isolated worktree.
|
|
27
|
+
6. Create an immutable proposal identity. Use the existing commit SHA for committed proposals. For working-tree edits, use a deterministic diff hash over the baseline `HEAD` SHA, base SHA, head SHA, sorted normalized changed paths, status records, and file bytes.
|
|
28
|
+
7. Record every changed path, including tracked, untracked, renamed, and deleted paths.
|
|
29
|
+
8. Record exact tests and outcomes: each test command, exit code, and outcome.
|
|
30
|
+
9. Return selected-candidate-ready proposal evidence with the proposal ID, isolated worktree path, changed paths, findings, tests, and outcomes.
|
|
31
|
+
10. Keep commit, push, pull-request body, pull-request comment, pull-request review, pull-request update, merge, rebase, and Ready-state mutations disabled.
|
|
32
|
+
11. Return the proposal for downstream disposition. The downstream owner adds the proposal ID to its selected or dispositioned proposal collection. Reapplication uses exactly the selected records and their changed paths. Give each later finding a new proposal ID and evidence record.
|
|
33
|
+
|
|
34
|
+
## Evidence record
|
|
35
|
+
|
|
36
|
+
Use this record shape:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
mode: preflight-proposal
|
|
40
|
+
pr_number: <resolved PR number>
|
|
41
|
+
base_sha: <immutable base SHA>
|
|
42
|
+
head_sha: <immutable head SHA>
|
|
43
|
+
proposal_id:
|
|
44
|
+
kind: commit-sha | diff-sha256
|
|
45
|
+
value: <immutable identity>
|
|
46
|
+
isolated_worktree: <caller-supplied path>
|
|
47
|
+
changed_paths:
|
|
48
|
+
- <normalized path>
|
|
49
|
+
findings:
|
|
50
|
+
- <audit-classified finding>
|
|
51
|
+
tests:
|
|
52
|
+
- command: <exact command>
|
|
53
|
+
exit_code: <integer>
|
|
54
|
+
outcome: <exact outcome>
|
|
55
|
+
downstream_selection: required
|
|
56
|
+
```
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
default mode: git diff since merge-base, joined with untracked files
|
|
6
6
|
--staged: validate the staged index; --paths: validate explicit files
|
|
7
|
+
--immediate: validate staged rules and terminology at commit time
|
|
7
8
|
every mode ends by naming how many files it inspected
|
|
8
9
|
|
|
9
10
|
This entry module wires the ``code_rules_gate_parts`` submodules into one CLI
|
|
@@ -43,6 +44,7 @@ try:
|
|
|
43
44
|
ALL_WINDOWS_VENV_PYTHON_RELATIVE_PATH_SEGMENTS,
|
|
44
45
|
EMPTY_FILE_SET_EXIT_CODE,
|
|
45
46
|
EMPTY_FILE_SET_MESSAGE,
|
|
47
|
+
IMMEDIATE_SCOPE_ARGUMENT,
|
|
46
48
|
INSPECTED_COUNT_MESSAGE,
|
|
47
49
|
MAXIMUM_STAGED_PYTEST_COMMAND_LINE_CHARACTERS,
|
|
48
50
|
MINIMUM_STAGED_PYTEST_PYTHON_MAJOR,
|
|
@@ -263,31 +265,50 @@ def _run_explicit_paths_mode(
|
|
|
263
265
|
)
|
|
264
266
|
|
|
265
267
|
|
|
266
|
-
def
|
|
268
|
+
def _run_staged_validation(
|
|
267
269
|
validate_content: enforcer_loading.ValidateContentCallable,
|
|
268
270
|
arguments: argparse.Namespace,
|
|
269
271
|
repository_root: Path,
|
|
270
272
|
) -> int:
|
|
271
|
-
"""Validate
|
|
272
|
-
_report_terminology_findings(staged_terminology_findings(repository_root))
|
|
273
|
-
staged_test_exit_code = _staged_pytest_exit_code_for_current_python(repository_root)
|
|
273
|
+
"""Validate staged file content and report scoped rule findings."""
|
|
274
274
|
staged_file_paths = filter_paths_under_prefixes(
|
|
275
275
|
paths_from_git_staged(repository_root), repository_root, arguments.only_under
|
|
276
276
|
)
|
|
277
277
|
if not staged_file_paths:
|
|
278
278
|
sys.stderr.write(INSPECTED_COUNT_MESSAGE.format(inspected_count=0) + "\n")
|
|
279
|
-
return
|
|
279
|
+
return 0
|
|
280
280
|
staged_added_lines = added_lines_by_file_staged(repository_root, staged_file_paths)
|
|
281
|
-
|
|
281
|
+
return run_gate(
|
|
282
282
|
validate_content,
|
|
283
283
|
staged_file_paths,
|
|
284
284
|
repository_root,
|
|
285
285
|
all_added_lines_by_path=staged_added_lines,
|
|
286
286
|
should_read_staged_content=True,
|
|
287
287
|
)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _run_staged_mode(
|
|
291
|
+
validate_content: enforcer_loading.ValidateContentCallable,
|
|
292
|
+
arguments: argparse.Namespace,
|
|
293
|
+
repository_root: Path,
|
|
294
|
+
) -> int:
|
|
295
|
+
"""Validate staged rules, terminology, and staged-test behavior."""
|
|
296
|
+
_report_terminology_findings(staged_terminology_findings(repository_root))
|
|
297
|
+
staged_test_exit_code = _staged_pytest_exit_code_for_current_python(repository_root)
|
|
298
|
+
gate_exit_code = _run_staged_validation(validate_content, arguments, repository_root)
|
|
288
299
|
return gate_exit_code or staged_test_exit_code
|
|
289
300
|
|
|
290
301
|
|
|
302
|
+
def _run_immediate_mode(
|
|
303
|
+
validate_content: enforcer_loading.ValidateContentCallable,
|
|
304
|
+
arguments: argparse.Namespace,
|
|
305
|
+
repository_root: Path,
|
|
306
|
+
) -> int:
|
|
307
|
+
"""Validate staged rules and terminology at the native commit boundary."""
|
|
308
|
+
_report_terminology_findings(staged_terminology_findings(repository_root))
|
|
309
|
+
return _run_staged_validation(validate_content, arguments, repository_root)
|
|
310
|
+
|
|
311
|
+
|
|
291
312
|
def _run_diff_mode(
|
|
292
313
|
validate_content: enforcer_loading.ValidateContentCallable,
|
|
293
314
|
arguments: argparse.Namespace,
|
|
@@ -339,6 +360,8 @@ def main(all_arguments: list[str]) -> int:
|
|
|
339
360
|
validate_content = load_validate_content()
|
|
340
361
|
if arguments.paths:
|
|
341
362
|
return _run_explicit_paths_mode(validate_content, arguments, repository_root)
|
|
363
|
+
if arguments.immediate:
|
|
364
|
+
return _run_immediate_mode(validate_content, arguments, repository_root)
|
|
342
365
|
if arguments.staged:
|
|
343
366
|
return _run_staged_mode(validate_content, arguments, repository_root)
|
|
344
367
|
return _run_diff_mode(validate_content, arguments, repository_root)
|
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
import argparse
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
from pr_loop_shared_constants.code_rules_gate_constants import (
|
|
7
|
+
IMMEDIATE_SCOPE_ARGUMENT,
|
|
8
|
+
IMMEDIATE_SCOPE_HELP,
|
|
9
|
+
)
|
|
10
|
+
|
|
6
11
|
|
|
7
12
|
def _add_source_arguments(parser: argparse.ArgumentParser) -> None:
|
|
8
|
-
"""Add the repo-root, base-ref, and staged-
|
|
13
|
+
"""Add the repo-root, base-ref, and staged-scope arguments to *parser*."""
|
|
9
14
|
parser.add_argument(
|
|
10
15
|
"--repo-root",
|
|
11
16
|
type=Path,
|
|
@@ -17,12 +22,19 @@ def _add_source_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
17
22
|
default="origin/main",
|
|
18
23
|
help="Merge-base ref for git diff (default: origin/main).",
|
|
19
24
|
)
|
|
20
|
-
parser.
|
|
25
|
+
staged_scope_group = parser.add_mutually_exclusive_group()
|
|
26
|
+
staged_scope_group.add_argument(
|
|
21
27
|
"--staged",
|
|
22
28
|
action="store_true",
|
|
23
29
|
default=False,
|
|
24
30
|
help="Scope to staged changes only (git diff --cached).",
|
|
25
31
|
)
|
|
32
|
+
staged_scope_group.add_argument(
|
|
33
|
+
IMMEDIATE_SCOPE_ARGUMENT,
|
|
34
|
+
action="store_true",
|
|
35
|
+
default=False,
|
|
36
|
+
help=IMMEDIATE_SCOPE_HELP,
|
|
37
|
+
)
|
|
26
38
|
|
|
27
39
|
|
|
28
40
|
def _add_filter_arguments(parser: argparse.ArgumentParser) -> None:
|
|
@@ -65,6 +77,6 @@ def parse_arguments(all_arguments: list[str]) -> argparse.Namespace:
|
|
|
65
77
|
|
|
66
78
|
Returns:
|
|
67
79
|
The parsed namespace with ``repo_root``, ``base``, ``staged``,
|
|
68
|
-
``only_under``, and ``paths`` attributes.
|
|
80
|
+
``immediate``, ``only_under``, and ``paths`` attributes.
|
|
69
81
|
"""
|
|
70
82
|
return _build_argument_parser().parse_args(all_arguments)
|
|
@@ -3,14 +3,23 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
|
-
from code_rules_gate_parts import gate_running
|
|
7
6
|
|
|
7
|
+
from code_rules_gate_parts import enforcer_loading, gate_running
|
|
8
|
+
from code_rules_gate_parts.tests._repo_test_helpers import (
|
|
9
|
+
init_repository,
|
|
10
|
+
write_commit_and_stage_change,
|
|
11
|
+
)
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
|
|
14
|
+
def _clean_validate(
|
|
15
|
+
_content: str, _path: str, _prior: str = "", **_kwargs: object
|
|
16
|
+
) -> list[str]:
|
|
10
17
|
return []
|
|
11
18
|
|
|
12
19
|
|
|
13
|
-
def _dirty_validate(
|
|
20
|
+
def _dirty_validate(
|
|
21
|
+
_content: str, _path: str, _prior: str = "", **_kwargs: object
|
|
22
|
+
) -> list[str]:
|
|
14
23
|
return ["Line 1: bad"]
|
|
15
24
|
|
|
16
25
|
|
|
@@ -92,8 +101,42 @@ def test_print_violation_section_groups_by_relative_path(
|
|
|
92
101
|
) -> None:
|
|
93
102
|
module_path = (tmp_path / "module.py").resolve()
|
|
94
103
|
|
|
95
|
-
gate_running.print_violation_section(
|
|
104
|
+
gate_running.print_violation_section(
|
|
105
|
+
"HEADER", {module_path: ["Line 1: issue"]}, tmp_path
|
|
106
|
+
)
|
|
96
107
|
|
|
97
108
|
captured = capsys.readouterr()
|
|
98
109
|
assert "HEADER" in captured.err
|
|
99
110
|
assert "Line 1: issue" in captured.err
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_gate_caller_scans_staged_content_with_commit_stage_scope(
|
|
114
|
+
tmp_path: Path,
|
|
115
|
+
capsys: pytest.CaptureFixture[str],
|
|
116
|
+
) -> None:
|
|
117
|
+
repository_root = tmp_path / "repository"
|
|
118
|
+
repository_root.mkdir()
|
|
119
|
+
init_repository(repository_root)
|
|
120
|
+
committed_source = "def calculate_total() -> int:\n return 0\n"
|
|
121
|
+
staged_source = (
|
|
122
|
+
"def calculate_total() -> int:\n total = 9999\n return total\n"
|
|
123
|
+
)
|
|
124
|
+
file_path = write_commit_and_stage_change(
|
|
125
|
+
repository_root,
|
|
126
|
+
"service.py",
|
|
127
|
+
committed_source,
|
|
128
|
+
staged_source,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
resolved_file_path = file_path.resolve()
|
|
132
|
+
exit_code = gate_running.run_gate(
|
|
133
|
+
validate_content=enforcer_loading.load_validate_content(),
|
|
134
|
+
all_file_paths=[resolved_file_path],
|
|
135
|
+
repository_root=repository_root,
|
|
136
|
+
all_added_lines_by_path={resolved_file_path: {2, 3}},
|
|
137
|
+
should_read_staged_content=True,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
captured = capsys.readouterr()
|
|
141
|
+
assert exit_code == 1
|
|
142
|
+
assert "9999" in captured.err
|
|
@@ -97,6 +97,10 @@ CODE_RULES_GATE_PYTHON_ENV_VAR: str = "CODE_RULES_GATE_PYTHON"
|
|
|
97
97
|
|
|
98
98
|
CODE_RULES_GATE_PYTHONPATH_ENV_VAR: str = "CODE_RULES_GATE_PYTHONPATH"
|
|
99
99
|
|
|
100
|
+
IMMEDIATE_SCOPE_ARGUMENT: str = "--immediate"
|
|
101
|
+
|
|
102
|
+
IMMEDIATE_SCOPE_HELP: str = "Validate staged rules without running staged tests."
|
|
103
|
+
|
|
100
104
|
PYTHONPATH_ENV_VAR: str = "PYTHONPATH"
|
|
101
105
|
|
|
102
106
|
ALL_VENV_DIRECTORY_NAMES: tuple[str, ...] = (".venv", "venv")
|