capt-hook 3.4.0__tar.gz → 3.5.0__tar.gz
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.
- {capt_hook-3.4.0 → capt_hook-3.5.0}/PKG-INFO +2 -2
- {capt_hook-3.4.0 → capt_hook-3.5.0}/README.md +1 -1
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/cli.py +23 -39
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/cli.py +3 -3
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/pipeline.py +11 -2
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/SKILL.md +1 -1
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/pattern-catalog.md +1 -1
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/bootstrapping-hooks/SKILL.md +2 -2
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/scanning-sessions/SKILL.md +3 -3
- {capt_hook-3.4.0 → capt_hook-3.5.0}/pyproject.toml +1 -1
- {capt_hook-3.4.0 → capt_hook-3.5.0}/LICENSE +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/.claude-plugin/plugin.json +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/__main__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/app.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/classifiers/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/classifiers/conductor.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/classifiers/droid.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/classifiers/native.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/command.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/conditions.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/context.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/decisions.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/dispatch.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/events.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/file.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/llm/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/loader.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/log.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/capt-hook.toml +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/commands.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/docs.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/plans.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/prompts.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/review.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/stewardship.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/general/tasks.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/manager.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/python/capt-hook.toml +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/python/style.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/python/testing.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/packs/python/toolchain.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/commands.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/lint.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/llm.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/nudge.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/primitives/workflow.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/prompt.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/py.typed +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/dashboard.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/fix.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/formats.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/judge.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/repo.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/scan.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/settings.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/store.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/review/sync.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/session.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/settings.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/signals/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/signals/nlp.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/capt-hook-api.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/pitfalls.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/testing-hooks.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/scanning-sessions/references/pr-workflow.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/scanning-sessions/references/review-cli.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/translating-styleguides/SKILL.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/translating-styleguides/references/llm-rule-patterns.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/translating-styleguides/references/matcher-reference.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/translating-styleguides/references/tier-rubric.md +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/state.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/style/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/style/matchers.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/style/scope.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/style/types.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/tasks.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/templates/example_hook.py.tmpl +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/testing/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/testing/helpers.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/testing/session_cache.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/testing/types.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/tests/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/tests/helpers.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/types.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/util/__init__.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/util/model_cache.py +0 -0
- {capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capt-hook
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Declarative hook framework for Claude Code
|
|
5
5
|
Keywords: claude,claude-code,hooks,llm,agents,guardrails,cli
|
|
6
6
|
Author: Yasyf Mohamedali
|
|
@@ -66,7 +66,7 @@ captain-hook needs no install — it runs through [uvx](https://docs.astral.sh/u
|
|
|
66
66
|
uvx capt-hook init
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
`init` scaffolds `.claude/hooks/`, wires Claude Code's settings,
|
|
69
|
+
`init` scaffolds `.claude/hooks/`, wires Claude Code's settings, registers the captain-hook plugin so its skills install on workspace-trust, and arms the [session reviewer](#it-learns-from-your-corrections). Or do it all from a session. Run `/plugin marketplace add yasyf/captain-hook`, then ask Claude to "set up captain hook".
|
|
70
70
|
|
|
71
71
|
## Your first hook
|
|
72
72
|
|
|
@@ -19,7 +19,7 @@ captain-hook needs no install — it runs through [uvx](https://docs.astral.sh/u
|
|
|
19
19
|
uvx capt-hook init
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
`init` scaffolds `.claude/hooks/`, wires Claude Code's settings,
|
|
22
|
+
`init` scaffolds `.claude/hooks/`, wires Claude Code's settings, registers the captain-hook plugin so its skills install on workspace-trust, and arms the [session reviewer](#it-learns-from-your-corrections). Or do it all from a session. Run `/plugin marketplace add yasyf/captain-hook`, then ask Claude to "set up captain hook".
|
|
23
23
|
|
|
24
24
|
## Your first hook
|
|
25
25
|
|
|
@@ -54,40 +54,24 @@ def example_hook_source() -> str:
|
|
|
54
54
|
return (importlib.resources.files("captain_hook") / "templates" / "example_hook.py.tmpl").read_text()
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def
|
|
58
|
-
"""
|
|
57
|
+
def plugin_dir() -> Path:
|
|
58
|
+
"""Filesystem path to the bundled captain-hook plugin root.
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
force: Replace existing skill directories wholesale instead of skipping them.
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
Per-skill status of ``"installed"``, ``"replaced"``, or ``"skipped"``.
|
|
60
|
+
Holds ``.claude-plugin/plugin.json`` and ``skills/``, so ``claude --plugin-dir``
|
|
61
|
+
can load the skills in-place from the installed wheel without a marketplace clone.
|
|
66
62
|
"""
|
|
67
|
-
|
|
68
|
-
summary: dict[str, str] = {}
|
|
69
|
-
with importlib.resources.as_file(importlib.resources.files("captain_hook") / "skills") as src_root:
|
|
70
|
-
for skill in sorted(p for p in src_root.iterdir() if p.is_dir()):
|
|
71
|
-
dest = dest_root / skill.name
|
|
72
|
-
if dest.exists() and not force:
|
|
73
|
-
summary[skill.name] = "skipped"
|
|
74
|
-
continue
|
|
75
|
-
if dest.exists():
|
|
76
|
-
shutil.rmtree(dest)
|
|
77
|
-
summary[skill.name] = "replaced"
|
|
78
|
-
else:
|
|
79
|
-
summary[skill.name] = "installed"
|
|
80
|
-
shutil.copytree(skill, dest)
|
|
81
|
-
return summary
|
|
63
|
+
return Path(str(importlib.resources.files("captain_hook")))
|
|
82
64
|
|
|
83
65
|
|
|
84
66
|
def register_marketplace(root: Path) -> None:
|
|
85
|
-
"""Enable the captain-hook plugin marketplace in ``root/.claude/settings.
|
|
67
|
+
"""Enable the captain-hook plugin marketplace in ``root/.claude/settings.json``.
|
|
86
68
|
|
|
87
69
|
Merges ``extraKnownMarketplaces`` and ``enabledPlugins`` entries into the
|
|
88
|
-
|
|
70
|
+
committed settings so the skills load from the plugin (tracking the repository)
|
|
71
|
+
instead of being copied into ``.claude/skills``. Claude Code prompts to install
|
|
72
|
+
the plugin when the project folder is trusted.
|
|
89
73
|
"""
|
|
90
|
-
settings_path = root / ".claude" / "settings.
|
|
74
|
+
settings_path = root / ".claude" / "settings.json"
|
|
91
75
|
existing = json.loads(settings_path.read_text()) if settings_path.exists() else {}
|
|
92
76
|
write_settings(
|
|
93
77
|
settings_path,
|
|
@@ -104,7 +88,9 @@ def maybe_launch_bootstrap(root: Path) -> bool:
|
|
|
104
88
|
|
|
105
89
|
Only fires in an interactive session with the ``claude`` CLI on PATH; CI and
|
|
106
90
|
scripted runs skip the prompt entirely. On acceptance, the captain-hook plugin
|
|
107
|
-
marketplace is registered in ``.claude/settings.
|
|
91
|
+
marketplace is registered in ``.claude/settings.json``, and Claude is launched
|
|
92
|
+
with the bundled plugin loaded via ``--plugin-dir`` so the namespaced skill
|
|
93
|
+
resolves immediately without waiting on a marketplace install.
|
|
108
94
|
|
|
109
95
|
Returns:
|
|
110
96
|
Whether Claude was launched.
|
|
@@ -114,7 +100,9 @@ def maybe_launch_bootstrap(root: Path) -> bool:
|
|
|
114
100
|
if not click.confirm("Bootstrap hooks now? (launches Claude with the bootstrapping-hooks skill)", default=True):
|
|
115
101
|
return False
|
|
116
102
|
register_marketplace(root)
|
|
117
|
-
subprocess.run(
|
|
103
|
+
subprocess.run(
|
|
104
|
+
["claude", "--plugin-dir", str(plugin_dir()), "/captain-hook:bootstrapping-hooks"], cwd=root, check=False
|
|
105
|
+
)
|
|
118
106
|
return True
|
|
119
107
|
|
|
120
108
|
|
|
@@ -326,17 +314,14 @@ def init_project(root: Path, *, review: bool = True) -> None:
|
|
|
326
314
|
merged, summary = merge_settings(".claude/hooks", settings_path)
|
|
327
315
|
write_settings(settings_path, merged)
|
|
328
316
|
|
|
329
|
-
|
|
317
|
+
register_marketplace(root)
|
|
330
318
|
|
|
331
319
|
click.echo(f"Scaffolded {example.relative_to(root)} + {settings_path.relative_to(root)}.")
|
|
332
320
|
click.echo()
|
|
333
321
|
print_hook_summary(str(settings_path.relative_to(root)), summary)
|
|
334
322
|
click.echo()
|
|
335
|
-
click.echo("
|
|
336
|
-
|
|
337
|
-
click.echo(f" + installed {name}")
|
|
338
|
-
if skipped := [n for n, status in skills_summary.items() if status == "skipped"]:
|
|
339
|
-
click.echo(f" unchanged: {', '.join(skipped)} (already present; capt-hook skills install --force to refresh)")
|
|
323
|
+
click.echo("Claude Code plugin:")
|
|
324
|
+
click.echo(f" + registered {PLUGIN_ID} in .claude/settings.json (skills install on folder-trust)")
|
|
340
325
|
click.echo()
|
|
341
326
|
match (review, repo_key(root)):
|
|
342
327
|
case (False, _):
|
|
@@ -545,12 +530,11 @@ def skills() -> None:
|
|
|
545
530
|
|
|
546
531
|
|
|
547
532
|
@skills.command(name="install")
|
|
548
|
-
@click.option("--force", is_flag=True, default=False, help="Replace skills that already exist in .claude/skills")
|
|
549
533
|
@click.pass_obj
|
|
550
|
-
def skills_install(state: CliState
|
|
551
|
-
"""
|
|
552
|
-
|
|
553
|
-
|
|
534
|
+
def skills_install(state: CliState) -> None:
|
|
535
|
+
"""Register the captain-hook plugin in .claude/settings.json (skills load from the plugin, not copied files)."""
|
|
536
|
+
register_marketplace(state.root)
|
|
537
|
+
click.echo(f" registered {PLUGIN_ID} in .claude/settings.json")
|
|
554
538
|
|
|
555
539
|
|
|
556
540
|
@cli.group()
|
|
@@ -120,12 +120,12 @@ def spawn(transcript: Path, cwd: str | None) -> None:
|
|
|
120
120
|
@review.command()
|
|
121
121
|
@click.pass_obj
|
|
122
122
|
def enable(state: CliState) -> None:
|
|
123
|
-
"""Watch the current repo,
|
|
124
|
-
from captain_hook.cli import
|
|
123
|
+
"""Watch the current repo, register the captain-hook plugin, and wire the SessionEnd hook."""
|
|
124
|
+
from captain_hook.cli import register_marketplace
|
|
125
125
|
|
|
126
126
|
repo = current_repo(state.root)
|
|
127
127
|
watch_repo(repo)
|
|
128
|
-
|
|
128
|
+
register_marketplace(state.root)
|
|
129
129
|
wired = ensure_review_wiring(state.root / ".claude" / "settings.local.json")
|
|
130
130
|
click.echo(f"watching {repo}" + (" (SessionEnd hook wired into .claude/settings.local.json)" if wired else ""))
|
|
131
131
|
|
|
@@ -134,7 +134,7 @@ def brain_prompt(transcript: Path) -> str:
|
|
|
134
134
|
from captain_hook.review.scan import REVIEWER_MARKER
|
|
135
135
|
|
|
136
136
|
return (
|
|
137
|
-
f"/scanning-sessions --transcript {transcript}\n\n"
|
|
137
|
+
f"/captain-hook:scanning-sessions --transcript {transcript}\n\n"
|
|
138
138
|
f"[{REVIEWER_MARKER}] Review this repo's eligible candidates and open at most one pull request per"
|
|
139
139
|
" candidate. Work in one continuous run: do not stop to summarize after drafting — you are done only"
|
|
140
140
|
" when every eligible candidate has a PR recorded via `review update <id> pr_open --pr-url <url>` or"
|
|
@@ -143,13 +143,22 @@ def brain_prompt(transcript: Path) -> str:
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
def brain_argv(*, max_turns: int, max_budget_usd: float) -> list[str]:
|
|
146
|
+
from captain_hook.cli import plugin_dir
|
|
146
147
|
from captain_hook.llm import ClaudeBackend
|
|
147
148
|
|
|
148
149
|
backend = ClaudeBackend()
|
|
149
150
|
argv = backend.build_command(backend.models[BRAIN_TIER], None, agent=True)
|
|
150
151
|
argv[argv.index("--permission-mode") + 1] = "acceptEdits"
|
|
151
152
|
argv[argv.index("--max-budget-usd") + 1] = str(max_budget_usd)
|
|
152
|
-
return [
|
|
153
|
+
return [
|
|
154
|
+
*argv,
|
|
155
|
+
"--plugin-dir",
|
|
156
|
+
str(plugin_dir()),
|
|
157
|
+
"--max-turns",
|
|
158
|
+
str(max_turns),
|
|
159
|
+
"--allowedTools",
|
|
160
|
+
",".join(BRAIN_ALLOWED_TOOLS),
|
|
161
|
+
]
|
|
153
162
|
|
|
154
163
|
|
|
155
164
|
def spawn_brain(transcript: Path, *, repo_root: Path, settings: ReviewSettings) -> None:
|
|
@@ -70,7 +70,7 @@ has the full decision rules and defaults:
|
|
|
70
70
|
| A done-criterion to check once at stop ("run tests before stopping") | `gate(only_if=[...], skip_if=[RanCommand(...)])` |
|
|
71
71
|
| Advice worth surfacing once per session | `nudge` |
|
|
72
72
|
| A code-content rule needing AST precision | `lint()` |
|
|
73
|
-
| A whole style guide | delegate to the `translating-styleguides` skill |
|
|
73
|
+
| A whole style guide | delegate to the `captain-hook:translating-styleguides` skill |
|
|
74
74
|
|
|
75
75
|
Worked, test-passing code for each shape:
|
|
76
76
|
[pattern catalog](references/pattern-catalog.md).
|
|
@@ -364,6 +364,6 @@ CONTRIBUTING/AGENTS/CLAUDE.
|
|
|
364
364
|
|
|
365
365
|
Found one? Stop. Do not write `StyleRule`s, `lint` approximations of style rules, or a
|
|
366
366
|
`style.py` here. Offer the category E menu option and, if approved, invoke the
|
|
367
|
-
`translating-styleguides` skill with the markdown path — it owns rule atomization, the
|
|
367
|
+
`captain-hook:translating-styleguides` skill with the markdown path — it owns rule atomization, the
|
|
368
368
|
Matcher/`check()`/LLM tier decision, `style.py`, and its own enforcement report. If the
|
|
369
369
|
Skill tool is unavailable, read that skill's `SKILL.md` and follow it (both ship together).
|
|
@@ -119,7 +119,7 @@ that already had its own `.claude/hooks/`, `init` leaves those files untouched a
|
|
|
119
119
|
|
|
120
120
|
One file per approved category: `safety.py`, `quality.py`, `testing.py`, `workflow.py`
|
|
121
121
|
(+ `style.py`, owned end-to-end by `translating-styleguides`). Drafting is delegated:
|
|
122
|
-
for each approved hook, invoke the `authoring-hooks` skill via the Skill tool, passing
|
|
122
|
+
for each approved hook, invoke the `captain-hook:authoring-hooks` skill via the Skill tool, passing
|
|
123
123
|
|
|
124
124
|
- the **source quote, verbatim** (it becomes the citation inside the message — the
|
|
125
125
|
agent being blocked learns *why*),
|
|
@@ -225,7 +225,7 @@ Report row:
|
|
|
225
225
|
|
|
226
226
|
When the survey finds a style guide (`STYLEGUIDE.md`, a "Code style" section in
|
|
227
227
|
CONTRIBUTING/AGENTS/CLAUDE, `docs/style*.md`), this skill **never** writes `StyleRule`s
|
|
228
|
-
itself. If the user approves the category E option, invoke the `translating-styleguides`
|
|
228
|
+
itself. If the user approves the category E option, invoke the `captain-hook:translating-styleguides`
|
|
229
229
|
skill via the Skill tool with the markdown path as args; it owns `style.py` end-to-end and
|
|
230
230
|
its enforcement report is appended to this skill's final report. If the Skill tool is
|
|
231
231
|
unavailable, read that skill's `SKILL.md` directly and follow it — both skills ship together.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scanning-sessions
|
|
3
|
-
description: The headless session-reviewer brain — turns a watched repo's PR-eligible candidates into pull requests, both kinds. Invoked as /scanning-sessions --transcript <path> inside the target repo by capt-hook's detached SessionEnd reviewer pipeline. Enumerates judge-accepted, threshold-eligible candidates via uvx capt-hook review (the CLI is the source of truth), re-verifies every cited correction or complaint verbatim against its session transcript, then per candidate drafts a new hook (create candidates) or amends the attributed misfiring hook with a regression test (fix candidates) in a worktree by delegating to the authoring-hooks skill, proves it with uvx capt-hook test, opens exactly one PR with the verbatim evidence, and records the PR on the candidate. Use when a prompt starts with /scanning-sessions, or to review eligible capt-hook candidates and open hook PRs.
|
|
3
|
+
description: The headless session-reviewer brain — turns a watched repo's PR-eligible candidates into pull requests, both kinds. Invoked as /captain-hook:scanning-sessions --transcript <path> inside the target repo by capt-hook's detached SessionEnd reviewer pipeline. Enumerates judge-accepted, threshold-eligible candidates via uvx capt-hook review (the CLI is the source of truth), re-verifies every cited correction or complaint verbatim against its session transcript, then per candidate drafts a new hook (create candidates) or amends the attributed misfiring hook with a regression test (fix candidates) in a worktree by delegating to the authoring-hooks skill, proves it with uvx capt-hook test, opens exactly one PR with the verbatim evidence, and records the PR on the candidate. Use when a prompt starts with /captain-hook:scanning-sessions, or to review eligible capt-hook candidates and open hook PRs.
|
|
4
4
|
argument-hint: "--transcript <path to the ended session's transcript>"
|
|
5
5
|
allowed-tools: Read, Grep, Glob, Bash, Skill
|
|
6
6
|
---
|
|
@@ -46,7 +46,7 @@ user feedback next pass.
|
|
|
46
46
|
the candidate stays `watching`, and you never open a PR against a hook that is no
|
|
47
47
|
longer there.
|
|
48
48
|
- **You do not draft hooks yourself** — this skill carries no Write/Edit. Drafting
|
|
49
|
-
happens inside the `authoring-hooks` skill, invoked via the Skill tool.
|
|
49
|
+
happens inside the `captain-hook:authoring-hooks` skill, invoked via the Skill tool.
|
|
50
50
|
- **`uvx capt-hook test` must be green** in the worktree before `gh pr create`.
|
|
51
51
|
- **Run to completion — never stop early.** You run headless; a text-only reply ends
|
|
52
52
|
the session immediately. After the authoring-hooks skill returns, keep going in the
|
|
@@ -126,7 +126,7 @@ Follow [references/pr-workflow.md](references/pr-workflow.md) exactly:
|
|
|
126
126
|
|
|
127
127
|
1. **Worktree** — fetch, then `git worktree add` a `capt-hook/review/<rule-slug>`
|
|
128
128
|
branch off `origin/<default>`.
|
|
129
|
-
2. **Draft** — invoke the `authoring-hooks` skill via the Skill tool, passing the
|
|
129
|
+
2. **Draft** — invoke the `captain-hook:authoring-hooks` skill via the Skill tool, passing the
|
|
130
130
|
verbatim correction, its context, and the worktree path. It picks the primitive,
|
|
131
131
|
writes `.claude/hooks/<slug>.py` with inline tests (one firing on the offending
|
|
132
132
|
shape, one `Allow()` on a benign neighbor), and runs `uvx capt-hook test`. For a
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/capt-hook-api.md
RENAMED
|
File without changes
|
{capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/pitfalls.md
RENAMED
|
File without changes
|
{capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/authoring-hooks/references/testing-hooks.md
RENAMED
|
File without changes
|
{capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/scanning-sessions/references/pr-workflow.md
RENAMED
|
File without changes
|
{capt_hook-3.4.0 → capt_hook-3.5.0}/captain_hook/skills/scanning-sessions/references/review-cli.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|