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
|
@@ -22,7 +22,7 @@ Before writing a single line — **task-local discovery only** (no project-wide
|
|
|
22
22
|
1. **Load scoped repository instructions first.** Starting at the repository root, read every applicable `AGENTS.md` on the path to the task file. Then read the applicable `CLAUDE.md` files. Apply nearer instructions after broader ones; the closest file wins.
|
|
23
23
|
2. **Read the file you are about to edit** (when editing existing code). Note every existing comment so you can leave each one untouched on lines that remain otherwise unchanged.
|
|
24
24
|
3. **Discover config only next to the task files.** From each file you will write or edit, walk up to the nearest package or repo root and inspect the target package's existing constants layout — such as `config/` or a sibling `*_constants` package. Keep this task-local constants search. Do **not** force a generic `config/` layout. Do **not** glob the whole tree for every config file. Do **not** glob or open `.env`, `.env.*`, or other secret files.
|
|
25
|
-
4. **Reuse constants from that local table.** Reuse first: exact value match → import the existing name. Semantic match → reuse it. Add a shared constant only when the value is shared policy or has multiple consumers. When no match exists, use the target package's existing constants layout
|
|
25
|
+
4. **Reuse constants from that local table.** Reuse first: exact value match → import the existing name. Semantic match → reuse it. Add a shared constant only when the value is shared policy or has multiple consumers. When no match exists, use the target package's existing constants layout, and keep a one-use value in the scope that reads it rather than making it a new shared constant.
|
|
26
26
|
5. **Search callers.** When a symbol, name, or signature changes, search its full caller boundary and update every consumer. This search may be wider than the constants search.
|
|
27
27
|
|
|
28
28
|
## Generation mindset (9 laws)
|
|
@@ -50,17 +50,16 @@ Installed paths use the active managed root and agents home resolved above; sour
|
|
|
50
50
|
| Write-time gates | `<managed-root>/hooks/blocking/code_rules_enforcer.py` (source fallback: `packages/claude-dev-env/hooks/blocking/code_rules_enforcer.py`) |
|
|
51
51
|
| Naming and abbreviations | `<managed-root>/docs/CODE_RULES.md#5-no-abbreviations` (source fallback: `packages/claude-dev-env/docs/CODE_RULES.md#5-no-abbreviations`) |
|
|
52
52
|
| Policy surface map | `<managed-root>/rules/code-standards.md` (source fallback: `packages/claude-dev-env/rules/code-standards.md`) |
|
|
53
|
-
| File-global constants | `<managed-root>/rules/file-global-constants.md` (source fallback: `packages/claude-dev-env/rules/file-global-constants.md`) |
|
|
54
53
|
| Windows rmtree / mkdir | `<managed-root>/rules/windows-filesystem-safe.md` (source fallback: `packages/claude-dev-env/rules/windows-filesystem-safe.md`) |
|
|
55
54
|
| `gh` body files | `<managed-root>/rules/gh-cli-conventions.md` (source fallback: `packages/claude-dev-env/rules/gh-cli-conventions.md`) |
|
|
56
55
|
| Plain illustrative docstrings | `<managed-root>/rules/plain-illustrative-docstrings.md` (source fallback: `packages/claude-dev-env/rules/plain-illustrative-docstrings.md`) |
|
|
57
56
|
| Tests / TDD | `<managed-root>/rules/testing.md` (source fallback: `packages/claude-dev-env/rules/testing.md`), `<managed-root>/rules/paired-test-coverage.md` (source fallback: `packages/claude-dev-env/rules/paired-test-coverage.md`), `<managed-root>/rules/bdd.md` (source fallback: `packages/claude-dev-env/rules/bdd.md`) |
|
|
58
|
-
| Questions / task tracking | `<managed-root>/rules/
|
|
57
|
+
| Questions / task tracking | `<managed-root>/rules/verify-before-asking.md` (source fallback: `packages/claude-dev-env/rules/verify-before-asking.md`) |
|
|
59
58
|
| Runtime evidence | `<managed-root>/rules/verify-runtime-state.md` (source fallback: `packages/claude-dev-env/rules/verify-runtime-state.md`) |
|
|
60
59
|
| Documentation / durable artifacts | `<managed-root>/rules/doc-inventory-integrity.md` (source fallback: `packages/claude-dev-env/rules/doc-inventory-integrity.md`), `<managed-root>/rules/durable-post-artifacts.md` (source fallback: `packages/claude-dev-env/rules/durable-post-artifacts.md`) |
|
|
61
60
|
| Batch / failure blast radius | `<managed-root>/rules/failure-blast-radius.md` (source fallback: `packages/claude-dev-env/rules/failure-blast-radius.md`) |
|
|
62
61
|
| Git / GitHub | `<managed-root>/rules/git-workflow.md` (source fallback: `packages/claude-dev-env/rules/git-workflow.md`), `<managed-root>/rules/gh-cli-conventions.md` (source fallback: `packages/claude-dev-env/rules/gh-cli-conventions.md`), `<managed-root>/rules/re-stage-before-commit.md` (source fallback: `packages/claude-dev-env/rules/re-stage-before-commit.md`) |
|
|
63
|
-
| Workers / completion | `<managed-root>/rules/
|
|
62
|
+
| Workers / completion | `<managed-root>/rules/workers-done-before-complete.md` (source fallback: `packages/claude-dev-env/rules/workers-done-before-complete.md`) |
|
|
64
63
|
| TDD / right-size | Review contract Tests + Design; `CODE_RULES.md` §7–§8 |
|
|
65
64
|
|
|
66
65
|
## Session policy map (canonical links)
|
|
@@ -70,13 +69,13 @@ Load only the group that matches the task. Keep session policy details in these
|
|
|
70
69
|
| Group | Canonical refs |
|
|
71
70
|
|---|---|
|
|
72
71
|
| Tests | `<managed-root>/rules/testing.md` (source fallback: `packages/claude-dev-env/rules/testing.md`); `<managed-root>/rules/anti-corollary-tests.md` (source fallback: `packages/claude-dev-env/rules/anti-corollary-tests.md`) |
|
|
73
|
-
| Questions | `<managed-root>/rules/
|
|
72
|
+
| Questions | `<managed-root>/rules/verify-before-asking.md` (source fallback: `packages/claude-dev-env/rules/verify-before-asking.md`) |
|
|
74
73
|
| Search and shell | `<managed-root>/rules/filesystem-search.md` (source fallback: `packages/claude-dev-env/rules/filesystem-search.md`); `<managed-root>/rules/shell-invocation.md` (source fallback: `packages/claude-dev-env/rules/shell-invocation.md`) |
|
|
75
74
|
| Runtime checks | `<managed-root>/rules/verify-runtime-state.md` (source fallback: `packages/claude-dev-env/rules/verify-runtime-state.md`) |
|
|
76
75
|
| Documentation | `<managed-root>/rules/doc-inventory-integrity.md` (source fallback: `packages/claude-dev-env/rules/doc-inventory-integrity.md`); `<managed-root>/rules/docstring-prose-matches-implementation.md` (source fallback: `packages/claude-dev-env/rules/docstring-prose-matches-implementation.md`) |
|
|
77
76
|
| Batch failures | `<managed-root>/rules/failure-blast-radius.md` (source fallback: `packages/claude-dev-env/rules/failure-blast-radius.md`) |
|
|
78
77
|
| Git | `<managed-root>/rules/git-workflow.md` (source fallback: `packages/claude-dev-env/rules/git-workflow.md`); `<managed-root>/rules/re-stage-before-commit.md` (source fallback: `packages/claude-dev-env/rules/re-stage-before-commit.md`) |
|
|
79
|
-
| Worker coordination | `<managed-root>/rules/
|
|
78
|
+
| Worker coordination | `<managed-root>/rules/workers-done-before-complete.md` (source fallback: `packages/claude-dev-env/rules/workers-done-before-complete.md`) |
|
|
80
79
|
|
|
81
80
|
Material implementation questions must return to the caller for `AskUserQuestion` handling; do not ask in plain text or guess.
|
|
82
81
|
|
|
@@ -19,7 +19,7 @@ Keep the same warm `issue-tracker` agent for follow-up actions on the **same iss
|
|
|
19
19
|
|
|
20
20
|
## Voice
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Keep the final message to the issue number(s) and URL(s) only.
|
|
23
23
|
|
|
24
24
|
## On each turn
|
|
25
25
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pr-description-writer
|
|
3
|
-
description: "Writes factual pull request titles, descriptions, and comments in plain illustrative language from the current diff.
|
|
3
|
+
description: "Writes factual pull request titles, descriptions, and comments in plain illustrative language from the current diff. Spawn it when a pull request needs a body written from the diff or rewritten in full."
|
|
4
4
|
tools: Read,Grep,Glob,Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -30,18 +30,7 @@ A caller may bundle three of these fields — `Composition plan`, `Description`,
|
|
|
30
30
|
|
|
31
31
|
A refine packet instead carries: the current SKILL.md, what was observed, what to change, new gotchas to add, what to preserve, a description rewrite, a composition change, and a deterministic fix.
|
|
32
32
|
|
|
33
|
-
**Direct request.** A looser prompt names the skill to build or the file to edit. Fill the packet yourself from the
|
|
34
|
-
|
|
35
|
-
## Read first
|
|
36
|
-
|
|
37
|
-
At the start of every job, read the live references at `~/.claude/skills/skill-builder/references/` so you author to current conventions:
|
|
38
|
-
|
|
39
|
-
- `delegation-map.md` — the handoff packet and the Produce contract.
|
|
40
|
-
- `deterministic-elements.md` — the rule that deterministic work ships as code, artifacts, or session tasks.
|
|
41
|
-
- `description-field.md` — the trigger-catalog description shape.
|
|
42
|
-
- `skill-modularity.md` — hub layout and compose-by-name.
|
|
43
|
-
|
|
44
|
-
Read them fresh each run; they carry the rules you author to.
|
|
33
|
+
**Direct request.** A looser prompt names the skill to build or the file to edit. Fill the packet yourself from the standards below, and ask the caller for any field only they hold, such as domain context or constraints.
|
|
45
34
|
|
|
46
35
|
## Standards every file meets
|
|
47
36
|
|
|
@@ -13,14 +13,14 @@ model on every spawn, so no agent definition names one, concrete or
|
|
|
13
13
|
`inherit`::
|
|
14
14
|
|
|
15
15
|
ok: <no model key at all>
|
|
16
|
-
flag: model: inherit <- caller
|
|
16
|
+
flag: model: inherit <- caller cannot choose the model
|
|
17
17
|
flag: model: opus <- pinned concrete model, caller can't override
|
|
18
18
|
|
|
19
19
|
Every block must also load through `yaml.safe_load`. An unquoted colon inside
|
|
20
20
|
a plain scalar reads as a mapping key and makes the whole block unloadable::
|
|
21
21
|
|
|
22
22
|
ok: description: ... constraints. Examples are below.
|
|
23
|
-
flag: description: ... constraints. Examples: <- block
|
|
23
|
+
flag: description: ... constraints. Examples: <- block does not load
|
|
24
24
|
|
|
25
25
|
Two parsers read these files, and a block that satisfies one can still be
|
|
26
26
|
unreadable by the other. `scripts/codex_compat_materializer.py` loads the
|
|
@@ -445,10 +445,6 @@ EXPECTED_SOURCE_LINK_PAIRS = {
|
|
|
445
445
|
"<managed-root>/rules/code-standards.md",
|
|
446
446
|
"packages/claude-dev-env/rules/code-standards.md",
|
|
447
447
|
),
|
|
448
|
-
(
|
|
449
|
-
"<managed-root>/rules/file-global-constants.md",
|
|
450
|
-
"packages/claude-dev-env/rules/file-global-constants.md",
|
|
451
|
-
),
|
|
452
448
|
(
|
|
453
449
|
"<managed-root>/rules/windows-filesystem-safe.md",
|
|
454
450
|
"packages/claude-dev-env/rules/windows-filesystem-safe.md",
|
|
@@ -477,10 +473,6 @@ EXPECTED_SOURCE_LINK_PAIRS = {
|
|
|
477
473
|
"<managed-root>/rules/bdd.md",
|
|
478
474
|
"packages/claude-dev-env/rules/bdd.md",
|
|
479
475
|
),
|
|
480
|
-
(
|
|
481
|
-
"<managed-root>/rules/ask-user-question-required.md",
|
|
482
|
-
"packages/claude-dev-env/rules/ask-user-question-required.md",
|
|
483
|
-
),
|
|
484
476
|
(
|
|
485
477
|
"<managed-root>/rules/verify-before-asking.md",
|
|
486
478
|
"packages/claude-dev-env/rules/verify-before-asking.md",
|
|
@@ -521,10 +513,6 @@ EXPECTED_SOURCE_LINK_PAIRS = {
|
|
|
521
513
|
"<managed-root>/rules/re-stage-before-commit.md",
|
|
522
514
|
"packages/claude-dev-env/rules/re-stage-before-commit.md",
|
|
523
515
|
),
|
|
524
|
-
(
|
|
525
|
-
"<managed-root>/rules/agent-spawn-protocol.md",
|
|
526
|
-
"packages/claude-dev-env/rules/agent-spawn-protocol.md",
|
|
527
|
-
),
|
|
528
516
|
(
|
|
529
517
|
"<managed-root>/rules/workers-done-before-complete.md",
|
|
530
518
|
"packages/claude-dev-env/rules/workers-done-before-complete.md",
|
|
@@ -797,7 +785,6 @@ def test_clean_coder_links_canonical_policy_areas() -> None:
|
|
|
797
785
|
required_links = (
|
|
798
786
|
"<managed-root>/docs/CODE_RULES.md#5-no-abbreviations",
|
|
799
787
|
"<managed-root>/rules/testing.md",
|
|
800
|
-
"<managed-root>/rules/ask-user-question-required.md",
|
|
801
788
|
"<managed-root>/rules/verify-runtime-state.md",
|
|
802
789
|
"<managed-root>/rules/doc-inventory-integrity.md",
|
|
803
790
|
"<managed-root>/rules/failure-blast-radius.md",
|
|
@@ -992,7 +979,6 @@ def test_clean_coder_follows_target_package_constant_layouts() -> None:
|
|
|
992
979
|
assert "Reuse first" in body
|
|
993
980
|
assert "shared policy" in body
|
|
994
981
|
assert "multiple consumers" in body
|
|
995
|
-
assert "file-global-constants" in body
|
|
996
982
|
assert "add the constant to the appropriate config file" not in body
|
|
997
983
|
|
|
998
984
|
|
|
@@ -1029,7 +1015,6 @@ def test_clean_coder_groups_session_policy_references() -> None:
|
|
|
1029
1015
|
"Worker coordination",
|
|
1030
1016
|
):
|
|
1031
1017
|
assert each_policy_group in body
|
|
1032
|
-
assert "ask-user-question-required.md" in body
|
|
1033
1018
|
assert "workers-done-before-complete.md" in body
|
|
1034
1019
|
assert "verify-runtime-state.md" in body
|
|
1035
1020
|
assert "Material implementation questions must return to the caller" in body
|
|
@@ -1039,7 +1024,6 @@ def test_clean_coder_groups_session_policy_references() -> None:
|
|
|
1039
1024
|
expected_session_policy_files = (
|
|
1040
1025
|
"testing.md",
|
|
1041
1026
|
"anti-corollary-tests.md",
|
|
1042
|
-
"ask-user-question-required.md",
|
|
1043
1027
|
"verify-before-asking.md",
|
|
1044
1028
|
"filesystem-search.md",
|
|
1045
1029
|
"shell-invocation.md",
|
|
@@ -1049,7 +1033,6 @@ def test_clean_coder_groups_session_policy_references() -> None:
|
|
|
1049
1033
|
"failure-blast-radius.md",
|
|
1050
1034
|
"git-workflow.md",
|
|
1051
1035
|
"re-stage-before-commit.md",
|
|
1052
|
-
"agent-spawn-protocol.md",
|
|
1053
1036
|
"workers-done-before-complete.md",
|
|
1054
1037
|
)
|
|
1055
1038
|
session_policy_map = body[body.index("## Session policy map") :]
|
|
@@ -21,7 +21,7 @@ Prefer the **same warm** `issue-tracker` agent for follow-ups on the same issue
|
|
|
21
21
|
|
|
22
22
|
## Voice
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
End with the issue number(s) and URL(s) the caller must keep, and nothing else.
|
|
25
25
|
|
|
26
26
|
## Gotchas
|
|
27
27
|
|
|
@@ -36,9 +36,8 @@ verification reads.
|
|
|
36
36
|
## status_gate (deterministic — not optional)
|
|
37
37
|
|
|
38
38
|
**Prose does not keep the loop alive.** Re-arm and terminate are gated by
|
|
39
|
-
`scripts/status_gate.py
|
|
40
|
-
|
|
41
|
-
single pending re-arm latch in the status file, not host product names.
|
|
39
|
+
`scripts/status_gate.py`. The gate is host-agnostic: a single pending re-arm
|
|
40
|
+
latch in the status file, not host product names.
|
|
42
41
|
|
|
43
42
|
```
|
|
44
43
|
python scripts/status_gate.py set --status active|done [--run-slug SLUG] [--status-file PATH]
|
|
@@ -158,8 +157,8 @@ in the repo the run works on (working files, not committed):
|
|
|
158
157
|
- **One assignment file per task** — scope, file list, constraints, the
|
|
159
158
|
acceptance check, baseline command output. The thick context goes
|
|
160
159
|
here. `/prompt-generator` authors the assignment once at plan time,
|
|
161
|
-
and every ticket for that task reuses it
|
|
162
|
-
|
|
160
|
+
and every ticket for that task reuses it, so each spawn starts from
|
|
161
|
+
the same named files, constraints, and acceptance check.
|
|
163
162
|
- **Results merge into run state.** An executor's product is its
|
|
164
163
|
artifact — the branch diff, the test output, the report its agent type
|
|
165
164
|
may write — and its reply is thin: status, artifact paths, blockers.
|
|
@@ -73,7 +73,7 @@ current process environment.
|
|
|
73
73
|
|
|
74
74
|
| Skill | When | Produces | If missing |
|
|
75
75
|
|---|---|---|---|
|
|
76
|
-
| `pr-description-writer` |
|
|
76
|
+
| `pr-description-writer` | Create or a full body rewrite, when you want the body drafted for you | A reviewed title and body file | Write the title and body yourself |
|
|
77
77
|
| `privacy-hygiene` | Before any durable GitHub post | A clean body and repository privacy sweep | Stop before publication and report the missing gate |
|
|
78
78
|
| `issue-tracker` | Issue create, edit, or comment requests | Issue state and issue URLs | Route the request there. |
|
|
79
79
|
| `e-code-review` | Review or review/fix loop requests | Structured findings or a clean review result | Route the request there. |
|
|
@@ -97,10 +97,10 @@ request target. Create actions publish drafts. Record the target before any writ
|
|
|
97
97
|
|
|
98
98
|
### 2. Author the title and body
|
|
99
99
|
|
|
100
|
-
For create and full body rewrite,
|
|
101
|
-
`pr-description-writer
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
For create and full body rewrite, write the title and a body file, or invoke
|
|
101
|
+
the installed `pr-description-writer` to draft them from the diff. A comment or
|
|
102
|
+
review may use a supplied body file when it does not rewrite the pull request
|
|
103
|
+
description.
|
|
104
104
|
|
|
105
105
|
### 3. Run the local linter
|
|
106
106
|
|
|
@@ -122,8 +122,9 @@ permanent URLs. Rerun the linter after changing the body.
|
|
|
122
122
|
|
|
123
123
|
### 5. Resolve the process-local author
|
|
124
124
|
|
|
125
|
-
Run
|
|
126
|
-
|
|
125
|
+
Run `~/.agents/skills/pull-request/scripts/pull_request.py` (under the agents
|
|
126
|
+
home, not the repository; a worktree holds no `.agents/` copy) with one
|
|
127
|
+
structured action and the selected author. The command runs the linter again, resolves
|
|
127
128
|
the author value, and passes it only to the child `gh` process. It never
|
|
128
129
|
changes the parent environment or calls `gh auth switch`.
|
|
129
130
|
|
|
@@ -6,7 +6,7 @@ reason when the task is conditional. This file is a task seed catalog, not a
|
|
|
6
6
|
markdown progress board.
|
|
7
7
|
|
|
8
8
|
1. Resolve one repository, action, and selected author. For create, resolve the source branch, base, and head. For other actions, resolve one existing pull request target. Create actions publish drafts.
|
|
9
|
-
2.
|
|
9
|
+
2. Record the title and body file for create or full body rewrite, written by you or drafted by `pr-description-writer`. Mark `N/A` for comment or review bodies that do not rewrite the pull request description.
|
|
10
10
|
3. Validate every title, body, artifact, and local path input. Reject inline body input.
|
|
11
11
|
4. Resolve the active managed root and run `<managed-root>/scripts/durable_post_lint.py` for the matching action. Record exit code `0` before credential lookup or network work.
|
|
12
12
|
5. Run `privacy-hygiene` before the GitHub post and record its clean result.
|
|
@@ -26,9 +26,8 @@ One warm advisor at the strongest tier this session can reach. This session is t
|
|
|
26
26
|
1. Name the session identity first (protocol **Host profiles**), then walk the model floor.
|
|
27
27
|
2. Claude: Fable first in-session at `ADVISOR_EFFORT` (default low). When Fable is out of usage, bind Astra at the same effort. Codex: Astra in-session. Third-party: headless Fable then Astra. When the host's walk fails, fail closed.
|
|
28
28
|
3. Name: `team-advisor-agent` on Claude (Agent spawn of `session-advisor`); a native Astra subagent on Codex; one CLI `session_id` on a third-party host via the protocol Claude-chain or Astra helper.
|
|
29
|
-
4.
|
|
30
|
-
5.
|
|
31
|
-
6. When the bind or reply path fails, fail closed and report to the user. On a third-party host, only the bound advisor issues ENDORSE / CORRECTION / PLAN / STOP.
|
|
29
|
+
4. Skip the multi-consumer "who you are" opener. This session is the sole consumer.
|
|
30
|
+
5. When the bind or reply path fails, fail closed and report to the user. On a third-party host, only the bound advisor issues ENDORSE / CORRECTION / PLAN / STOP.
|
|
32
31
|
|
|
33
32
|
**GOTCHA (Cursor / ThirdParty + Astra):** when the walk reaches Astra or the user asks for Astra, first tool call is `python ~/.claude/_shared/advisor/scripts/codex_astra_advisor.py --bind --enable-astra --cwd <repo-root>` with the charter on stdin. Do not use Agent or Task. Do not search for a probe path. Details: [`third-party-bind.md`](../../_shared/advisor/reference/third-party-bind.md) GOTCHA and [`astra-rung.md`](../../_shared/advisor/reference/astra-rung.md).
|
|
34
33
|
|
|
@@ -104,7 +104,6 @@ The validator checks ladder shape only; host policy sits on top.
|
|
|
104
104
|
## Warm-up (once per session)
|
|
105
105
|
|
|
106
106
|
On a **Claude host**, spawn `session-advisor` at the Fable alias with the charter as its prompt. When Fable is out of usage and the Astra rung is open, bind Astra through the Codex helper instead.
|
|
107
|
-
A **Fable**-tier try carries the exact token `FABLE-SPAWN-AUTHORIZED` in its prompt. `hooks/blocking/fable_spawn_gate.py` denies a Fable-tier spawn without it.
|
|
108
107
|
Full spawn fields and the charter template: [`reference/warm-up.md`](reference/warm-up.md).
|
|
109
108
|
|
|
110
109
|
On a **Codex host**, spawn a native in-session Astra subagent with the same charter. Bind fields: [`reference/identity.md`](reference/identity.md) and [`reference/warm-up.md`](reference/warm-up.md).
|
|
@@ -10,7 +10,6 @@ Every other consumer (executors, or any other consulting session) reaches it by
|
|
|
10
10
|
One shared advisor exists per orchestrated session, owned by the session that spawned it.
|
|
11
11
|
|
|
12
12
|
**Re-spawn on drift.** If a reply shows the agent working from a stale picture, or the session pivots to an unrelated task, the owning session ends that agent and spawns a fresh one with a new charter.
|
|
13
|
-
A **Fable**-tier re-spawn carries the exact token `FABLE-SPAWN-AUTHORIZED` in that fresh prompt, as a Fable-tier warm-up try does.
|
|
14
13
|
|
|
15
14
|
## Codex host
|
|
16
15
|
|
|
@@ -11,14 +11,13 @@ The consuming skill's session tries Fable first. Spawn with:
|
|
|
11
11
|
- `model`: the short alias via `resolve_cli_model_id("Fable")` (alias table: [`cli-chain.md`](cli-chain.md)): `fable`. When Fable is out of usage and the Astra rung is open, continue with the Codex helper in [`astra-rung.md`](astra-rung.md) as the Astra fallback.
|
|
12
12
|
- `name`: a name the session and every consumer will use to reach it (e.g. `team-advisor-agent`).
|
|
13
13
|
- `run_in_background: true`.
|
|
14
|
-
- `prompt`: the charter below.
|
|
14
|
+
- `prompt`: the charter below.
|
|
15
15
|
|
|
16
16
|
Stop at the first successful bind. That try's tier is `selected_tier`; the warm advisor lives at that tier for the rest of the session.
|
|
17
17
|
|
|
18
18
|
## Charter (the spawn prompt)
|
|
19
19
|
|
|
20
20
|
The charter states the agent's role, the repo path, and the session's current goal in two or three sentences. The agent is a standing reviewer. It answers only via SendMessage. File edits and commands are out of its scope.
|
|
21
|
-
On a Fable-tier try, include the exact token `FABLE-SPAWN-AUTHORIZED` as plain text in this prompt (substring match; the gate reads the token alone, wherever it came from).
|
|
22
21
|
State plainly:
|
|
23
22
|
|
|
24
23
|
- Every consult carries: who is asking (name and assignment), what changed since their last consult, the live decision or question, and any load-bearing paths or excerpts.
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
| E6 | Removed-but-not-deleted symbol references | Symbols renamed/removed elsewhere with stale import or call sites left behind. |
|
|
27
27
|
| E7 | Test fixtures / helpers defined but never used | Pytest fixtures, test data builders, mock factories with no callers. |
|
|
28
28
|
| E8 | Stub / placeholder code without tracking | Judge `pass`, `...`, and `raise NotImplementedError` directly; track follow-up work outside source code. |
|
|
29
|
-
| E9 | Constants-module exports with no importer | A module-level `UPPER_SNAKE` constant added to a `*_constants.py` / `config/` module that no module in the repo imports and that the constants file itself never references.
|
|
29
|
+
| E9 | Constants-module exports with no importer | A module-level `UPPER_SNAKE` constant added to a `*_constants.py` / `config/` module that no module in the repo imports and that the constants file itself never references. No write-time check reads a constants module, and every name such a module exports carries zero in-file references by design, so a dead export reaches the audit untouched. Distinguish dead from live by grepping the whole repo for each constant name: a sibling such as `MEDIUM_TERMINAL` imported by a consumer module is live; a `MEDIUM_TEXT` that no `from ... import` line and no in-file reference names is dead (CODE_RULES 9.8). Remove the dead export. |
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
**Examples of Category J findings:**
|
|
6
6
|
- A literal `60` appears in a production function body (magic value rule).
|
|
7
7
|
- A new `MAX_RETRIES = 3` declared at module scope outside `config/`.
|
|
8
|
-
- A parameter named `ctx`
|
|
8
|
+
- A parameter named `ctx` where the name `context` belongs (abbreviation rule).
|
|
9
9
|
- A function that returns a value with no return-type annotation.
|
|
10
10
|
- A new `# explains the loop logic` comment added to production code.
|
|
11
11
|
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
| J1 | Magic values in production function bodies | Literals other than `0`, `1`, `-1` inside production function bodies. Test files exempt. |
|
|
21
21
|
| J2 | String-template magic | f-strings whose structural literal text (paths, URLs, patterns) belongs in `config/`. |
|
|
22
22
|
| J3 | Constants location | Module-level `UPPER_SNAKE = ...` outside `config/` in production code. Exempt path families: `config/*`, `/migrations/`, `/workflow/`, `_tab.py`, `/states.py`, `/modules.py`, test files. |
|
|
23
|
-
| J4 | File-global use-count | A file-global constant referenced by fewer than two methods/functions/classes in the same file. |
|
|
24
23
|
| J5 | Abbreviations | `ctx`, `cfg`, `msg`, `btn`, `idx`, `cnt`, `elem`, `val`, `tmp`, `str`, `num`, `arr`, `obj`, `fn`, `cb`, `req`, `res`. (Loop counters `i`/`j`/`k` and `e` for exceptions are exempt.) |
|
|
25
24
|
| J6 | Vague names | `result`, `data`, `output`, `response`, `value`, `item`, `temp`, `info`, `stuff`, `thing`. Vague prefixes: `handle`, `process`, `manage`, `do`. |
|
|
26
25
|
| J7 | Type hints | Missing type annotation on a parameter or return; presence of `Any` or `# type: ignore`. |
|
|
@@ -26,7 +26,7 @@ Inline the artifact under this section using the section types defined in the ch
|
|
|
26
26
|
|
|
27
27
|
**E2. Functions / methods defined but never called**
|
|
28
28
|
- For every function, method, or callable defined or modified by the artifact, enumerate call sites: direct calls, callback registrations (`onerror=`, `key=`, signal handlers), decorator applications, `__main__` guards, framework-driven discovery (pytest collection, Django URL resolution, FastAPI route decorators, Click groups), and string-form references resolved at runtime (`getattr`, dispatch tables).
|
|
29
|
-
- Leading-underscore names: a single internal call site is
|
|
29
|
+
- Leading-underscore names: a single internal call site is enough; explicitly verify nothing outside the file imports the underscore-prefixed name.
|
|
30
30
|
- Public names: confirm at least one call site inside or outside the file, or confirm the function is part of a documented public API.
|
|
31
31
|
- Framework-discovered callables (test functions, route handlers, CLI commands): state which collector picks them up and confirm the artifact's path matches that collector's pattern.
|
|
32
32
|
|
|
@@ -59,7 +59,7 @@ Inline the artifact under this section using the section types defined in the ch
|
|
|
59
59
|
|
|
60
60
|
**E7. Test fixtures / helpers defined but never used**
|
|
61
61
|
- For every test file in scope, enumerate `@pytest.fixture`, `@pytest.fixture(scope=...)`, `setUp` / `tearDown` methods, factory helpers, mock builders, and module-level test constants. Verify each has at least one consumer test.
|
|
62
|
-
- Module-level constants in test files: each must
|
|
62
|
+
- Module-level constants in test files: each must be referenced by at least two callers, OR by exactly one test plus one helper that the tests call.
|
|
63
63
|
- Helpers defined inside a single test body that are never called within that body are dead.
|
|
64
64
|
- Adversarial probes for proof-of-absence: (a) any test that defines a local helper (e.g., `def make_dir(...):`) and never calls it? (b) any imported test name from the production module that no test exercises? (c) any module-level constant whose call graph collapses to zero references after the diff?
|
|
65
65
|
|
|
@@ -71,7 +71,7 @@ Inline the artifact under this section using the section types defined in the ch
|
|
|
71
71
|
|
|
72
72
|
**E9. Constants-module exports with no importer**
|
|
73
73
|
- For every module-level `UPPER_SNAKE` constant the artifact adds to a `*_constants.py` or `config/` module, grep the whole repo for the constant name and locate at least one importer (`from <module> import <NAME>`) or in-file reference.
|
|
74
|
-
-
|
|
74
|
+
- Every name a constants module exports carries zero in-file references by design and no write-time check reads such a module, so a dead export reaches the audit untouched; this sub-bucket is the audit-time backstop.
|
|
75
75
|
- A sibling that a consumer module imports is live; a constant that no `from ... import` line and no in-file reference names anywhere in the repo is dead and must be removed (CODE_RULES 9.8).
|
|
76
76
|
- Constants reached only by string-form lookup (`getattr(config, name)`, settings registries) are live; name the dynamic consumer when you mark such a constant referenced.
|
|
77
77
|
- Adversarial probes for proof-of-absence: (a) does the artifact add any constant to a `*_constants.py` / `config/` module whose name returns zero hits outside its own definition line? (b) is any newly added constant shadowed by a same-named constant in a sibling module so the importer resolves the other one? (c) does any constant exist only as an `__all__` re-export with no downstream importer of that re-export?
|
|
@@ -156,7 +156,7 @@ ID prefix: `find`.
|
|
|
156
156
|
**E7. Test fixtures / helpers defined but never used**
|
|
157
157
|
- `test_sweep_empty_dirs.py` defines no `@pytest.fixture` decorators. Nothing to flag under "fixture with no consumers".
|
|
158
158
|
- `_set_creation_time_windows` is the only test helper; it has three call sites (E2 above). Used.
|
|
159
|
-
- `_SCRIPTS_DIR` (line 12) is a module-level constant used at line 13 (`if str(_SCRIPTS_DIR) not in sys.path:`) and line 14 (`sys.path.insert(0, str(_SCRIPTS_DIR))`). Two references;
|
|
159
|
+
- `_SCRIPTS_DIR` (line 12) is a module-level constant used at line 13 (`if str(_SCRIPTS_DIR) not in sys.path:`) and line 14 (`sys.path.insert(0, str(_SCRIPTS_DIR))`). Two references; the constant earns its module scope.
|
|
160
160
|
- No test data builders or mock factories are defined in this PR.
|
|
161
161
|
- Adversarial probes for proof-of-absence: (a) does any of the five tests define a local helper inside its body that is then never called? (e.g., a `def make_dir(...):` defined but unused) — scan each test body. (b) does any test import a name from `sweep_empty_dirs` that it never uses? — only `sweep` is imported, and every test calls it. (c) does the `_SCRIPTS_DIR` block survive if pytest is invoked with `sweep_empty_dirs.py` already on `sys.path`? — yes, the membership-test guards the insert, so the constant is still meaningfully consumed even on the second run.
|
|
162
162
|
|
|
@@ -178,7 +178,7 @@ ID prefix: `find`.
|
|
|
178
178
|
|
|
179
179
|
Q1: Are there imports unused locally but consumed by a re-export pattern in another file? Cite the cross-file pair if found. (Hypothesis: none — neither `sweep_empty_dirs.py` nor `test_sweep_empty_dirs.py` defines `__all__`, so re-export is not in play. `config/sweep_config.py` declares two constants that ARE consumed by `sweep_empty_dirs.py` lines 10-11; this is normal cross-file consumption, not a re-export.)
|
|
180
180
|
Q2: What's the worst unused-code hazard introduced by this PR? Cite `<file>:<line>`. Candidates to evaluate: `arguments.interval` is parsed but unreachable on the `--once` path (line 57 short-circuits before the watch loop at line 67); the scheduled task always uses `--once`, so the `--interval` argparse declaration at line 45 is dead code on the only invocation path the installer creates. Decide: P2 (style) because the manual watch-mode path still uses it, vs P1 if you treat "the only installer path never exercises this branch" as functionally dead.
|
|
181
|
-
Q3: Which symbol most likely will *become* dead code after a near-future refactor? Candidates: `_log_walk_error` (sole call site is the `os.walk(..., onerror=...)` kwarg — if a future refactor switches to `pathlib.Path.rglob` for walking, this helper has no other consumer and silently becomes orphaned); `DEFAULT_POLL_INTERVAL` (sole consumer is `_build_parser`'s `--interval` default — if Q2's hazard is resolved by removing `--interval` from the `--once`-only installer flow, this constant has zero consumers in the script
|
|
181
|
+
Q3: Which symbol most likely will *become* dead code after a near-future refactor? Candidates: `_log_walk_error` (sole call site is the `os.walk(..., onerror=...)` kwarg — if a future refactor switches to `pathlib.Path.rglob` for walking, this helper has no other consumer and silently becomes orphaned); `DEFAULT_POLL_INTERVAL` (sole consumer is `_build_parser`'s `--interval` default — if Q2's hazard is resolved by removing `--interval` from the `--once`-only installer flow, this constant has zero consumers in the script).
|
|
182
182
|
|
|
183
183
|
## Output
|
|
184
184
|
|
|
@@ -50,11 +50,6 @@ A `test_*.py` name or a `.mjs` extension takes the line out of the write-time ga
|
|
|
50
50
|
- Distinguish *imports* (`from config.X import FOO`) from *declarations* — imports are not J3-scope.
|
|
51
51
|
- Adversarial probes: (a) does any module-level constant masquerade as an "import" via a re-export pattern? (b) is there a `_PRIVATE_UPPER` declaration that escapes the visual UPPER_SNAKE filter but is still module-level? (c) does any test file declare a constant that *would* be flagged if it were in production, indicating the constant probably belongs in `config/` even if test-exempt?
|
|
52
52
|
|
|
53
|
-
**J4. File-global use-count**
|
|
54
|
-
- For every file-global constant outside `config/`, count references in the same file. Single ref → move to `config/`. Zero refs → delete.
|
|
55
|
-
- The rule applies to *constants*, not functions, classes, or imports.
|
|
56
|
-
- Adversarial probes: (a) is any imported constant referenced only once in the importing file (suggesting the import itself is gratuitous)? (b) is any helper function defined in a production file but never called from inside the same file (separate dead-code concern, surfaced here for completeness)? (c) does any constant in `config/` get imported from zero call sites across the repo?
|
|
57
|
-
|
|
58
53
|
**J5. Abbreviations**
|
|
59
54
|
- Walk every parameter, local, and attribute name across production, test, and JavaScript changed lines. Flag: `ctx`, `cfg`, `msg`, `btn`, `idx`, `cnt`, `elem`, `val`, `tmp`, `str`, `num`, `arr`, `obj`, `fn`, `cb`, `req`, `res`. Loop counters `i`/`j`/`k` and `e` for exceptions are exempt.
|
|
60
55
|
- This audit walks changed test-file and `.mjs` / `.js` lines for this rule, even though the write-time hook skips them.
|
|
@@ -101,7 +96,7 @@ A `test_*.py` name or a `.mjs` extension takes the line out of the write-time ga
|
|
|
101
96
|
|
|
102
97
|
## Cross-bucket questions to answer at the end
|
|
103
98
|
|
|
104
|
-
Q1: Are there literals or names that span two sub-buckets (e.g., a magic value in J1 that also appears inside an f-string scrutinized by J2; an UPPER_SNAKE in J3 that also
|
|
99
|
+
Q1: Are there literals or names that span two sub-buckets (e.g., a magic value in J1 that also appears inside an f-string scrutinized by J2; an UPPER_SNAKE in J3 that is also an abbreviation under J5)? Cite the literal/name and both sub-bucket IDs.
|
|
105
100
|
|
|
106
101
|
Q2: What is the worst CODE_RULES drift introduced by this artifact? Cite `<file>:<line>`. (Common candidates: cross-language duplicates, stale help text mirroring a config constant, abbreviations in a public API surface, bare `Any` annotations, hardcoded user paths in installer scripts.)
|
|
107
102
|
|
|
@@ -149,13 +144,6 @@ ID prefix: `find`.
|
|
|
149
144
|
- `Install-SweepEmptyDirs.ps1` line 245 — `$TaskName = "SweepEmptyDirs"` is a PowerShell variable; J3 enforces Python module-level UPPER_SNAKE outside `config/`. PowerShell out of scope for J3.
|
|
150
145
|
- Adversarial probes: (a) does any module-level constant in `sweep_empty_dirs.py` masquerade as an "import"? (b) is there any `_PRIVATE_UPPER` declaration that escapes the visual UPPER_SNAKE filter? (c) does the test file accidentally declare a constant that *would* be flagged if it were in production?
|
|
151
146
|
|
|
152
|
-
**J4. File-global use-count**
|
|
153
|
-
- For every file-global constant outside `config/`, count references in the same file. Single ref → move to `config/`. Zero refs → delete.
|
|
154
|
-
- `sweep_empty_dirs.py` — no file-global constants declared (`DEFAULT_AGE_SECONDS` and `DEFAULT_POLL_INTERVAL` are imports). Imports follow standard import-usage rules, not the file-global use-count rule.
|
|
155
|
-
- `config/sweep_config.py:142-143` — `DEFAULT_AGE_SECONDS` and `DEFAULT_POLL_INTERVAL` live in `config/`, exempt by location.
|
|
156
|
-
- Test file `_SCRIPTS_DIR` — test files exempt.
|
|
157
|
-
- Adversarial probes: (a) is any imported constant in `sweep_empty_dirs.py` referenced only once (line 104 for `DEFAULT_AGE_SECONDS`, line 108 for `DEFAULT_POLL_INTERVAL`) — wait, `DEFAULT_AGE_SECONDS` is referenced TWICE on line 104 (`default=DEFAULT_AGE_SECONDS`) and line 105 (`f"...default: {DEFAULT_AGE_SECONDS} = 2 minutes"`); `DEFAULT_POLL_INTERVAL` is referenced TWICE on line 108 and line 109. Both meet the ≥2-references threshold (note: file-global use-count technically applies to declarations, not imports — listed here for completeness). (b) is any helper function in `sweep_empty_dirs.py` defined but never called from inside the file? `_log_walk_error` (line 73) is referenced once at line 84; `_build_parser` (line 101) is referenced once at line 114. The use-count rule applies to *constants*, not functions, so neither is flagged. (c) does any constant in `config/sweep_config.py` get imported from zero call sites?
|
|
158
|
-
|
|
159
147
|
**J5. Abbreviations**
|
|
160
148
|
- Walk every parameter, local, and attribute name in `sweep_empty_dirs.py`.
|
|
161
149
|
- `_log_walk_error(os_error: OSError)` — `os_error` is full word, not `e` (exception loop var allowed but not required). Verified clean.
|
|
@@ -247,11 +235,9 @@ import time
|
|
|
247
235
|
from config.sweep_config import DEFAULT_AGE_SECONDS
|
|
248
236
|
from config.sweep_config import DEFAULT_POLL_INTERVAL
|
|
249
237
|
|
|
250
|
-
|
|
251
238
|
def _log_walk_error(os_error: OSError) -> None:
|
|
252
239
|
print(f"warning: cannot scan {os_error.filename} — {os_error.strerror}", file=sys.stderr)
|
|
253
240
|
|
|
254
|
-
|
|
255
241
|
def sweep(root: str, min_age_seconds: int) -> list[str]:
|
|
256
242
|
"""Remove empty directories under *root* older than *min_age_seconds*."""
|
|
257
243
|
|
|
@@ -275,7 +261,6 @@ def sweep(root: str, min_age_seconds: int) -> list[str]:
|
|
|
275
261
|
|
|
276
262
|
return removed
|
|
277
263
|
|
|
278
|
-
|
|
279
264
|
def _build_parser() -> argparse.ArgumentParser:
|
|
280
265
|
parser = argparse.ArgumentParser(description="Delete empty directories older than a given age.")
|
|
281
266
|
parser.add_argument("root", help="Root directory to scan")
|
|
@@ -287,7 +272,6 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
287
272
|
help=f"Poll interval in seconds when looping (default: {DEFAULT_POLL_INTERVAL})")
|
|
288
273
|
return parser
|
|
289
274
|
|
|
290
|
-
|
|
291
275
|
def main() -> None:
|
|
292
276
|
parser = _build_parser()
|
|
293
277
|
arguments = parser.parse_args()
|
|
@@ -309,7 +293,6 @@ def main() -> None:
|
|
|
309
293
|
print("
|
|
310
294
|
stopped.")
|
|
311
295
|
|
|
312
|
-
|
|
313
296
|
if __name__ == "__main__":
|
|
314
297
|
main()
|
|
315
298
|
```
|
|
@@ -342,7 +325,6 @@ if str(_SCRIPTS_DIR) not in sys.path:
|
|
|
342
325
|
|
|
343
326
|
from sweep_empty_dirs import sweep # noqa: E402
|
|
344
327
|
|
|
345
|
-
|
|
346
328
|
def _set_creation_time_windows(path: str, timestamp: float) -> None:
|
|
347
329
|
dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
|
|
348
330
|
date_str = dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
@@ -352,7 +334,6 @@ def _set_creation_time_windows(path: str, timestamp: float) -> None:
|
|
|
352
334
|
check=True, capture_output=True,
|
|
353
335
|
)
|
|
354
336
|
|
|
355
|
-
|
|
356
337
|
def test_deletes_empty_dir_older_than_threshold() -> None:
|
|
357
338
|
with tempfile.TemporaryDirectory() as tmp:
|
|
358
339
|
empty_dir = os.path.join(tmp, "old_empty")
|
|
@@ -362,7 +343,6 @@ def test_deletes_empty_dir_older_than_threshold() -> None:
|
|
|
362
343
|
assert empty_dir in removed
|
|
363
344
|
assert not os.path.isdir(empty_dir)
|
|
364
345
|
|
|
365
|
-
|
|
366
346
|
def test_skips_empty_dir_newer_than_threshold() -> None:
|
|
367
347
|
with tempfile.TemporaryDirectory() as tmp:
|
|
368
348
|
fresh_dir = os.path.join(tmp, "fresh_empty")
|
|
@@ -371,7 +351,6 @@ def test_skips_empty_dir_newer_than_threshold() -> None:
|
|
|
371
351
|
assert fresh_dir not in removed
|
|
372
352
|
assert os.path.isdir(fresh_dir)
|
|
373
353
|
|
|
374
|
-
|
|
375
354
|
def test_deletes_nested_empty_dirs() -> None:
|
|
376
355
|
with tempfile.TemporaryDirectory() as tmp:
|
|
377
356
|
leaf = os.path.join(tmp, "parent", "child", "leaf")
|
|
@@ -384,13 +363,11 @@ def test_deletes_nested_empty_dirs() -> None:
|
|
|
384
363
|
assert os.path.join(tmp, "parent", "child") in removed
|
|
385
364
|
assert os.path.join(tmp, "parent") in removed
|
|
386
365
|
|
|
387
|
-
|
|
388
366
|
def test_empty_root_does_not_crash() -> None:
|
|
389
367
|
with tempfile.TemporaryDirectory() as tmp:
|
|
390
368
|
_set_creation_time_windows(tmp, time.time() - 300)
|
|
391
369
|
sweep(tmp, min_age_seconds=120)
|
|
392
370
|
|
|
393
|
-
|
|
394
371
|
def test_skips_nonempty_dir() -> None:
|
|
395
372
|
with tempfile.TemporaryDirectory() as tmp:
|
|
396
373
|
nonempty_dir = os.path.join(tmp, "has_stuff")
|
|
@@ -55,12 +55,7 @@ export const RUN_BACKUP_DIRECTORY_NAME_PATTERN =
|
|
|
55
55
|
*/
|
|
56
56
|
export const PACKAGE_AGENTS_HOME_DIRECTORY_NAME = '.agents';
|
|
57
57
|
|
|
58
|
-
export const PSTACK_MODEL_RULE_FILE_NAME = 'pstack-models.mdc';
|
|
59
58
|
export const SUBAGENT_MODEL_POLICY_FILE_NAME = 'subagent-model-policy.json';
|
|
60
|
-
export const PSTACK_SEEDED_MODEL_PREFERENCES_FILE_NAMES = Object.freeze([
|
|
61
|
-
'pstack-model-preferences.claude.json',
|
|
62
|
-
'pstack-model-preferences.codex.json',
|
|
63
|
-
]);
|
|
64
59
|
|
|
65
60
|
/**
|
|
66
61
|
* The directory name skill directories carry in a package source and under
|