claude-dev-env 1.82.0 → 1.84.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/CLAUDE.md +16 -13
- package/_shared/pr-loop/audit-contract.md +24 -12
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/README.md +1 -0
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviewer_availability_constants.py +12 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +0 -2
- package/_shared/pr-loop/scripts/reviewer_availability.py +182 -0
- package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +9 -33
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +2 -0
- package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
- package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
- package/_shared/pr-loop/scripts/tests/test_reviewer_availability.py +159 -0
- package/_shared/pr-loop/scripts/tests/test_reviewer_availability_constants.py +36 -0
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +14 -4
- package/agents/clean-coder.md +3 -0
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
- package/bin/install.mjs +16 -8
- package/bin/install.test.mjs +17 -6
- package/commands/CLAUDE.md +0 -1
- package/docs/CODE_RULES.md +1 -1
- package/hooks/blocking/CLAUDE.md +2 -4
- package/hooks/blocking/code_rules_constants_config.py +164 -1
- package/hooks/blocking/code_rules_docstrings.py +428 -15
- package/hooks/blocking/code_rules_enforcer.py +33 -0
- package/hooks/blocking/code_rules_imports_logging.py +867 -1
- package/hooks/blocking/code_rules_magic_values.py +5 -0
- package/hooks/blocking/code_rules_naming_collection.py +152 -6
- package/hooks/blocking/code_rules_shared.py +34 -0
- package/hooks/blocking/code_rules_string_magic.py +68 -0
- package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
- package/hooks/blocking/pre_tool_use_dispatcher.py +3 -3
- package/hooks/blocking/reviewer_spawn_gate.py +182 -0
- package/hooks/blocking/stale_comment_reference_blocker.py +267 -0
- package/hooks/blocking/state_description_blocker.py +96 -5
- package/hooks/blocking/test_code_rules_config_duplicate_path_anchor.py +132 -0
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +2 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +385 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
- package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +67 -0
- package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +40 -0
- package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +213 -0
- package/hooks/blocking/test_code_rules_enforcer_referenced_underscore_loop.py +169 -0
- package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
- package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
- package/hooks/blocking/test_code_rules_js_bare_flag_return_directive.py +266 -0
- package/hooks/blocking/test_code_rules_js_sibling_return_object_key_drift.py +490 -0
- package/hooks/blocking/test_code_rules_logging_adjacent_literals.py +171 -0
- package/hooks/blocking/test_code_rules_magic_values.py +54 -0
- package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
- package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +9 -3
- package/hooks/blocking/test_reviewer_spawn_gate.py +230 -0
- package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
- package/hooks/blocking/test_stale_comment_reference_blocker.py +236 -0
- package/hooks/blocking/test_state_description_blocker.py +135 -0
- package/hooks/hooks.json +5 -0
- package/hooks/hooks_constants/CLAUDE.md +3 -4
- package/hooks/hooks_constants/blocking_check_limits.py +46 -0
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +41 -0
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
- package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
- package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +4 -0
- package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +41 -0
- package/hooks/hooks_constants/stale_comment_reference_blocker_constants.py +76 -0
- package/hooks/hooks_constants/state_description_blocker_constants.py +8 -0
- package/hooks/validation/post_tool_use_dispatcher.py +1 -1
- package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
- package/hooks/workflow/CLAUDE.md +2 -8
- package/package.json +1 -1
- package/rules/CLAUDE.md +5 -2
- package/rules/claude-md-orphan-file.md +5 -0
- package/rules/docstring-prose-matches-implementation.md +10 -1
- package/rules/env-var-table-code-drift.md +5 -0
- package/rules/es-exe-file-search.md +17 -0
- package/rules/no-historical-clutter.md +12 -1
- package/rules/orphan-css-class.md +5 -0
- package/rules/package-inventory-stale-entry.md +10 -0
- package/rules/paired-test-coverage.md +5 -0
- package/rules/plain-illustrative-docstrings.md +40 -1
- package/rules/verify-before-asking.md +7 -0
- package/rules/verify-runtime-state.md +40 -0
- package/rules/windows-filesystem-safe.md +8 -0
- package/rules/workers-done-before-complete.md +33 -0
- package/rules/workflow-substitution-slots.md +5 -0
- package/skills/CLAUDE.md +7 -2
- package/skills/autoconverge/SKILL.md +48 -61
- package/skills/autoconverge/reference/closing-report.md +6 -6
- package/skills/autoconverge/reference/convergence.md +17 -15
- package/skills/autoconverge/reference/gotchas.md +6 -3
- package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
- package/skills/autoconverge/workflow/converge.contract.test.mjs +153 -10
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +55 -19
- package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
- package/skills/autoconverge/workflow/converge.mjs +167 -106
- package/skills/autoconverge/workflow/render_report.py +7 -11
- package/skills/bugteam/CLAUDE.md +1 -1
- package/skills/bugteam/PROMPTS.md +7 -6
- package/skills/bugteam/SKILL.md +25 -72
- package/skills/bugteam/reference/CLAUDE.md +1 -3
- package/skills/bugteam/reference/README.md +1 -1
- package/skills/bugteam/reference/audit-and-teammates.md +1 -1
- package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
- package/skills/bugteam/reference/team-setup.md +8 -7
- package/skills/bugteam/scripts/CLAUDE.md +0 -6
- package/skills/bugteam/scripts/README.md +0 -4
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
- package/skills/code/SKILL.md +2 -0
- package/skills/copilot-review/CLAUDE.md +1 -1
- package/skills/copilot-review/SKILL.md +25 -23
- package/skills/everything-search/SKILL.md +5 -0
- package/skills/findbugs/CLAUDE.md +2 -2
- package/skills/findbugs/SKILL.md +22 -83
- package/skills/fixbugs/SKILL.md +2 -4
- package/skills/log-audit/CLAUDE.md +20 -0
- package/skills/log-audit/SKILL.md +68 -0
- package/skills/log-audit/reference/CLAUDE.md +9 -0
- package/skills/log-audit/reference/charter.md +52 -0
- package/skills/log-audit/scripts/CLAUDE.md +27 -0
- package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
- package/skills/log-audit/scripts/collect_log_window.py +199 -0
- package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
- package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
- package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
- package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
- package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
- package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
- package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
- package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
- package/skills/monitor-open-prs/SKILL.md +2 -2
- package/skills/post-audit-findings/SKILL.md +84 -0
- package/skills/pr-converge/CLAUDE.md +2 -0
- package/skills/pr-converge/SKILL.md +72 -59
- package/skills/pr-converge/reference/CLAUDE.md +1 -1
- package/skills/pr-converge/reference/convergence-gates.md +16 -19
- package/skills/pr-converge/reference/examples.md +5 -5
- package/skills/pr-converge/reference/fix-protocol.md +16 -43
- package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
- package/skills/pr-converge/reference/per-tick.md +24 -45
- package/skills/pr-converge/reference/state-schema.md +15 -0
- package/skills/pr-converge/scripts/README.md +3 -5
- package/skills/pr-fix-protocol/SKILL.md +70 -0
- package/skills/pr-loop-lifecycle/SKILL.md +73 -0
- package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
- package/skills/pr-scope-resolve/SKILL.md +48 -0
- package/skills/qbug/CLAUDE.md +4 -4
- package/skills/qbug/SKILL.md +46 -144
- package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
- package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
- package/skills/reviewer-gates/SKILL.md +96 -0
- package/skills/session-log/CLAUDE.md +7 -7
- package/skills/session-log/SKILL.md +27 -44
- package/skills/test_markdown_link_integrity.py +103 -0
- package/commands/doc-gist.md +0 -16
- package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
- package/hooks/blocking/conftest.py +0 -30
- package/hooks/blocking/md_path_exemptions.py +0 -224
- package/hooks/blocking/md_to_html_blocker.py +0 -155
- package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
- package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
- package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
- package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
- package/hooks/hooks_constants/html_companion_constants.py +0 -20
- package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
- package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
- package/hooks/workflow/doc_gist_auto_publish.py +0 -144
- package/hooks/workflow/md_to_html_companion.py +0 -358
- package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
- package/hooks/workflow/test_md_to_html_companion.py +0 -613
- package/skills/bugteam/reference/audit-contract.md +0 -163
- package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
- package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
- package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
- package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
- package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
- package/skills/doc-gist/CLAUDE.md +0 -25
- package/skills/doc-gist/SKILL.md +0 -97
- package/skills/doc-gist/references/CLAUDE.md +0 -9
- package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
- package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
- package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
- package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
- package/skills/doc-gist/references/examples/05-design-system.html +0 -629
- package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
- package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
- package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
- package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
- package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
- package/skills/doc-gist/references/examples/11-status-report.html +0 -528
- package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
- package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
- package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
- package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
- package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
- package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
- package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
- package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
- package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
- package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
- package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
- package/skills/doc-gist/references/examples/README.md +0 -5
- package/skills/doc-gist/scripts/CLAUDE.md +0 -27
- package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
- package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
- package/skills/doc-gist/scripts/gist_upload.py +0 -177
- package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
- /package/skills/{doc-gist/scripts/doc_gist_scripts_constants → log-audit/scripts/log_audit_constants}/__init__.py +0 -0
package/skills/qbug/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: qbug
|
|
|
3
3
|
description: >-
|
|
4
4
|
Required baseline review for every new PR. Runs the /bugteam audit → fix →
|
|
5
5
|
commit → push cycle via one clean-coder subagent (not a full team), looping
|
|
6
|
-
until convergence or stuck. Uses the same CODE_RULES gate, A–
|
|
6
|
+
until convergence or stuck. Uses the same CODE_RULES gate, A–P category
|
|
7
7
|
rubric, and per-loop PR review shape as /bugteam — without TeamCreate,
|
|
8
8
|
teammates, per-loop clean-room, or a loop cap. Invoke /bugteam instead for
|
|
9
9
|
larger PRs that need per-loop bias isolation or a hard loop cap. Triggers:
|
|
@@ -21,8 +21,8 @@ Shared artifacts with /bugteam are referenced below by path, using the `${CLAUDE
|
|
|
21
21
|
|
|
22
22
|
- Pre-flight script: `${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/preflight.py`
|
|
23
23
|
- Code-rules gate script: `${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/code_rules_gate.py`
|
|
24
|
-
- Bug category rubric A–
|
|
25
|
-
- **Audit contract** (finding schema, proof-of-absence, adversarial pass, Haiku secondary, post-fix self-audit, diagnostics JSON): [`
|
|
24
|
+
- Bug category rubric A–P: [`bugteam/PROMPTS.md`](../bugteam/PROMPTS.md#audit-spawn-prompt-xml-bugfind-teammate)
|
|
25
|
+
- **Audit contract** (finding schema, proof-of-absence, adversarial pass, Haiku secondary, post-fix self-audit, diagnostics JSON): [`_shared/pr-loop/audit-contract.md`](../../_shared/pr-loop/audit-contract.md)
|
|
26
26
|
- PR comment lifecycle shape: [`bugteam/SKILL.md`](../bugteam/SKILL.md#audit-posting)
|
|
27
27
|
|
|
28
28
|
## When this skill applies
|
|
@@ -31,12 +31,15 @@ Shared artifacts with /bugteam are referenced below by path, using the `${CLAUDE
|
|
|
31
31
|
|
|
32
32
|
Refusals — first match wins; respond with the quoted line exactly and stop:
|
|
33
33
|
|
|
34
|
-
- **Disabled via environment.** When `CLAUDE_REVIEWS_DISABLED`
|
|
35
|
-
token `bugteam
|
|
36
|
-
`/qbug is disabled via CLAUDE_REVIEWS_DISABLED.`
|
|
34
|
+
- **Disabled via environment.** When `CLAUDE_REVIEWS_DISABLED` carries the
|
|
35
|
+
token `bugteam`:
|
|
36
|
+
`/qbug is disabled via CLAUDE_REVIEWS_DISABLED.` Run the check via
|
|
37
|
+
`python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer bugteam`
|
|
38
|
+
(exit 0 = disabled). `/qbug` is the bugteam
|
|
37
39
|
baseline review and shares the `bugteam` token with `/bugteam`; the shared
|
|
38
40
|
pre-flight script also exits 7 in this case so any caller invoking it
|
|
39
|
-
directly halts on the same signal.
|
|
41
|
+
directly halts on the same signal. The gate semantics live in the
|
|
42
|
+
`reviewer-gates` skill (`../reviewer-gates/SKILL.md`).
|
|
40
43
|
- **No PR or upstream diff.** `No PR or upstream diff. /qbug needs a target.`
|
|
41
44
|
- **Dirty tree.** `Uncommitted changes detected. Stash, commit, or revert before /qbug.`
|
|
42
45
|
- **Missing subagent.** Before Step 2, confirm `clean-coder` exists. Else: `Required subagent type clean-coder not installed. /qbug needs clean-coder available.`
|
|
@@ -72,9 +75,7 @@ Pre-flight checks (in order):
|
|
|
72
75
|
|
|
73
76
|
## Step 1: Resolve PR scope (lead)
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
2. Else `git merge-base HEAD origin/<default>` then `git diff <merge-base>...HEAD`
|
|
77
|
-
3. Else refuse per § When this skill applies.
|
|
78
|
+
Apply the `pr-scope-resolve` skill (`../pr-scope-resolve/SKILL.md`) with caller `qbug`. When no target exists, refuse per § When this skill applies with the sub-skill's canonical line.
|
|
78
79
|
|
|
79
80
|
Capture: `owner/repo`, `baseRefName`, `headRefName`, PR `number`, `url`, `starting_sha = git rev-parse HEAD`.
|
|
80
81
|
|
|
@@ -116,7 +117,7 @@ Agent(
|
|
|
116
117
|
subagent_type="code-quality-agent",
|
|
117
118
|
model="haiku",
|
|
118
119
|
description="qbug Haiku secondary audit for PR <number>",
|
|
119
|
-
prompt="<audit-only prompt: read the PR diff, apply A
|
|
120
|
+
prompt="<audit-only prompt: read the PR diff, apply A–P categories from <categories_file>, return structured findings. No FIX, no git add, no git commit, no git push.>",
|
|
120
121
|
run_in_background=False
|
|
121
122
|
)
|
|
122
123
|
```
|
|
@@ -187,11 +188,12 @@ The subagent receives this prompt and loops internally — the lead does not re-
|
|
|
187
188
|
|
|
188
189
|
- Read the patch file.
|
|
189
190
|
- Audit only added/modified lines. Read <categories_file> for the
|
|
190
|
-
A–
|
|
191
|
+
A–P category definitions; investigate each category explicitly.
|
|
191
192
|
- Follow the shared audit contract at
|
|
192
|
-
|
|
193
|
-
either a Shape A structured finding or a Shape B
|
|
194
|
-
proof-of-absence. Bare "verified clean" labels are
|
|
193
|
+
$HOME/.claude/_shared/pr-loop/audit-contract.md. Per category:
|
|
194
|
+
produce either a Shape A structured finding or a Shape B
|
|
195
|
+
structured proof-of-absence. Bare "verified clean" labels are
|
|
196
|
+
REJECTED.
|
|
195
197
|
- Run the contract's adversarial second pass after the primary
|
|
196
198
|
finding list.
|
|
197
199
|
- The LEAD spawns the Haiku secondary auditor in parallel with
|
|
@@ -203,87 +205,20 @@ The subagent receives this prompt and loops internally — the lead does not re-
|
|
|
203
205
|
<qbug_temp_dir>/loop-<loop_count>-audit.json per the contract's
|
|
204
206
|
persistence schema.
|
|
205
207
|
|
|
206
|
-
Post ONE review per loop
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
`
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
at `Fix:` (including the trailing `Validation:` clause) becomes
|
|
221
|
-
`fix_summary` (the `failure_mode` field carries the full
|
|
222
|
-
audit-to-fix handoff per
|
|
223
|
-
[`agents/code-quality-agent.md`](../../agents/code-quality-agent.md)).
|
|
224
|
-
When a finding's `failure_mode` omits the `Fix:` heading, write
|
|
225
|
-
the full text to BOTH `description` and `fix_summary`. Set
|
|
226
|
-
`side="RIGHT"` for every entry. Zero anchored findings → write
|
|
227
|
-
`[]` and pass `--state CLEAN`; one or more anchored findings →
|
|
228
|
-
pass `--state DIRTY` with the full list.
|
|
229
|
-
|
|
230
|
-
**Self-PR auto-toggle.** GitHub rejects both `APPROVE` and
|
|
231
|
-
`REQUEST_CHANGES` reviews with HTTP 422 when the authenticated
|
|
232
|
-
identity matches the PR author ("Cannot approve/request changes
|
|
233
|
-
on your own pull request"). `post_audit_thread.py` detects this
|
|
234
|
-
case via `gh api user` + `gh api repos/<o>/<r>/pulls/<n>` and
|
|
235
|
-
auto-resolves an alternate gh account's token for the reviews
|
|
236
|
-
POST — the active `gh auth` account is not mutated; only the
|
|
237
|
-
bearer token sent on the request changes. After the POST the
|
|
238
|
-
active account is still whoever it was before, so no "swap back"
|
|
239
|
-
step is needed.
|
|
240
|
-
|
|
241
|
-
Configuration:
|
|
242
|
-
|
|
243
|
-
- `GH_TOKEN` / `GITHUB_TOKEN` env vars take precedence over the
|
|
244
|
-
toggle. Set them when you need to pin a specific reviewer
|
|
245
|
-
identity by token rather than by account login.
|
|
246
|
-
- `BUGTEAM_REVIEWER_ACCOUNT` env var names which authenticated
|
|
247
|
-
alternate to prefer when a toggle is needed (for example,
|
|
248
|
-
`BUGTEAM_REVIEWER_ACCOUNT=jl-cmd`). The env var name is shared
|
|
249
|
-
across every skill that invokes `post_audit_thread.py`. When
|
|
250
|
-
unset, the script falls back to the first alternate account
|
|
251
|
-
`gh auth status` reports.
|
|
252
|
-
- The named alternate must be logged in (`gh auth login -h
|
|
253
|
-
github.com -u <login>`) before the audit skill runs. The
|
|
254
|
-
script exits 1 with a pointing-at-`gh auth login` message
|
|
255
|
-
when self-PR is detected and no usable alternate is
|
|
256
|
-
authenticated.
|
|
257
|
-
|
|
258
|
-
```
|
|
259
|
-
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py" \
|
|
260
|
-
--skill qbug \
|
|
261
|
-
--owner <owner> \
|
|
262
|
-
--repo <repo> \
|
|
263
|
-
--pr-number <pr_number> \
|
|
264
|
-
--commit <head_sha> \
|
|
265
|
-
--state <CLEAN|DIRTY> \
|
|
266
|
-
--findings-json <qbug_temp_dir>/loop-<loop_count>-findings.json
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
The script POSTs a single review with `event=APPROVE` on CLEAN
|
|
270
|
-
(the request event; GitHub stores it as `state=APPROVED`; empty
|
|
271
|
-
`comments[]`, body documents "no findings") or
|
|
272
|
-
`event=REQUEST_CHANGES` on DIRTY (one inline anchored comment per
|
|
273
|
-
finding; each becomes its own resolvable thread on the PR). It
|
|
274
|
-
handles retries internally (1s / 4s / 16s backoff across four
|
|
275
|
-
attempts). Exit 0 emits the new review's `html_url` to stdout;
|
|
276
|
-
extract the numeric review id from the URL's
|
|
277
|
-
`#pullrequestreview-<id>` suffix (the trailing URL fragment of
|
|
278
|
-
`html_url`, the part after `#`). Then harvest child-comment URLs **and PR review
|
|
279
|
-
thread node ids** via
|
|
280
|
-
`pull_request_read(method="get_review_comments",
|
|
281
|
-
owner=<owner>, repo=<repo>, pullNumber=<pr_number>)` filtered to
|
|
282
|
-
that review id. The same response carries each
|
|
283
|
-
comment's PR review thread node id (e.g. `PRRT_kwDOxxx`) — match
|
|
284
|
-
children to findings in the order they appear in the findings
|
|
285
|
-
JSON. Each `loop_comment_index[finding_id]` entry must carry
|
|
286
|
-
`finding_comment_id` (numeric, used by
|
|
208
|
+
Post ONE review per loop. Read
|
|
209
|
+
$HOME/.claude/skills/post-audit-findings/SKILL.md and apply it
|
|
210
|
+
with `--skill qbug`. That skill owns the findings-JSON mapping,
|
|
211
|
+
the anchored-only serialization, the CLEAN/DIRTY decision, the
|
|
212
|
+
self-PR reviewer toggle, and the exit codes. qbug-specific
|
|
213
|
+
persistence: write the anchored findings JSON to
|
|
214
|
+
`<qbug_temp_dir>/loop-<loop_count>-findings.json` and pass that
|
|
215
|
+
path as `--findings-json`. Unanchored findings surface in the
|
|
216
|
+
loop's user-facing summary rather than as inline anchored
|
|
217
|
+
comments.
|
|
218
|
+
|
|
219
|
+
On exit 0, harvest ids per that skill's "Harvest ids for the fix
|
|
220
|
+
loop" section: each `loop_comment_index[finding_id]` entry must
|
|
221
|
+
carry `finding_comment_id` (numeric, used by
|
|
287
222
|
`add_reply_to_pull_request_comment`), `finding_comment_url`, and
|
|
288
223
|
`thread_node_id` (`PRRT_kwDOxxx`, used by `resolve_thread`) so
|
|
289
224
|
the FIX step can reply against the comment and resolve the
|
|
@@ -313,7 +248,7 @@ The subagent receives this prompt and loops internally — the lead does not re-
|
|
|
313
248
|
for every modified file.
|
|
314
249
|
|
|
315
250
|
Post-fix self-audit: follow the contract's post-fix self-audit
|
|
316
|
-
sequence at
|
|
251
|
+
sequence at $HOME/.claude/_shared/pr-loop/audit-contract.md. Paranoid mode
|
|
317
252
|
(Haiku secondary in parallel), internal iteration cap = 3, exit
|
|
318
253
|
"stuck: post-fix audit not converging" after 3 rounds with fresh
|
|
319
254
|
findings. Only when gate_findings empty AND post_fix_findings
|
|
@@ -330,55 +265,22 @@ The subagent receives this prompt and loops internally — the lead does not re-
|
|
|
330
265
|
Write <qbug_temp_dir>/loop-<loop_count>-diagnostics.json per the
|
|
331
266
|
contract's diagnostics schema (all eight keys required).
|
|
332
267
|
|
|
333
|
-
For each finding,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
**Claude finished @<reviewer>'s task** —— <status_line>
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
### <action_heading> ✅
|
|
350
|
-
|
|
351
|
-
<1–2 paragraph plain-language explanation>
|
|
352
|
-
|
|
353
|
-
**`<file>:<line>`:**
|
|
354
|
-
- <bullet describing change or rationale>
|
|
355
|
-
- <bullet describing change or rationale>
|
|
356
|
-
|
|
357
|
-
<closing paragraph>
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Per-path `<status_line>` / `<action_heading>`:
|
|
361
|
-
- `status=fixed`: `Fixed in <short_sha>` (first 7 chars) /
|
|
362
|
-
finding-specific action verb (e.g.,
|
|
363
|
-
`Replaced Any with concrete type`).
|
|
364
|
-
- `status=could_not_address`: `Could not address this loop` /
|
|
365
|
-
one-line reason text.
|
|
366
|
-
- `status=hook_blocked`: `Hook blocked the fix commit` /
|
|
367
|
-
one-line hook summary.
|
|
368
|
-
|
|
268
|
+
For each finding, read
|
|
269
|
+
$HOME/.claude/skills/pr-fix-protocol/SKILL.md and apply its
|
|
270
|
+
reply-and-resolve unit: atomically (a) post the fix reply via
|
|
271
|
+
`add_reply_to_pull_request_comment` against
|
|
272
|
+
`loop_comment_index[finding_id].finding_comment_id`, using the
|
|
273
|
+
body template at
|
|
274
|
+
$HOME/.claude/_shared/pr-loop/audit-reply-template.md, then
|
|
275
|
+
(b) call `pull_request_review_write(method="resolve_thread",
|
|
276
|
+
threadId=<loop_comment_index[finding_id].thread_node_id>)` for
|
|
277
|
+
the same thread. Per-path `<status_line>`:
|
|
278
|
+
- `status=fixed`: `Fixed in <short_sha>` (first 7 chars).
|
|
279
|
+
- `status=could_not_address`: `Could not address this loop`.
|
|
280
|
+
- `status=hook_blocked`: `Hook blocked the fix commit`.
|
|
369
281
|
Body text is passed directly as string parameters — no temp
|
|
370
282
|
files, no jq, no shell pipes.
|
|
371
283
|
|
|
372
|
-
(b) Immediately call
|
|
373
|
-
`pull_request_review_write(method="resolve_thread",
|
|
374
|
-
threadId=<loop_comment_index[finding_id].thread_node_id>,
|
|
375
|
-
owner=<owner>, repo=<repo>, pullNumber=<pr_number>)` for the
|
|
376
|
-
same thread (this is the PR review thread node ID —
|
|
377
|
-
`PRRT_kwDOxxx` — distinct from the numeric comment ID; the
|
|
378
|
-
AUDIT step captures it at audit time when calling
|
|
379
|
-
`get_review_comments` and stores it on each
|
|
380
|
-
`loop_comment_index` entry alongside `finding_comment_id`).
|
|
381
|
-
|
|
382
284
|
Update state: last_action="fixed". Append
|
|
383
285
|
`<N> fix: <short_sha> — <fixed>/<could_not_address>/<hook_blocked>`
|
|
384
286
|
to audit_log.
|
|
@@ -443,7 +345,7 @@ Delete the resolved `<qbug_temp_dir>` tree and any `.qbug-*.md` temp files in th
|
|
|
443
345
|
- **No loop cap.** Cycle runs until `converged`, `stuck`, or `error`. User can interrupt.
|
|
444
346
|
- **Code rules gate before every AUDIT.** Same `validate_content` logic as /bugteam.
|
|
445
347
|
- **One commit per FIX action.** Linear branch, fast-forward push only.
|
|
446
|
-
- **Categories A–
|
|
348
|
+
- **Categories A–P.** Same rubric as [`bugteam/PROMPTS.md`](../bugteam/PROMPTS.md).
|
|
447
349
|
- **One review per loop.** Anchored findings as `comments[]`; unanchored findings surface in the calling skill's user-facing output (chat reply to the user) rather than in the PR review body.
|
|
448
350
|
- **PR description rewrite on every exit**, same as /bugteam Step 4.5.
|
|
449
351
|
- **Temp file cleanup on every exit path.**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Tests verifying the shared audit contract and qbug's reference to it.
|
|
2
2
|
|
|
3
|
-
The contract lives in
|
|
3
|
+
The contract lives in _shared/pr-loop/audit-contract.md and is the single
|
|
4
4
|
source of truth for finding schema, proof-of-absence shape, adversarial pass,
|
|
5
5
|
Haiku secondary, and de-dup/merge rules. qbug/SKILL.md must reference it.
|
|
6
6
|
"""
|
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
|
|
13
13
|
SKILL_FILE_PATH = Path(__file__).parent / "SKILL.md"
|
|
14
14
|
CONTRACT_FILE_PATH = (
|
|
15
|
-
Path(__file__).
|
|
15
|
+
Path(__file__).parents[2] / "_shared" / "pr-loop" / "audit-contract.md"
|
|
16
16
|
)
|
|
17
17
|
CATEGORY_E_RUBRIC_FILE_PATH = (
|
|
18
18
|
Path(__file__).parent.parent.parent
|
|
@@ -76,7 +76,7 @@ def test_should_require_loop_n_diagnostics_json() -> None:
|
|
|
76
76
|
|
|
77
77
|
def test_contract_should_require_all_eight_source_keys_in_diagnostics() -> None:
|
|
78
78
|
contract_path = (
|
|
79
|
-
Path(__file__).
|
|
79
|
+
Path(__file__).parents[2] / "_shared" / "pr-loop" / "audit-contract.md"
|
|
80
80
|
)
|
|
81
81
|
contract_text = contract_path.read_text(encoding="utf-8")
|
|
82
82
|
required_keys = [
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer-gates
|
|
3
|
+
description: >-
|
|
4
|
+
Runs the availability gates a PR-loop orchestrator checks before engaging an
|
|
5
|
+
external reviewer: the CLAUDE_REVIEWS_DISABLED opt-out parse (bugbot,
|
|
6
|
+
bugteam, and copilot tokens via reviews_disabled.py), the once-per-run
|
|
7
|
+
Copilot premium-quota pre-check (copilot_quota.py with copilot_down
|
|
8
|
+
semantics), and the Cursor Bugbot trigger/acknowledge/CI-detect flow
|
|
9
|
+
(check_bugbot_ci.py with the literal `bugbot run` comment). Invoked by
|
|
10
|
+
PR-loop orchestrators — pr-converge, autoconverge, bugteam, qbug, findbugs,
|
|
11
|
+
copilot-review, monitor-open-prs — at run start and at each reviewer
|
|
12
|
+
engagement point. Not a general code-review skill; it decides whether a
|
|
13
|
+
reviewer runs, never what the reviewer finds.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Reviewer Gates
|
|
17
|
+
|
|
18
|
+
**Core principle:** one place decides whether an external reviewer is engaged. A caller never hand-parses `CLAUDE_REVIEWS_DISABLED`, never re-queries Copilot quota mid-run, and never invents a Bugbot trigger phrase.
|
|
19
|
+
|
|
20
|
+
## How callers invoke this
|
|
21
|
+
|
|
22
|
+
- **Skill-capable contexts** (a lead session with the `Skill` tool): `Skill({skill: "reviewer-gates", args: "--skill <caller> <gate> [gate parameters]"})`.
|
|
23
|
+
- **Fallback** (a subagent or teammate without the `Skill` tool): the caller's spawn prompt says "Read `~/.claude/skills/reviewer-gates/SKILL.md` and apply the `<gate>` section with the parameters below."
|
|
24
|
+
|
|
25
|
+
Every invocation carries the caller's identity (`--skill <caller>`, e.g. `pr-converge`, `qbug`). The refusal line in Gate 1 and every logged decision names the caller, so a multi-skill session's transcript shows which loop each gate served.
|
|
26
|
+
|
|
27
|
+
## Gate 1: Reviewer opt-out (`CLAUDE_REVIEWS_DISABLED`)
|
|
28
|
+
|
|
29
|
+
The `CLAUDE_REVIEWS_DISABLED` environment variable is a comma-separated token list (case-insensitive, whitespace-tolerant). Three tokens exist:
|
|
30
|
+
|
|
31
|
+
| Token | Disables |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `bugteam` | The whole bug-audit family: `/bugteam`, `/qbug`, `/findbugs`, and audit dispatch in `/monitor-open-prs` |
|
|
34
|
+
| `bugbot` | Cursor Bugbot triggering and polling |
|
|
35
|
+
| `copilot` | GitHub Copilot review requests and polling |
|
|
36
|
+
|
|
37
|
+
Run the shared parser — never an inline shell parse:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer <bugbot|bugteam|copilot>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **Exit 0** — the named reviewer is opted out. A skill whose whole run depends on that reviewer responds with its refusal line and stops. The template: `/<caller> is disabled via CLAUDE_REVIEWS_DISABLED.` A loop that merely includes the reviewer as one gate marks the reviewer down (`bugbot_down = true`, `copilot_down = true`) and continues on its remaining signals.
|
|
44
|
+
- **Exit 1** — the reviewer is available; continue.
|
|
45
|
+
|
|
46
|
+
## Gate 2: Copilot quota pre-check (once per run)
|
|
47
|
+
|
|
48
|
+
At run start — before any Copilot request, poll, or agent spawn — run:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python "$HOME/.claude/_shared/pr-loop/scripts/copilot_quota.py"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
It resolves the configured GitHub account, reads the remaining Copilot premium-request quota via `gh api copilot_internal/user`, and prints one line. Log that line.
|
|
55
|
+
|
|
56
|
+
- **Exit 0** — Copilot has quota. Leave `copilot_down` false (or pass `copilotDisabled: false` to a workflow).
|
|
57
|
+
- **Any non-zero exit** — skip Copilot for the whole run: the account is out of quota, the quota API or account access is down, or no account is set. Set `copilot_down = true` (or `copilotDisabled: true`). The no-account line names the exact `.env` path and key to set; the account comes from the `COPILOT_QUOTA_ACCOUNT` environment variable or a git-ignored `.env` file.
|
|
58
|
+
|
|
59
|
+
Run the pre-check once per run, not per tick or per round. Every later tick reads the stored flag. While `copilot_down` is true:
|
|
60
|
+
|
|
61
|
+
- Skip every Copilot fetch, request, poll, and agent spawn outright.
|
|
62
|
+
- Export `CLAUDE_REVIEWS_DISABLED="copilot"` in the shell of any convergence check (`check_convergence.py`), so the check bypasses its Copilot review gate and pending-requested-reviews gate and the run still marks ready on the remaining signals.
|
|
63
|
+
|
|
64
|
+
`reviewer_availability.py` (same directory) is the single entry point when a caller wants one command answering "may reviewer X be engaged?" — it composes the opt-out parse and, for Copilot, the quota check: exit 0 to engage, non-zero to skip.
|
|
65
|
+
|
|
66
|
+
## Gate 3: Bugbot trigger, acknowledge, and CI-detect
|
|
67
|
+
|
|
68
|
+
Cursor Bugbot signals through CI check runs, not always through a posted review. The decision tree runs against `<current_head>` with `check_bugbot_ci.py` (installed at `$HOME/.claude/skills/pr-converge/scripts/check_bugbot_ci.py`; `--help` documents every mode):
|
|
69
|
+
|
|
70
|
+
1. **Silent-pass pre-check (always first).**
|
|
71
|
+
`python "$HOME/.claude/skills/pr-converge/scripts/check_bugbot_ci.py" --check-clean --owner <O> --repo <R> --sha <current_head>`
|
|
72
|
+
- Exit 0 — Bugbot CI completed with a `success`/`neutral` conclusion and posted no review: a silent pass. Record `bugbot_clean_at = <current_head>` and stop; do not trigger.
|
|
73
|
+
- Exit 1 (not a silent pass) or exit 2 (gh CLI error, silent pass not confirmable) — continue.
|
|
74
|
+
2. **Already-queued check.**
|
|
75
|
+
`... check_bugbot_ci.py --check-active --owner <O> --repo <R> --sha <current_head>`
|
|
76
|
+
- Exit 0 — Bugbot is already queued on this commit. Skip posting; wait for completion (callers schedule their own wakeup).
|
|
77
|
+
- Exit 1 — continue.
|
|
78
|
+
3. **Trigger.** Post exactly `bugbot run` as an issue comment (`add_issue_comment`) — no `@cursor[bot]` mention, no other text. `bugbot run` is empirically the only re-trigger Cursor Bugbot recognizes; every other phrasing silently no-ops. Wait 8 seconds with an in-turn Monitor delay, never a foreground `sleep` (blocked in headless runs).
|
|
79
|
+
4. **Acknowledge check.**
|
|
80
|
+
`... check_bugbot_ci.py --owner <O> --repo <R> --sha <current_head>`
|
|
81
|
+
- Exit 0 — a check run is present: record `bugbot_acknowledged_at = <now, ISO 8601>`; the caller polls on its own cadence.
|
|
82
|
+
- Exit non-zero — Bugbot is down: set `bugbot_down = true` and route past the Bugbot phase; the run continues on its remaining signals.
|
|
83
|
+
|
|
84
|
+
The silent-pass pre-check runs first so a bot that already finished cleanly is never re-prompted — Bugbot refuses to re-run on an evaluated commit, and without the pre-check the acknowledge step would falsely mark `bugbot_down = true`.
|
|
85
|
+
|
|
86
|
+
**Flag reset rule:** `bugbot_down` resets to false whenever `<current_head>` changes — a new HEAD invalidates the old down-detection. `copilot_down` never resets mid-run; it holds until the run ends.
|
|
87
|
+
|
|
88
|
+
## Gotchas
|
|
89
|
+
|
|
90
|
+
- **`bugbot run` is load-bearing text.** Alternative phrasings (`@cursor run`, `cursor review`, `bugbot please`) return no error and do nothing.
|
|
91
|
+
- **A skipped gate is a decision, not an omission.** When `copilot_down` or `bugbot_down` short-circuits a phase, record the flag and the exit line that set it — a convergence report that cannot show why a reviewer was skipped is incomplete.
|
|
92
|
+
- **The opt-out gate re-runs at every reviewer entry point;** the quota pre-check runs once per run. Confusing the two either re-spends quota-API calls per tick or misses a mid-run opt-out.
|
|
93
|
+
|
|
94
|
+
## Folder map
|
|
95
|
+
|
|
96
|
+
- `SKILL.md` — this file; the skill ships no scripts of its own. Gate scripts live in `_shared/pr-loop/scripts/` (`reviews_disabled.py`, `copilot_quota.py`, `reviewer_availability.py`) and `pr-converge/scripts/` (`check_bugbot_ci.py`).
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# session-log
|
|
2
2
|
|
|
3
|
-
Logs a session report as a
|
|
3
|
+
Logs a session report as a self-contained HTML page in the Obsidian vault, publishes it with the `Artifact` tool, extracts unrecorded decisions, tidies the project session folder, and outputs a `/rename` command.
|
|
4
4
|
|
|
5
5
|
**Trigger:** `/session-log`, "journal this session", "log this work", "session report", "save session", "capture session", "document what we did".
|
|
6
6
|
|
|
7
7
|
## Purpose
|
|
8
8
|
|
|
9
|
-
Produces a self-contained HTML session report shaped to the session's character (feature build, incident, research, etc.) rather than a fixed template. The skill owns the vault path, session numbering, frontmatter contract, decision extraction, and folder hygiene
|
|
9
|
+
Produces a self-contained HTML session report shaped to the session's character (feature build, incident, research, etc.) rather than a fixed template. The skill owns the vault path, session numbering, frontmatter contract, HTML composition and publishing, decision extraction, and folder hygiene.
|
|
10
10
|
|
|
11
11
|
## Key files
|
|
12
12
|
|
|
@@ -18,14 +18,14 @@ Produces a self-contained HTML session report shaped to the session's character
|
|
|
18
18
|
|
|
19
19
|
1. **Backend detection** — headless vault (`ob --version` + `OBSIDIAN_VAULT_PATH`) then local vault (`~/.claude/vault/`). Session number from `[N]. *.html` and `[N]. *.md` files in the project folder.
|
|
20
20
|
2. **Session metadata** — project name, session number, session ID from `CLAUDE_CODE_SESSION_ID`, date, title.
|
|
21
|
-
3. **
|
|
22
|
-
4. **Vault context tracking** — two Edit calls set `vault_context_retrieved` and append a vault-context line
|
|
21
|
+
3. **Compose and publish via the Artifact tool** — loads the `artifact-design` skill first, designs the shape for the session's character (e.g., a PR-writeup shape for feature builds, a timeline shape for incidents), writes the HTML, then publishes it with the `Artifact` tool using the fixed favicon `📓`.
|
|
22
|
+
4. **Vault context tracking** — two Edit calls set `vault_context_retrieved` and append a vault-context line, then redeploy via `Artifact` on the same `file_path` so the URL stays the same.
|
|
23
23
|
5. **Decision extraction** — scans conversation for unrecorded decisions; prompts user via `AskUserQuestion` before invoking `/remember`.
|
|
24
|
-
6. **Session tidy** — audits `.html` files in the project folder for naming and frontmatter; auto-fixes minor issues
|
|
24
|
+
6. **Session tidy** — audits `.html` files in the project folder for naming and frontmatter; auto-fixes minor issues and redeploys via `Artifact`.
|
|
25
25
|
|
|
26
26
|
## Conventions
|
|
27
27
|
|
|
28
|
-
-
|
|
29
|
-
- Session reports use HTML; `.md` paths are blocked by `md_to_html_blocker` for session paths.
|
|
28
|
+
- Session reports use HTML — the Artifact tool publishes HTML or Markdown, and HTML gives the report designer more visual structure.
|
|
30
29
|
- `write_existing_file_blocker` rejects Write on existing paths — use Edit for all vault-context updates.
|
|
30
|
+
- The `Artifact` tool redeploys to the same URL on repeat calls with the same `file_path` within the current run — edits made in steps 3 and 5 to the session created this run never mint a new URL.
|
|
31
31
|
- Final step copies `/rename [Project] - [Primary Outcome]` to the clipboard via `pwsh Set-Clipboard`.
|
|
@@ -1,44 +1,30 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: session-log
|
|
3
3
|
description: >-
|
|
4
|
-
Log a session report by
|
|
4
|
+
Log a session report by composing a self-contained HTML page and publishing it with the Artifact tool, then track vault context, extract unrecorded decisions, tidy the project's session folder, and output a /rename command. Use when the user says /session-log, journal this session, log this work, session report, or any variation of "summarize/log/record this session". Also triggers on "save session", "capture session", or "document what we did".
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Session Log
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Session-log composes the HTML report and publishes it directly with the `Artifact` tool. The skill owns the whole flow: where the file lives in the vault, what number it gets, the frontmatter metadata contract, HTML composition and publishing, post-write vault tracking, decision extraction, project-folder hygiene, and the closing `/rename` hand-off.
|
|
12
12
|
|
|
13
13
|
**Announce at start:** "I'm logging this session."
|
|
14
14
|
|
|
15
|
-
## Why this
|
|
15
|
+
## Why this report is designed fresh per session
|
|
16
16
|
|
|
17
|
-
Sessions come in many shapes — convergence loops, feature builds, research dives, incidents, refactors, decisions. A single h2-emoji-list template forces every session into the same form regardless of fit, and the artifact reads as a process log rather than a substance log.
|
|
18
|
-
|
|
19
|
-
The gallery lives at `~/.claude/skills/doc-gist/references/examples/`. Patterns that usually fit session reports:
|
|
20
|
-
|
|
21
|
-
| Session character | Gallery shape to study |
|
|
22
|
-
|---|---|
|
|
23
|
-
| Feature build / PR ships | `17-pr-writeup.html` |
|
|
24
|
-
| Incident, debugging arc, convergence loop | `12-incident-report.html` |
|
|
25
|
-
| Status update / weekly progress | `11-status-report.html` |
|
|
26
|
-
| Implementation plan or decision record | `16-implementation-plan.html` |
|
|
27
|
-
| Exploration of multiple approaches | `01-exploration-code-approaches.html` |
|
|
28
|
-
| Code-explainer with module map | `04-code-understanding.html` |
|
|
29
|
-
|
|
30
|
-
The session designer reads the matching gallery file, then designs the report in that shape. **Adapt, do not copy.**
|
|
17
|
+
Sessions come in many shapes — convergence loops, feature builds, research dives, incidents, refactors, decisions. A single h2-emoji-list template forces every session into the same form regardless of fit, and the artifact reads as a process log rather than a substance log. Load the `artifact-design` skill before composing any page content — it calibrates the design investment and shape to the session's character: a feature build reads naturally as a PR writeup, an incident or convergence loop as a timeline, a status update as a progress summary, a plan or decision as a decision record, an exploration as a multi-approach walkthrough.
|
|
31
18
|
|
|
32
19
|
## Gotchas
|
|
33
20
|
|
|
34
|
-
- **
|
|
35
|
-
-
|
|
36
|
-
- **
|
|
21
|
+
- **Load the `artifact-design` skill before writing page content.** The `Artifact` tool needs this step first — it is not optional polish.
|
|
22
|
+
- **The `Artifact` tool wraps the file in a document skeleton at publish time.** It adds `<!doctype html>…<head>…</head><body>` around whatever the file holds — write page content only (a `<title>`, a `<style>` block, and the body markup). Do not include `<!DOCTYPE>`, `<html>`, `<head>`, or `<body>` tags in the file itself.
|
|
23
|
+
- **The `Artifact` tool redeploys to the same URL only within the current run.** Editing the session's HTML file in a later step of this same skill run and calling `Artifact` again does not mint a new URL — it updates the same published page in place. A fresh session has no memory of an artifact's URL from an earlier run, so republishing a session report written in a prior session always mints a new URL (there is no other way to target the old one without the user supplying it).
|
|
24
|
+
- **Vault paths sit outside `.claude/`.** Headless vault paths (e.g., `$OBSIDIAN_VAULT_PATH`) resolve outside the project tree. Session reports use HTML regardless of vault location — the Artifact tool needs a written file to publish.
|
|
37
25
|
- **Sessions describe current state by convention.** The state_description_blocker hook does not scan .html, but the rule at `~/.claude/rules/no-historical-clutter.md` applies as a writing standard — skip historical and comparative language when composing the report; the rule file lists the full trigger set.
|
|
38
26
|
- **`write_existing_file_blocker` rejects Write on existing paths.** Use Write only when creating a fresh session report; use Edit for the vault-context append in step 3.
|
|
39
|
-
- **Each Write/Edit of the marked HTML creates a fresh gist with a new ID.** `gist_upload.py` calls `gh gist create` with no lookup of any prior gist. Step 3 performs two Edits and Step 5's tidy may Edit the current session a third time — each Edit produces a different gist URL than its predecessor. Quote the URLs from the FINAL publish (the most recent auto-publish run for the session being created — the second Step-3 Edit when Step 5 does not touch the current session, or the Step 5 Edit when it does) to the user; never embed a URL inside the HTML that a later Edit then re-publishes.
|
|
40
27
|
- **Obsidian frontmatter index is HTML-blind.** Obsidian's native YAML-frontmatter parser reads only `.md` files. HTML files do not appear in Obsidian's frontmatter index. Search by content still works; search by `type: session-report` does not.
|
|
41
|
-
- **Auto-published gists carry the default `gist_upload.py` description (`HTML artifact`), not a session-specific title.** The auto-publish hook invokes `gist_upload.py` with only `--input` and `--no-open` — it has no session-title context to pass as `--description`. Browsing or sharing gists, operators see "HTML artifact" rather than `Session [N] — [Title] — session-log — [Project]`. Workaround: after the canonical Edit completes, edit the existing gist's description in place with `gh gist edit <gist-id> --desc "Session [N] — [Title] — session-log — [Project]"` (this updates the existing gist's metadata; no new gist ID is created) if a meaningful title matters for that share. The HTML frontmatter inside the file remains the authoritative session metadata regardless of the gist's external description.
|
|
42
28
|
|
|
43
29
|
## Backend Detection (run before Step 1)
|
|
44
30
|
|
|
@@ -87,27 +73,25 @@ tags: [session, [project-tag], [topic-tags]]
|
|
|
87
73
|
|
|
88
74
|
Every session report carries this metadata block verbatim so vault search and the tidy step in step 5 work. **Initial values for Step 2's Write:** substitute concrete values for every placeholder — for `session_id`, write the value read from `CLAUDE_CODE_SESSION_ID` in step 1 (or `unknown` when the variable is unset); for `vault_context_retrieved`, write the literal value `false` (the safe default before Step 3's vault-MCP-tool scan completes). Step 3 then Edits `vault_context_retrieved` to `true` if any of the three vault MCP tools fired this session.
|
|
89
75
|
|
|
90
|
-
## Step 2: Compose the HTML via
|
|
76
|
+
## Step 2: Compose and Publish the HTML via the Artifact Tool
|
|
91
77
|
|
|
92
|
-
Design the artifact for **this session's character
|
|
78
|
+
Load the `artifact-design` skill before writing any content. Design the artifact for **this session's character** — a feature build reads naturally as a PR writeup, an incident or convergence loop as a timeline, a status update as a progress summary, a plan or decision as a decision record, an exploration as a multi-approach walkthrough. The report must answer for a cold reader, from the section headers alone, three questions: *what shipped*, *why it matters*, *what impact it had*. Process narration (commit-by-commit walks, agent gotchas, retry counts) belongs at the end, not in the opening sections.
|
|
93
79
|
|
|
94
|
-
**Required
|
|
80
|
+
**Required as the first content line:** the frontmatter HTML comment from step 1.
|
|
95
81
|
|
|
96
|
-
|
|
97
|
-
<!-- @publish-as-gist -->
|
|
98
|
-
```
|
|
82
|
+
**Required somewhere in the content:** a `<title>` element naming the session — it names the browser tab and the artifact gallery entry.
|
|
99
83
|
|
|
100
|
-
|
|
84
|
+
**Required as the first content section (after the frontmatter comment):** an opening "What this session shipped" paragraph + bullets — written so a reader with zero prior context understands the outcome. For continuation sessions (where the substantive work landed in a prior session), recap the parent session's outcome briefly so the report stands alone.
|
|
101
85
|
|
|
102
|
-
**Required
|
|
86
|
+
**Required: self-contained, responsive, theme-aware HTML.** Inline all CSS in a `<style>` block and all JS inline; embed any images as data URIs — the `Artifact` tool's content security policy blocks external CDN scripts, stylesheets, fonts, and network requests. Use relative units so the layout holds at any width, and support both light and dark via `prefers-color-scheme` (or `:root[data-theme]` overrides).
|
|
103
87
|
|
|
104
|
-
**
|
|
88
|
+
**No document wrapper tags.** The `Artifact` tool wraps the file content in a `<!doctype html>…<head>…</head><body>` skeleton at publish time — write the `<title>`, `<style>`, and body markup directly, with no `<!DOCTYPE>`, `<html>`, `<head>`, or `<body>` tags of your own.
|
|
105
89
|
|
|
106
|
-
|
|
90
|
+
Beyond those requirements, design the shape that fits the session — the `artifact-design` skill's guidance covers typography, palette, and layout choices.
|
|
107
91
|
|
|
108
|
-
|
|
92
|
+
**Write the file** via the Write tool to the vault path. Create the project directory via `mkdir -p` if it does not exist.
|
|
109
93
|
|
|
110
|
-
**
|
|
94
|
+
**Publish the file** by calling the `Artifact` tool with `file_path` set to the vault path just written, `favicon` set to the fixed session-log favicon `📓` — this favicon stays the same across every session-log report so the series reads as one consistent collection; never swap it per session — and `description` set to a one-sentence subtitle summarizing the session. Capture the returned URL: it is the canonical URL for this session report, and it stays the same across every later `Artifact` call on this same `file_path` within the current run (steps 3 and 5 redeploy to it rather than minting a new one).
|
|
111
95
|
|
|
112
96
|
**If the Write fails**, output the HTML content in the conversation so the user can copy it manually. Before emitting the HTML to chat, resolve the `vault_context_retrieved` placeholder to `true` or `false` based on the same vault-MCP-tool scan that Step 3 would have run, and include the matching vault-context `<li>` line (Retrieved or Not retrieved) so the emitted HTML is a valid copy-paste artifact with complete frontmatter. Skip Step 3 and continue at step 4.
|
|
113
97
|
|
|
@@ -121,10 +105,10 @@ Review the conversation history for any use of these vault MCP tools (look only
|
|
|
121
105
|
- `mcp__obsidian__read_note`
|
|
122
106
|
- `mcp__obsidian__read_multiple_notes`
|
|
123
107
|
|
|
124
|
-
Edit the vault HTML via two Edit calls
|
|
108
|
+
Edit the vault HTML via two Edit calls:
|
|
125
109
|
|
|
126
110
|
1. Set the frontmatter `vault_context_retrieved` field to `true` when any of the three tools fired this session, `false` otherwise.
|
|
127
|
-
2. Append one fact — vault-context status — into whatever section the report designer placed for notes / metadata / references. If the report has no such section, append a fresh `<h2>Notes</h2>` block
|
|
111
|
+
2. Append one fact — vault-context status — into whatever section the report designer placed for notes / metadata / references. If the report has no such section, append a fresh `<h2>Notes</h2>` block at the end of the content:
|
|
128
112
|
|
|
129
113
|
```html
|
|
130
114
|
<h2>Notes</h2>
|
|
@@ -137,7 +121,7 @@ Edit the vault HTML via two Edit calls (each Edit re-fires the auto-publish hook
|
|
|
137
121
|
|
|
138
122
|
If the report already has a notes / references section, use Edit to insert one matching child element at the end of that section. The element shape mirrors whatever the section already uses: an extra `<li>` before the closing `</ul>` for a list, an extra `<dt>Vault context</dt><dd>…</dd>` pair before the closing `</dl>` for a description list, an extra `<p><strong>Vault context:</strong> …</p>` before the section's closing tag for a paragraph-based section. Pick the form that matches the surrounding markup.
|
|
139
123
|
|
|
140
|
-
|
|
124
|
+
After both Edits land, call the `Artifact` tool again with the same `file_path` and the same `favicon` used in step 2 to redeploy the updated content. This updates the URL captured in step 2 in place; no new URL is minted.
|
|
141
125
|
|
|
142
126
|
## Step 4: Decision Extraction
|
|
143
127
|
|
|
@@ -160,7 +144,7 @@ Scope: the current project's session folder only.
|
|
|
160
144
|
- Missing frontmatter fields that can be inferred (e.g., `blocked: false` when status is `completed`; `vault_context_retrieved: false` when the field is absent, since the field defaults to false in pre-existing sessions)
|
|
161
145
|
- `type` field set to a wrong value (correct to `session-report`)
|
|
162
146
|
|
|
163
|
-
|
|
147
|
+
When the Edit touches the session report created in this run, call `Artifact` again with the same `file_path` and `favicon` from step 2 to redeploy — the URL captured in step 2 stays unchanged. When the Edit touches an older session report published in a prior run, call `Artifact` on that `file_path` with no `url` argument, since this skill keeps no record of that file's earlier URL — this publishes the older report at a new URL. Surface a `Session [N] republished at a new URL: <url>` line so the user can update any prior shares.
|
|
164
148
|
4. **Report issues that need user input:**
|
|
165
149
|
- Files with wrong naming convention (propose new name)
|
|
166
150
|
- Stale statuses (propose update to `completed` or ask)
|
|
@@ -190,14 +174,13 @@ The primary outcome comes from the session title resolved in step 1.
|
|
|
190
174
|
|
|
191
175
|
- [ ] Backend detected and announced
|
|
192
176
|
- [ ] Session number resolved from `[N]. *.html` and `[N]. *.md` files (both parsed to preserve sequence across the format migration)
|
|
193
|
-
- [ ]
|
|
194
|
-
- [ ]
|
|
195
|
-
- [ ] Frontmatter HTML comment present
|
|
177
|
+
- [ ] `artifact-design` skill loaded before composing page content
|
|
178
|
+
- [ ] HTML composed for this session's character (no document wrapper tags; self-contained, responsive, theme-aware)
|
|
179
|
+
- [ ] Frontmatter HTML comment present as the first content line
|
|
196
180
|
- [ ] `session_id` frontmatter field set from `CLAUDE_CODE_SESSION_ID` (the authoring agent's own session), or `unknown` when the variable is unset
|
|
197
181
|
- [ ] Opening section answers "what shipped / why / impact" for a cold reader
|
|
198
|
-
- [ ]
|
|
199
|
-
- [ ]
|
|
200
|
-
- [ ] Vault-context line appended via Edit (step 3); URL pair from the most recent auto-publish run for the current session quoted to the user (typically the final Step-3 Edit, but the Step 5 republish takes over when Step 5 edits the current session)
|
|
182
|
+
- [ ] Published via the `Artifact` tool with the fixed favicon `📓`; URL captured (or HTML emitted to chat when step 2 Write failed)
|
|
183
|
+
- [ ] Vault-context line appended via Edit (step 3); `Artifact` redeployed on the same URL
|
|
201
184
|
- [ ] Decision extraction surfaced any unrecorded items
|
|
202
185
|
- [ ] Session tidy reported anomalies or stayed silent
|
|
203
186
|
- [ ] `/rename` command copied to clipboard via `pwsh Set-Clipboard`
|