claude-dev-env 8.1.0 → 8.3.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.
Files changed (122) hide show
  1. package/.agents/agents/poteto-agent.md +6 -0
  2. package/.agents/agents/test_agent_frontmatter.py +9 -9
  3. package/.agents/agents/test_pr_description_writer_style.py +1 -1
  4. package/.agents/agents-archived/ARCHIVE-MANIFEST.md +15 -0
  5. package/.agents/{agents → agents-archived}/clean-coder.md +4 -4
  6. package/.agents/{agents → agents-archived}/code-quality-agent.md +5 -5
  7. package/.agents/{agents → agents-archived}/plan-packet-validator.md +2 -2
  8. package/.agents/{agents → agents-archived}/session-advisor.md +2 -2
  9. package/.agents/skills/_shared/end-of-run-gotcha-recommendations.md +2 -2
  10. package/.agents/skills/cert-classification-rule/SKILL.md +3 -3
  11. package/.agents/skills/e-code-review/SKILL.md +2 -2
  12. package/.agents/skills/e-code-review/reference/fix.md +1 -1
  13. package/.agents/skills/e-code-review/reference/loop.md +1 -1
  14. package/.agents/skills/e-code-review/reference/medium.md +4 -4
  15. package/.agents/skills/e-code-review/reference/xhigh.md +5 -5
  16. package/.agents/skills/everything-search/SKILL.md +3 -3
  17. package/.agents/skills/grok-spawn/SKILL.md +9 -6
  18. package/.agents/skills/grok-spawn/reference/flag-profiles.md +12 -8
  19. package/.agents/skills/issue-tracker/SKILL.md +3 -3
  20. package/.agents/skills/orchestrator/SKILL.md +19 -18
  21. package/.agents/skills/orchestrator/reference/consult-the-orchestrator.md +1 -1
  22. package/.agents/skills/orchestrator/reference/executor-consult-block.md +1 -1
  23. package/.agents/skills/orchestrator-refresh/SKILL.md +4 -2
  24. package/.agents/skills/plugin-eval-standalone-skill/SKILL.md +96 -0
  25. package/.agents/skills/plugin-eval-standalone-skill/reference/graders-and-commands.md +108 -0
  26. package/.agents/skills/privacy-hygiene/SKILL.md +5 -6
  27. package/.agents/skills/privacy-hygiene/reference/sweep-procedure.md +5 -6
  28. package/.agents/skills/pull-request/SKILL.md +14 -5
  29. package/.agents/skills/pull-request/reference/publication-tasks.md +1 -1
  30. package/.agents/skills/repairing-hook-boundaries/SKILL.md +1 -1
  31. package/.agents/skills/syncing-submodules/SKILL.md +1 -1
  32. package/.agents/skills/team-advisor/SKILL.md +11 -9
  33. package/.agents/skills/team-advisor/reference/advisor-docs-review.md +28 -1
  34. package/.agents/skills/usage-pause/SKILL.md +3 -3
  35. package/_shared/advisor/advisor-protocol.md +7 -3
  36. package/_shared/advisor/reference/advisor-block.md +8 -1
  37. package/audit-rubrics/category_rubrics/category-f-silent-failures.md +2 -2
  38. package/audit-rubrics/category_rubrics/category-i-concurrency.md +1 -1
  39. package/audit-rubrics/category_rubrics/category-m-producer-consumer-cardinality.md +1 -1
  40. package/audit-rubrics/category_rubrics/category-n-test-name-scenario-verifier.md +5 -5
  41. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +5 -5
  42. package/audit-rubrics/category_rubrics/category-p-name-vs-behavior-contract.md +3 -3
  43. package/audit-rubrics/category_rubrics/category-q-cross-surface-claims.md +1 -1
  44. package/audit-rubrics/prompts/category-a-api-contracts.md +2 -2
  45. package/audit-rubrics/prompts/category-b-selector-engine-compat.md +3 -3
  46. package/audit-rubrics/prompts/category-c-resource-cleanup.md +3 -3
  47. package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +1 -1
  48. package/audit-rubrics/prompts/category-e-dead-code.md +3 -3
  49. package/audit-rubrics/prompts/category-f-silent-failures.md +12 -12
  50. package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +2 -2
  51. package/audit-rubrics/prompts/category-h-security-boundaries.md +4 -4
  52. package/audit-rubrics/prompts/category-i-concurrency.md +6 -6
  53. package/audit-rubrics/prompts/category-j-code-rules-compliance.md +5 -5
  54. package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +1 -1
  55. package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +7 -7
  56. package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
  57. package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +3 -3
  58. package/audit-rubrics/prompts/category-q-cross-surface-claims.md +2 -2
  59. package/bin/ever-shipped-skills.mjs +1 -0
  60. package/bin/ever-shipped-skills.test.mjs +4 -0
  61. package/bin/install.agents-home.test.mjs +44 -94
  62. package/bin/install.mjs +31 -24
  63. package/bin/install.test.mjs +21 -0
  64. package/bin/resolve-package-managed-directory.test.mjs +1 -1
  65. package/bin/subagent-model-policy.test.mjs +15 -8
  66. package/docs/BDD_SCENARIO_QUALITY.md +2 -2
  67. package/docs/CODE_RULES.md +7 -7
  68. package/docs/TEST_QUALITY.md +1 -1
  69. package/docs/nas-ssh-invocation.md +1 -1
  70. package/docs/references/advisor-tool.md +2 -2
  71. package/docs/references/prose-style-enforcement.md +1 -1
  72. package/docs/references/team-advisor-skill.md +2 -2
  73. package/docs/references/weak-executor-advisor.md +1 -1
  74. package/docs/subagent-model-routing.md +6 -5
  75. package/hooks/blocking/tdd_enforcer.py +2 -3
  76. package/hooks/blocking/test_bash_post_call_dispatcher.py +7 -24
  77. package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
  78. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +0 -3
  79. package/hooks/hooks_constants/hosted_hook_runner.py +1 -1
  80. package/hooks/hooks_constants/msys_path_conversion_advisor_constants.py +3 -35
  81. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +2 -10
  82. package/hooks/routing/subagent_model_routing.mjs +15 -0
  83. package/hooks/routing/subagent_model_routing.test.mjs +58 -25
  84. package/package.json +1 -1
  85. package/rules/archiving-agent-config.md +5 -8
  86. package/rules/git-workflow.md +3 -3
  87. package/rules/long-horizon-autonomy.md +1 -1
  88. package/rules/shell-invocation.md +0 -2
  89. package/rules/subagent-model-policy.json +5 -13
  90. package/rules/testing.md +0 -2
  91. package/scripts/active_capability_references.py +74 -19
  92. package/scripts/banned_prose_words.py +159 -0
  93. package/scripts/dev_env_scripts_constants/active_capability_constants.py +12 -10
  94. package/scripts/dev_env_scripts_constants/banned_prose_word_constants.py +95 -0
  95. package/scripts/dev_env_scripts_constants/grok_worker_constants.py +3 -3
  96. package/scripts/grok_headless_runner.py +19 -1
  97. package/scripts/grok_worker_preflight.py +67 -1
  98. package/scripts/policy_lint/adapter_retired_hook_prose.py +17 -7
  99. package/scripts/policy_lint/adapters.py +6 -6
  100. package/scripts/policy_lint/config/constants.py +8 -0
  101. package/scripts/policy_lint/registry.py +1 -1
  102. package/scripts/resolve_advisor_model_route.mjs +2 -2
  103. package/scripts/subagent_model_policy.mjs +4 -1
  104. package/scripts/sync_to_cursor/rules.py +1 -1
  105. package/scripts/test_active_capability_references.py +100 -33
  106. package/scripts/test_grok_headless_runner.py +35 -1
  107. package/scripts/test_grok_worker_preflight.py +73 -0
  108. package/scripts/tests/resolve_advisor_model_route.test.mjs +3 -3
  109. package/scripts/tests/test_banned_prose_words.py +103 -0
  110. package/scripts/tests/test_engine.py +1 -1
  111. package/scripts/tests/test_policy_lint_rules_retired_hook_prose.py +46 -0
  112. package/scripts/tests/test_rules.py +17 -6
  113. package/system-prompts/software-engineer.xml +7 -7
  114. package/hooks/advisory/msys_path_conversion_advisor.py +0 -200
  115. package/hooks/advisory/test_msys_path_conversion_advisor.py +0 -223
  116. package/hooks/hooks_constants/test_failure_recorder_constants.py +0 -34
  117. package/hooks/observability/test_failure_recorder.py +0 -221
  118. package/hooks/observability/test_test_failure_recorder.py +0 -173
  119. /package/.agents/{agents → agents-archived}/git-commit-crafter.md +0 -0
  120. /package/.agents/{agents → agents-archived}/issue-tracker.md +0 -0
  121. /package/.agents/{agents → agents-archived}/pr-description-writer.md +0 -0
  122. /package/.agents/{agents → agents-archived}/skill-writer-agent.md +0 -0
@@ -21,7 +21,7 @@ The first consult is complete. It carries:
21
21
  - Assignment and desired outcome
22
22
  - Constraints and exclusions
23
23
  - Actions taken in order
24
- - Real output and current state
24
+ - Output and current state
25
25
  - Live decision or blocker
26
26
  - Validation evidence
27
27
  - Unresolved risks
@@ -31,7 +31,7 @@ Fill `<orchestrator-name>` with the name the executor can address.
31
31
  > failure repeats or progress has stalled, and when the chosen approach
32
32
  > is being reconsidered.
33
33
  > The first consult carries: assignment, desired outcome, constraints
34
- > and exclusions, actions taken in order, real output and current
34
+ > and exclusions, actions taken in order, output and current
35
35
  > state, live decision or blocker, validation evidence, unresolved
36
36
  > risks, load-bearing paths or excerpts, and who is asking. Later
37
37
  > consults carry only changed evidence.
@@ -70,7 +70,7 @@ reports and adds nothing further.
70
70
  executor has no `in_progress` task naming it as owner; a finished
71
71
  executor's task is still open (or was closed without its result
72
72
  merged); the next phase you will dispatch has no pending task; a
73
- `blockedBy` link contradicts the actual run order. Fix every mismatch
73
+ `blockedBy` link contradicts the run order. Fix every mismatch
74
74
  with TaskCreate / TaskUpdate in this same firing — never defer.
75
75
  2. **You are the orchestrator.** Orchestrate and hold the user
76
76
  conversation; spawn executor subagents for every code edit and build
@@ -79,6 +79,8 @@ reports and adds nothing further.
79
79
  Claude host, or the resolver-printed sonnet-equivalent id on a
80
80
  third-party host, and fails closed — see Workflow Agent Routing in
81
81
  [`skills/orchestrator/SKILL.md`](../orchestrator/SKILL.md#workflow-agent-routing).
82
+ Advisor spawns use `flags: ["--advisor"]` only when they intentionally
83
+ select Astra.
82
84
  - **Focused tickets.** One mechanical done-check per ticket; resume a
83
85
  warm agent with a thin next-slice ticket rather than a fresh cold
84
86
  spawn, and keep thick context in the assignment file.
@@ -89,7 +91,7 @@ reports and adds nothing further.
89
91
  to orchestration and light verification reads.
90
92
  4. **Resume before you spawn.** `SendMessage` an existing *executor* by
91
93
  name or `agentId` before a cold spawn.
92
- 5. **Fresh spawn only for a genuine task switch.** Never tell an agent
94
+ 5. **Fresh spawn only for a task switch.** Never tell an agent
93
95
  to compact for a clean context.
94
96
  6. **Single-pending re-arm only.** Same protocol as the orchestrator
95
97
  skill (host-agnostic; **create then claim**):
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: plugin-eval-standalone-skill
3
+ description: >-
4
+ Run `claude plugin eval` against a standalone skill that is not a plugin, by wrapping the skill in a plugin folder, writing trigger and must-not-trigger cases, and reading the with-skill minus without-skill delta. Triggers: eval a skill, plugin eval, claude plugin eval, test my skill, skill eval, eval a standalone skill.
5
+ ---
6
+
7
+ # Plugin eval for a standalone skill
8
+
9
+ ## Contents
10
+
11
+ - Principle
12
+ - Gotchas
13
+ - When this applies
14
+ - Process
15
+ - Files
16
+
17
+ ## Principle
18
+
19
+ `claude plugin eval` runs plugins only. Wrap the skill in a plugin folder whose layout keeps every
20
+ relative link working. Grade behavior only the skill produces. Judge the skill by the delta between
21
+ the arm with the plugin and the arm without it.
22
+
23
+ ## Gotchas
24
+
25
+ - A `.claude-plugin/plugin.json` under any skills directory turns that folder into a
26
+ `<name>@skills-dir` plugin in every session. Build the wrapper outside every skills directory.
27
+ - The run sandbox gets a throwaway home and config. User settings, hooks, CLAUDE.md, MCP servers,
28
+ memory, and other skills are absent. Plugin items carry a prefix, such as `<plugin>:session-advisor`.
29
+ - `claude plugin eval init` with no arguments is interactive and needs a terminal. From an agent
30
+ shell, run `claude plugin eval init --bare <case-name>`.
31
+ - A prompt that starts with `/skill-name` loads the skill with no `Skill` tool call, so
32
+ `tool_used: Skill` always fails on a slash case.
33
+ - A plain-words case triggers only when the skill allows model invocation. Leave
34
+ `disable-model-invocation` unset in the copied frontmatter.
35
+ - Write, Edit, SendMessage, and Bash need `--allow-tools` on the command line. Bash and PowerShell
36
+ grants refuse the run on native Windows, which has no sandbox backend. Run those cases under WSL2.
37
+ - Writes under a loaded `--plugin-dir` are denied in dontAsk mode. That skews the with-plugin arm
38
+ only, so keep every working and output folder outside the plugin root.
39
+ - A metric built from tool_use attempts reports success even when every write was denied. Read each
40
+ run's `permission_denials` and final result before you compare arms.
41
+ - A score under `--ablation none` says nothing about what the skill adds. Run the baseline once
42
+ before you claim the skill helps.
43
+ - The sandbox disables feature-flag fetching. Flag-gated features such as the built-in `advisor()`
44
+ tool are off, and `/advisor` replies "isn't available in this environment". No env var or plugin
45
+ setting turns them on. Plugin `settings.json` accepts only `agent` and `subagentStatusLine`. Test
46
+ such a feature with the `claude -p` recipe in `reference/graders-and-commands.md`.
47
+ - `--keep-temp` on Windows warns that it cannot seal the folder. Delete that folder when done with
48
+ PowerShell `Remove-Item -Recurse -Force -LiteralPath <path>`.
49
+
50
+ ## When this applies
51
+
52
+ Use this skill to measure whether a skill that is not packaged as a plugin triggers and changes
53
+ behavior. It needs Claude Code 2.1.269 or later. Source doc: https://code.claude.com/docs/en/plugin-evals
54
+
55
+ ## Process
56
+
57
+ Register one session task per numbered step through the host task tool. Use `TaskCreate`, else
58
+ `TodoWrite`. Where the host has no task tool, say so and work the steps in order.
59
+
60
+ 1. Run `claude --version` and confirm 2.1.269 or later.
61
+ 2. Create the wrapper folder outside every skills directory:
62
+
63
+ ```text
64
+ <wrapper>/
65
+ ├── .claude-plugin/
66
+ │ └── plugin.json
67
+ ├── skills/
68
+ │ └── <name>/
69
+ ├── agents/
70
+ └── <each shared doc, at the path the skill's relative links expect>
71
+ ```
72
+
73
+ `plugin.json` holds `name`, `version`, and `description`.
74
+ 3. Copy the skill, every agent it spawns, and every shared doc it links. Copy from a tree at
75
+ `origin/main`, not from a stale worktree. Resolve each relative link in the copied skill against
76
+ the wrapper root.
77
+ 4. In the wrapper root, run `claude plugin eval init --bare <case-name>` once per case.
78
+ 5. Write `evals/<case>/prompt.md` and `evals/<case>/graders/*.md` for each case. Frontmatter keys,
79
+ grader types, and the case set are in `reference/graders-and-commands.md`.
80
+ 6. Re-copy the skill from `origin/main`, then run the smoke command from the reference file.
81
+ 7. Read each run's `permission_denials` and final result. Fix any denial that the case needs.
82
+ 8. Re-copy the skill, then run the full eval. Read the delta in `aggregate-result.json`.
83
+ 9. Delete any `--keep-temp` sandbox folder.
84
+
85
+ ## Files
86
+
87
+ - `SKILL.md`. Wrapper layout, gotchas, and process.
88
+ - `reference/graders-and-commands.md`. Prompt frontmatter, grader types, case set, eval commands,
89
+ and the `claude -p` recipe for flag-gated features.
90
+
91
+ ```text
92
+ plugin-eval-standalone-skill/
93
+ ├── SKILL.md
94
+ └── reference/
95
+ └── graders-and-commands.md
96
+ ```
@@ -0,0 +1,108 @@
1
+ # Graders and commands
2
+
3
+ ## Contents
4
+
5
+ - Prompt frontmatter
6
+ - Grader types
7
+ - Case set
8
+ - Eval commands
9
+ - Results
10
+ - Flag-gated features outside plugin eval
11
+
12
+ ## Prompt frontmatter
13
+
14
+ `evals/<case>/prompt.md` takes these frontmatter keys.
15
+
16
+ | Key | Use |
17
+ | --- | --- |
18
+ | `max_turns` | Default 10. Set about 40 for a skill that spawns agents. |
19
+ | `timeout_seconds` | Wall-clock cap for one run. |
20
+ | `allowed_tools` | Read-only set: Read, Glob, Grep, Skill, Agent, TodoWrite, and the task tools. |
21
+
22
+ Write, Edit, SendMessage, and Bash go on the command line through `--allow-tools`, not in
23
+ `allowed_tools`.
24
+
25
+ ## Grader types
26
+
27
+ Each file in `evals/<case>/graders/` is one grader.
28
+
29
+ | Type | Fields | Checks |
30
+ | --- | --- | --- |
31
+ | `regex` | `target`: `last_message`, `trace`, `files`, or `{source: file, path}` | A pattern in the chosen text |
32
+ | `tool_used` | `tool`, `input_match`, `min`, `max`, `arm` | How many calls to a tool, filtered by an input regex |
33
+ | `tool_order` | `before`, `after`, each a tool name or `{tool, input_match}` | One call lands before another |
34
+ | `file_exists` | `path` glob, `exists` | A file created during the run matches, or none does with `exists: false` |
35
+ | `llm` | The body is the rubric, `focus` | A judge panel votes, and 2 of 3 decide |
36
+ | `baseline` | `baseline_file`, `criteria` | A judge rates the run at least as good as a reference `.jsonl` transcript |
37
+
38
+ Source doc: https://code.claude.com/docs/en/plugin-evals
39
+
40
+ ## Case set
41
+
42
+ Write at least these three shapes.
43
+
44
+ **Slash case.** The prompt starts with `/<name>`. No `Skill` call happens, so grade what only the
45
+ skill produces:
46
+
47
+ - `tool_used` with `tool: Agent` and an `input_match` on the agent name the skill spawns.
48
+ - `tool_order` with that `Agent` spawn before the first `Write`.
49
+
50
+ **Plain-words case.** The prompt asks for the job in ordinary words. Vary the wording, and do not
51
+ copy the exact phrase from the skill description into the only trigger case. Grade the trigger with:
52
+
53
+ ```text
54
+ tool: Skill
55
+ input_match: '"skill"\s*:\s*"(?:[\w-]+:)?<name>"'
56
+ ```
57
+
58
+ **Must-not-trigger case.** The prompt uses a verb near the triggers in its ordinary sense. Grade
59
+ with `tool_used`, `tool: Skill`, `min: 0`, `max: 0`, `arm: both`.
60
+
61
+ Grade on skill behavior. A grader keyed to a transport token that upstream may remove breaks on an
62
+ upgrade with no change in the skill.
63
+
64
+ ## Eval commands
65
+
66
+ Run every command from the wrapper root.
67
+
68
+ Smoke run, one case:
69
+
70
+ ```text
71
+ claude plugin eval . --case <name> --runs 1 --ablation none --max-cost-usd 2 --no-publish --trust-plugin --allow-tools Write SendMessage
72
+ ```
73
+
74
+ `--trust-plugin` is needed when stdin is not a terminal. `--case` takes one glob. Only the last
75
+ `--case` flag takes effect, so match several cases with one glob.
76
+
77
+ Full run: drop `--runs` and `--ablation`. The default is 3 runs with the plugin and 3 runs without.
78
+ The delta, with minus without, measures what the skill adds. A smoke score under `--ablation none`
79
+ has no without-plugin arm, so it measures nothing about contribution.
80
+
81
+ Add `--keep-temp` to keep the sandbox. Its trace is `out/trace.jsonl`.
82
+
83
+ ## Results
84
+
85
+ Each run writes `evals/results/<timestamp>/report.html` and `aggregate-result.json`.
86
+
87
+ Before you compare arms, read each run's `permission_denials` and its final result. A run whose
88
+ writes were all denied still shows the tool_use attempts.
89
+
90
+ ## Flag-gated features outside plugin eval
91
+
92
+ The sandbox cannot turn on a flag-gated feature. Test it with `claude -p`, once with the wrapper
93
+ loaded and once without:
94
+
95
+ ```text
96
+ claude -p "<task>" --advisor <model> --plugin-dir <wrapper> --setting-sources project --strict-mcp-config --allowedTools "<list>" --permission-mode dontAsk --output-format stream-json --verbose
97
+ ```
98
+
99
+ Drop `--plugin-dir <wrapper>` for the second arm.
100
+
101
+ - Keep the user's config. An empty `CLAUDE_CONFIG_DIR` drops the login and the run reports
102
+ "Not logged in". `--setting-sources project` keeps user settings out.
103
+ - Count the feature in the stream. For the advisor, count content blocks with `type`
104
+ `server_tool_use` and `name` `advisor` on the main thread only.
105
+ - Before you read a zero count, run a positive control whose prompt asks for the feature by name. A
106
+ zero can mean the feature was not attached, rather than not chosen.
107
+ - Keep the run's working folder outside the wrapper root, since writes under `--plugin-dir` are
108
+ denied in dontAsk mode.
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: privacy-hygiene
3
- description: Full-repo sweep for personal data and secrets before commit or durable GitHub post. Use when preparing a PR, cleaning a leak, or when `pii_prevention_blocker` denies a write, post, or commit. Triggers on "privacy hygiene", "personal data", "secret sweep", "sanitize repository", "/privacy-hygiene".
3
+ description: Full-repo sweep for personal data and secrets before commit or durable GitHub post. Use when preparing a PR or cleaning a leak. Triggers on "privacy hygiene", "personal data", "secret sweep", "sanitize repository", "/privacy-hygiene".
4
4
  ---
5
5
 
6
6
  # privacy-hygiene
7
7
 
8
8
  ## Overview
9
9
 
10
- Find and remove personal data and high-confidence secrets before they land in git history or a durable GitHub post. The `pii_prevention_blocker` hook blocks the common cases at write, post, and commit time. This skill is the full sweep when you need a broader pass or a remediation plan.
10
+ Find and remove personal data and high-confidence secrets before they land in git history or a durable GitHub post. No write-time hook scans for these; `pii_prevention_blocker` was retired. This skill is the sweep.
11
11
 
12
12
  **Announce at start:** "Running privacy-hygiene sweep."
13
13
 
@@ -40,8 +40,7 @@ Run the full-tree sweep in
40
40
  run the ripgrep pass for the four high-confidence pattern families (email, home
41
41
  path, LAN address, secret), review each hit against the ignore list, and
42
42
  remediate. It also lists the accepted residual — what to leave in place rather
43
- than over-scrub. The ripgrep command is the only full-tree pass; the write-time
44
- `pii_prevention_blocker` scans one payload at a time.
43
+ than over-scrub. The ripgrep command is the only pass over the tree.
45
44
 
46
45
  ## Enable on any machine / public repository
47
46
 
@@ -56,9 +55,9 @@ Hooks register via `hooks/hooks.json` into `~/.claude/settings.json`. Once insta
56
55
 
57
56
  ## Open knobs
58
57
 
59
- - **NAS / LAN allowlist:** Unlisted private IPs are blocked. The scanner resolves your NAS host from `CLAUDE_NAS_HOST`, then `~/.claude/local-identity.json` (`nas.host`), and allowlists it when it is a private address, so the committed tree holds no real host. `ALL_ALLOWLISTED_PRIVATE_IP_ADDRESSES` in `hooks_constants` holds the static allowlist for any host every machine must share.
58
+ - **NAS / LAN allowlist:** Unlisted private IPs are blocked. The scanner resolves your NAS host from `CLAUDE_NAS_HOST`, then `~/.claude/local-identity.json` (`nas.host`), and allowlists it when it is a private address, so the committed tree holds no host address. `ALL_ALLOWLISTED_PRIVATE_IP_ADDRESSES` in `hooks_constants` holds the static allowlist for any host every machine must share.
60
59
  - **Commit-scan exempt repositories:** named owner/repo slugs skip the staged-commit PII scan only. Set `CLAUDE_PII_EXEMPT_REPOS` (comma-separated `owner/repo` values) or list them under `pii_exempt_repositories` in `~/.claude/local-identity.json`. Matching uses the repository's `remote.origin.url` and accepts only the exact host `github.com` (https, ssh scheme, or scp-style). A repository with no readable origin is never exempt (fail-closed to scanning). Write / Edit / MultiEdit and durable post bodies still scan in every repository.
61
- - **Public maintainer identity:** when a real email or name is intentional product surface, keep it and note that in the PR body so reviewers do not treat it as a leak.
60
+ - **Public maintainer identity:** when an email or name is intentional product surface, keep it and note that in the PR body so reviewers do not treat it as a leak.
62
61
 
63
62
  ## What this skill does not do
64
63
 
@@ -1,10 +1,9 @@
1
1
  # Full-tree PII sweep procedure
2
2
 
3
- The on-demand full-repository sweep for the `privacy-hygiene` skill — the
4
- complement to the write-time `pii_prevention_blocker`, which scans one payload at
5
- a time. The canonical per-payload patterns live in the hooks' `pii_scanner` and
6
- `pii_prevention_constants` modules; the ripgrep command below is the only
7
- full-tree pass. The hub ([`../SKILL.md`](../SKILL.md)) points here.
3
+ The on-demand full-repository sweep for the `privacy-hygiene` skill. The
4
+ per-payload patterns live in the hooks' `pii_scanner` and
5
+ `pii_prevention_constants` modules; the ripgrep command below is the only pass
6
+ over the tree. The hub ([`../SKILL.md`](../SKILL.md)) points here.
8
7
 
9
8
  ## 1. Scope the tree
10
9
 
@@ -40,7 +39,7 @@ Review each hit. Ignore:
40
39
 
41
40
  | Hit | Fix |
42
41
  |---|---|
43
- | Real email | Replace with `user@example.com` or remove |
42
+ | Email address | Replace with `user@example.com` or remove |
44
43
  | Home path | Use `Path.home()`, `~`, or `C:/Users/<you>/` |
45
44
  | LAN address | Remove, use a hostname, or — for your own NAS — set the host in `CLAUDE_NAS_HOST` or `~/.claude/local-identity.json`, both of which stay out of git |
46
45
  | Credential material | Remove from the tree; rotate the credential; load from env/secret store |
@@ -38,8 +38,9 @@ Use this skill for one pull request action:
38
38
  - Submit a pull request review.
39
39
  - Recover one selected legacy author record before the action.
40
40
 
41
- Send issue create, edit, and comment work to `issue-tracker`. Send review and
42
- fix-loop work to `e-code-review`. Send commits to `source-command-commit`.
41
+ Send issue create, edit, and comment work to `pstack:poteto-agent` with the
42
+ `issue-tracker` skill and one action. Send review and fix-loop work to
43
+ `e-code-review`. Send commits to `source-command-commit`.
43
44
 
44
45
  Require one repository and one action target. Stop before author lookup or
45
46
  network work when the repository, pull request, action, author, or required
@@ -73,9 +74,9 @@ current process environment.
73
74
 
74
75
  | Skill | When | Produces | If missing |
75
76
  |---|---|---|---|
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
+ | `pstack:poteto-agent` with `pull-request` instructions | 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
78
  | `privacy-hygiene` | Before any durable GitHub post | A clean body and repository privacy sweep | Stop before publication and report the missing gate |
78
- | `issue-tracker` | Issue create, edit, or comment requests | Issue state and issue URLs | Route the request there. |
79
+ | `pstack:poteto-agent` with `issue-tracker` | Issue create, edit, or comment requests | Issue state and issue URLs | Load the skill in this session. |
79
80
  | `e-code-review` | Review or review/fix loop requests | Structured findings or a clean review result | Route the request there. |
80
81
  | `source-command-commit` | Commit or push requests | A verified commit or pushed branch | Route the request there. |
81
82
 
@@ -98,10 +99,15 @@ request target. Create actions publish drafts. Record the target before any writ
98
99
  ### 2. Author the title and body
99
100
 
100
101
  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
+ `pstack:poteto-agent` with the diff-specific writing instructions to draft
103
+ them. A comment or
102
104
  review may use a supplied body file when it does not rewrite the pull request
103
105
  description.
104
106
 
107
+ Check each behavior claim against the final diff and verification evidence.
108
+ Preserve whether a rule is added, removed, or narrowed, and distinguish tests
109
+ added from tests run. Refresh these claims after a rebase or correction.
110
+
105
111
  ### 3. Run the local linter
106
112
 
107
113
  Resolve the active managed root (`CLAUDE_CONFIG_DIR` when set, `~/.claude`
@@ -153,6 +159,9 @@ Confirm the pull request URL and number, title, body, head SHA, and draft state.
153
159
  For comments and reviews, confirm the new remote entry. Report artifact URLs
154
160
  without exposing author values.
155
161
 
162
+ Confirm the published claims still describe the verified head and preserve the
163
+ scope of its evidence, including whether checks used saved artifacts or a new run.
164
+
156
165
  ## Exit handling
157
166
 
158
167
  Stop before network work when authoring, local validation, privacy, or author
@@ -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. 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.
9
+ 2. Record the title and body file for create or full body rewrite, written by you or drafted by `pstack:poteto-agent` with a PR-writing brief. 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.
@@ -27,7 +27,7 @@ output envelope, and exit status as separate boundaries.
27
27
  Use this skill for Claude or Codex hook failures involving registered events,
28
28
  settings, launchers, imports, paths, payloads, output envelopes, or exit status.
29
29
 
30
- For installer-only work, say: `Use /run-claude-dev-env for installer work that has no hook-boundary failure.`
30
+ For installer-only work, say: `Installer work with no hook-boundary failure belongs outside this skill.`
31
31
 
32
32
  ## Process
33
33
 
@@ -31,7 +31,7 @@ Use this skill after committing inside a checked-out submodule when its parent r
31
31
  Refusals use the first matching line:
32
32
 
33
33
  - Clone, initialize, or check out a submodule: `Use Git's submodule commands. This skill records an existing submodule commit in its parent.`
34
- - Fast-forward `main`: `Use /update. This skill changes one parent submodule pointer.`
34
+ - Fast-forward `main`: `Use Git directly. This skill changes one parent submodule pointer.`
35
35
  - Make an ordinary commit or push: `Use /source-command-commit. This skill commits only a parent submodule pointer.`
36
36
 
37
37
  ## Process
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: team-advisor
3
3
  description: >-
4
- Spawn one warm session-advisor at the strongest reachable tier and consult
5
- it before substantive work, completion, commits, or when stuck. Triggers:
6
- 'team-advisor', 'team advisor', 'second opinion', 'advisor', 'consult',
7
- 'verify', 'validate', 'commit', 'push'.
8
- disable-model-invocation: true
4
+ Bind one advisor, the built-in advisor tool or a warm `pstack:poteto-agent`, and
5
+ consult it before substantive work, completion, commits, or when stuck.
6
+ Triggers:
7
+ 'team-advisor', 'team advisor', 'second opinion', 'consult the advisor',
8
+ 'get an advisor', 'check my approach with an advisor'.
9
9
  ---
10
10
 
11
11
  # Team Advisor
@@ -18,14 +18,14 @@ One warm advisor at the strongest tier this session can reach. This session is t
18
18
  |---|---|
19
19
  | [`docs/references/advisor-tool.md`](../../docs/references/advisor-tool.md) | **Consult cadence and weight.** When to call, the hard rule before first write, and how to treat advice. Read this for every consult. |
20
20
  | [`~/.claude/_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md) | **Bind and lifecycle.** Session identity, host detect, model floor, warm-up, CLI fallback. Its read map routes each moment to a `reference/` detail file. |
21
- | [`agents/session-advisor.md`](../../agents/session-advisor.md) | **Reply contract.** ENDORSE / CORRECTION / PLAN / STOP. SendMessage only. |
21
+ | Installed `poteto-mode` skill | **Reply contract.** The advisor prompt carries ENDORSE / CORRECTION / PLAN / STOP. |
22
22
  | [`reference/advisor-docs-review.md`](reference/advisor-docs-review.md) | Anthropic advisor-tool source facts: measured effects, Sonnet steering, cost levers, failure modes. Background. Read it when tuning the bind, not on every consult. |
23
23
 
24
24
  ## Bind
25
25
 
26
26
  1. Name the session identity first (protocol **Host profiles**), then walk the model floor.
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
- 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.
27
+ 2. Claude: when `advisor` is in this session's tool list, the built-in advisor tool is the advisor. Spawn nothing and call `advisor()` at each consult point. Otherwise spawn or resume `pstack:poteto-agent` at `ADVISOR_EFFORT` (default low) with the advisor response contract in the prompt. When the bound model is out of usage, use the configured fallback at the same effort. Codex: use the native advisor path. Third-party: use the headless advisor path. When the host's walk fails, fail closed.
28
+ 3. Name the warm instance `team-advisor-agent` and keep its advisor response contract in every first prompt. When a native Codex subagent spawn is the advisor path, pass `flags: ["--advisor"]` with Astra.
29
29
  4. Skip the multi-consumer "who you are" opener. This session is the sole consumer.
30
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.
31
31
 
@@ -39,10 +39,12 @@ Follow **When to call**, **Hard rule**, and **How to treat advice** in `advisor-
39
39
 
40
40
  Build every first brief with [`_shared/advisor/reference/consult-format.md`](../../_shared/advisor/reference/consult-format.md). Later briefs carry only the delta and changed evidence.
41
41
 
42
+ With the built-in advisor tool, call `advisor()` with no brief. The tool forwards the whole transcript. Its reply is free text, not one of the four signal words, so weigh it per **How to treat advice** in `advisor-tool.md`.
43
+
42
44
  Aim for two consults on a normal task: one after orientation and one after writes and validation. Reserve a third for advisory recovery or reconciliation guidance, and add a consult when a material fork produces new evidence. This is an advisory target owned by the task, not a cap or gate.
43
45
 
44
46
  ## Constraints
45
47
 
46
- - One bind per session; this session owns spawn, in-session Astra spawn, or CLI bind, drift re-bind, and shutdown.
48
+ - One bind per session; this session owns the built-in tool choice, spawn, in-session Astra spawn, or CLI bind, drift re-bind, and shutdown.
47
49
  - Bind at or above the protocol floor for this host.
48
50
  - The advisor only answers (messaging); the session runs tools and posts.
@@ -125,7 +125,7 @@ directly; the wording lives under **Brevity cue** in
125
125
  Direct address works because the advisor reads the executor's prompt as
126
126
  quoted context: "instructions that address the advisor directly are followed
127
127
  much more reliably than third-person descriptions." A brief that asks for
128
- roughly 80 percent of the true ceiling raises consult frequency while
128
+ roughly 80 percent of the ceiling raises consult frequency while
129
129
  lowering total cost.
130
130
 
131
131
  Typical advisor output runs 400–700 text tokens, or 1,400–1,800 with
@@ -205,3 +205,30 @@ successful task.
205
205
 
206
206
  Track, per route: completion rate, regression rate, tool calls, tokens by
207
207
  tier, and latency.
208
+
209
+ ## I. Verifying the built-in tool path
210
+
211
+ Repository practice, observed on Claude Code 2.1.277: `claude plugin eval`
212
+ cannot reach the built-in tool path. Its sandbox turns off feature-flag
213
+ fetching, and `/advisor` replies "isn't available in this environment". A
214
+ plugin-eval suite therefore grades the warm-agent path alone.
215
+
216
+ Drive the built-in tool path with a headless run, once with the skill and once
217
+ without:
218
+
219
+ ```text
220
+ claude -p "<task>" --advisor opus --plugin-dir <wrapper> \
221
+ --setting-sources project --strict-mcp-config \
222
+ --allowedTools "Read,Glob,Grep,Skill,Agent,SendMessage,Write,Edit" \
223
+ --permission-mode dontAsk --output-format stream-json --verbose
224
+ ```
225
+
226
+ Count main-thread content blocks with `type: server_tool_use` and
227
+ `name: advisor`. Keep each run's folder outside `<wrapper>`, because
228
+ `dontAsk` denies writes under a loaded plugin directory. Read
229
+ `permission_denials` in each run before you compare the two arms.
230
+
231
+ Run a positive control first, with a prompt that asks for the advisor by name.
232
+ A zero count means the tool was never attached, or the model chose not to
233
+ call it. The control tells the two apart. An empty `CLAUDE_CONFIG_DIR` drops
234
+ the login, so keep the user config and use `--setting-sources project`.
@@ -33,7 +33,7 @@ On exit 0 the script prints one JSON object:
33
33
  | `session_utilization` | Percent of the 5-hour window spent (null on override) |
34
34
  | `weekly_utilization` | Percent of the weekly window spent (null on override) |
35
35
  | `weekly_resets_at` | When the weekly window resets (null on override) |
36
- | `weekly_near_cap` | True when the weekly meter is at or past the warn threshold |
36
+ | `weekly_near_cap` | `true` when the weekly meter is at or past the warn threshold |
37
37
 
38
38
  On exit 2 the script prints `{"error": ...}`. Ask the user for a manual reset time via AskUserQuestion (offer clock-time and duration examples), then rerun with `--override`.
39
39
 
@@ -68,7 +68,7 @@ Before the first sleep:
68
68
 
69
69
  The stage plan (`stages_seconds` from the resolver) keeps every stage under the maximum stage length and ends with a short tail so the final firing lands just past the reset. Stage sizing constants live in `scripts/usage_pause_constants/resolve_usage_window_constants.py`; a leftover too short to stand alone folds into the tail.
70
70
 
71
- Every wakeup does exactly three things — ping, record, schedule — and dispatches no new work. The cache rationale: an unpinged idle agent left past the cache window resumes cold and re-reads its whole transcript, so pings run tighter than the cache lifetime and keep each agent's next real invocation cheap.
71
+ Every wakeup does exactly three things — ping, record, schedule — and dispatches no new work. The cache rationale: an unpinged idle agent left past the cache window resumes cold and re-reads its whole transcript, so pings run tighter than the cache lifetime and keep each agent's next invocation cheap.
72
72
 
73
73
  ### Stage wakeup prompt template
74
74
 
@@ -78,7 +78,7 @@ Remaining chain (seconds): <remaining_stage_durations>. Cancelled crons: <cancel
78
78
  1. Ping every live agent AND every idle-but-warm agent with exactly this one line:
79
79
  "status checkpoint: reply with where you stand, do not start new work"
80
80
  An unpinged idle agent past the cache window resumes cold and re-reads its whole
81
- transcript; the ping keeps its next real invocation cheap.
81
+ transcript; the ping keeps its next invocation cheap.
82
82
  2. Record any finished agent results on the task list. Dispatch nothing.
83
83
  3. Take the first duration off the remaining chain and ScheduleWakeup it, passing this
84
84
  same prompt with that duration removed and the stage number advanced. When the
@@ -62,7 +62,9 @@ On Codex: Astra is the in-session default. The `ADVISOR_ASTRA` flag is not requi
62
62
 
63
63
  ### Claude host
64
64
 
65
- Use the **Model floor** ladder below (Fable first, then Astra when Fable is out of usage).
65
+ When `advisor` is in the session's tool list, the built-in advisor tool is the advisor. The user turns it on with `/advisor`, the `advisorModel` setting, or `--advisor`. Spawn nothing and call `advisor()` at each consult point. The tool forwards the whole transcript, so a consult needs no packet. Its reply is free text, so the four signal words do not apply; weigh it per `docs/references/advisor-tool.md` **How to treat advice**. It is a server tool, so hooks and the spawn-walk log do not see it. A Fable or Opus 5 advisor returns an encrypted result that a log cannot read. When a readable record matters, use the warm agent below.
66
+
67
+ When `advisor` is not in the tool list, use the **Model floor** ladder below (Fable first, then Astra when Fable is out of usage).
66
68
  Warm-up spawns `subagent_type: session-advisor` via the Agent tool for Fable; consults go through `SendMessage` to that warm agent. Astra uses the Codex helper.
67
69
  Assemble and paste each executor's Advisor block per the **Advisor block** section.
68
70
 
@@ -85,6 +87,7 @@ Executors report to the orchestrating session; that session consults the bound a
85
87
 
86
88
  ## Model floor
87
89
 
90
+ The built-in advisor tool sits outside this ladder. Claude Code and the API accept it only when the advisor is at least as capable as the main model, and that check is its floor.
88
91
  On Claude and ThirdParty the advisor ladder is `Fable` first, then Astra (flag-gated, Codex CLI) when Fable is out of usage.
89
92
  On Codex the walk is Astra only, in-session.
90
93
  Opus is not an advisor candidate. `Sonnet` and `Haiku` are executor tiers only.
@@ -103,7 +106,8 @@ The validator checks ladder shape only; host policy sits on top.
103
106
 
104
107
  ## Warm-up (once per session)
105
108
 
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.
109
+ On a **Claude host** with `advisor` in the tool list, skip the warm-up; the built-in tool needs none.
110
+ On a **Claude host** without it, 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
111
  Full spawn fields and the charter template: [`reference/warm-up.md`](reference/warm-up.md).
108
112
 
109
113
  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).
@@ -141,7 +145,7 @@ Modes and failover, the tier-to-alias table, brief piping, and `--resume` sessio
141
145
 
142
146
  **Codex host:** do not use this runner as the primary path. Astra binds in-session.
143
147
 
144
- **Claude host:** fall back to this runner exactly when one of these holds:
148
+ **Claude host:** the built-in advisor tool never falls back to this runner. On the warm-agent path, fall back to this runner exactly when one of these holds:
145
149
  - The Agent-tool spawn errors at every candidate tier down to the floor. The tool itself is unavailable.
146
150
  - `SendMessage` to the shared advisor errors, or draws no reply within the bound in `ADVISOR_SENDMESSAGE_REPLY_WAIT_SECONDS` (120) in `$HOME/.claude/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py`, and a re-spawn also fails.
147
151
  - The running session is itself a subagent barred from spawning further agents.
@@ -3,7 +3,7 @@
3
3
  Detail behind the **Advisor block** section of [`advisor-protocol.md`](../advisor-protocol.md).
4
4
  Open this when assembling the block for an executor spawn prompt.
5
5
 
6
- Assembly order: one transport preamble picked by host profile, then the shared core, then the weak-executor add-on for an executor at Sonnet or below.
6
+ Assembly order: one transport preamble picked by host profile, then the shared core, then the weak-executor add-on for an executor at Sonnet or below. A Claude host with the built-in advisor tool takes its own block and skips the preamble and the shared core.
7
7
  Paste the assembled block at the **top** of the spawn prompt, ahead of any other sentence that mentions the advisor.
8
8
  The assembled block is self-contained. The executor receives this text alone, so every path it names is absolute.
9
9
  The consult rules it restates are owned by [`consult-format.md`](consult-format.md); edit that file first and carry the change here.
@@ -12,6 +12,13 @@ The consult rules it restates are owned by [`consult-format.md`](consult-format.
12
12
 
13
13
  > A shared session advisor named `<name>` is reachable via SendMessage; send each consult to it directly by that name.
14
14
 
15
+ ## Block for a Claude host with the built-in advisor tool
16
+
17
+ Subagents inherit the session's advisor tool, so the executor calls it directly. Paste this block alone, then the weak-executor add-on for an executor at Sonnet or below. The shared core's packet and signal-word lines do not apply, and neither does the add-on's 80-word line.
18
+
19
+ > Your session has the built-in `advisor` tool. Call `advisor()` before locking in a nontrivial approach, once you believe your assignment is done, before any hard-to-reverse action, when the same failure repeats or progress has stalled, and when the chosen approach is being reconsidered.
20
+ > The tool reads your whole transcript, so call it with no brief. Its reply is free text. Give it serious weight; when your evidence contradicts it, call again and name the conflict.
21
+
15
22
  ## Transport preamble for a Codex host
16
23
 
17
24
  > A shared session advisor named `<name>` is reachable as a native Codex Astra subagent; send each consult to it in-session by that name.
@@ -20,14 +20,14 @@
20
20
  |---|---|---|
21
21
  | F1 | Catch-all except clauses | `except:` (bare), `except Exception:`, `except BaseException:` followed by `pass` / `continue` / log-only. |
22
22
  | F2 | Errors logged then swallowed | `logger.error(...)` followed by `return None` / `return default` without re-raise. |
23
- | F3 | Default fallback values masking failure | `dict.get(key, default)` where the absence of the key is itself a bug; `or default` short-circuits hiding `None`. Includes the stale-payload-key shape: a `payload.get("KEY", "")` (or `payload["KEY"]` wrapped in a fallback) read against an external-input dict whose contract the diff migrated — the rest of the module reads the payload through a different key set named in the docstring and bound to same-named variables, while this lone read targets a dropped key, so it resolves to the default on every real payload and silently records an empty value into the field it feeds. The audit teammate lists every string-literal key read from each `*_payload` / event / request dict, checks each key against the payload contract the module's docstring and other reads set up, and flags a key read at one site that no docstring, second read, or same-named binding anchors. A key consumed inline with a meaningful default (`resolve(payload.get("cwd", "."))`) is legitimate, not stale — the flag is the dropped key whose value the field needs but never receives. |
23
+ | F3 | Default fallback values masking failure | `dict.get(key, default)` where the absence of the key is itself a bug; `or default` short-circuits hiding `None`. Includes the stale-payload-key shape: a `payload.get("KEY", "")` (or `payload["KEY"]` wrapped in a fallback) read against an external-input dict whose contract the diff migrated — the rest of the module reads the payload through a different key set named in the docstring and bound to same-named variables, while this lone read targets a dropped key, so it resolves to the default on every payload and silently records an empty value into the field it feeds. The audit teammate lists every string-literal key read from each `*_payload` / event / request dict, checks each key against the payload contract the module's docstring and other reads set up, and flags a key read at one site that no docstring, second read, or same-named binding anchors. A key consumed inline with a meaningful default (`resolve(payload.get("cwd", "."))`) is legitimate, not stale — the flag is the dropped key whose value the field needs but never receives. |
24
24
  | F4 | Async task error swallowing | `asyncio.create_task(...)` without exception observation; `gather(..., return_exceptions=True)` consumed loosely. |
25
25
  | F5 | Boolean / status returns identical on success and failure | A function returns `True` on the happy path and `True` on the catch-all error path. |
26
26
  | F6 | Ignored return values from fallible calls | `subprocess.run` without `check=True` and unchecked `returncode`; `os.write` return value discarded. |
27
27
  | F7 | PowerShell error-suppression patterns | `-ErrorAction SilentlyContinue` followed by `.Property` access; `2>$null` or `*>$null`; `$?` not consulted. |
28
28
  | F8 | Test-level swallowing | Tests that catch and log instead of asserting; `pytest.warns` used instead of `pytest.raises`. |
29
29
  | F9 | Gate-validator self-defeat via parse-failure swallow | A new gate / validator / hook check parses input as code (`ast.parse`) and catches the parse error with `return []` / `return None` / `return True` (clean signal). When the dispatcher feeds the check a partial fragment (e.g., the Edit tool's `new_string` rather than the full file content), the parse always fails and the check silently fires zero findings. The audit teammate lists every new `ast.parse` / `tokenize` / `json.loads` / `yaml.safe_load` call in gate code and asks: does the catch branch produce a clean signal that would mask the gate being broken? |
30
- | F10 | Guard helper returns success-default on unverifiable input | A guard helper / predicate / classifier short-circuits to `True` / `Ok` / the success sentinel when it cannot validate the input shape (missing positional args, wrong arity, unexpected None). Guards must default-deny when they cannot verify; default-allow on unverifiable input masks real violations downstream. |
30
+ | F10 | Guard helper returns success-default on unverifiable input | A guard helper / predicate / classifier short-circuits to `True` / `Ok` / the success sentinel when it cannot validate the input shape (missing positional args, wrong arity, unexpected None). Guards must default-deny when they cannot verify; default-allow on unverifiable input masks violations downstream. |
31
31
 
32
32
  ---
33
33
 
@@ -33,6 +33,6 @@
33
33
  The reusable Variant C template for Category I is in [`../prompts/category-i-concurrency.md`](../prompts/category-i-concurrency.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's concurrency model.
34
34
 
35
35
  For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category I walks for that diff:
36
- - I4: TOCTOU between `os.walk` enumerating a directory and `os.path.getctime` / `os.rmdir` on the same path — another process could delete or repopulate the dir in the window. The `try/except OSError` handles the race correctly (Category F notes the same blocks for silent-failure concerns; here they're actually protective).
36
+ - I4: TOCTOU between `os.walk` enumerating a directory and `os.path.getctime` / `os.rmdir` on the same path — another process could delete or repopulate the dir in the window. The `try/except OSError` handles the race correctly (Category F notes the same blocks for silent-failure concerns; here they're protective).
37
37
  - I4 (PowerShell): `Test-Path $Target` followed by `Register-ScheduledTask` — directory could be deleted between the check and the registration. Low-impact since the schedule still registers.
38
38
  - I1, I2, I3, I5–I8: not applicable — script is single-threaded synchronous Python with no asyncio, no shared mutable state across processes.