capt-hook 3.7.0__tar.gz → 3.8.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.7.0 → capt_hook-3.8.0}/PKG-INFO +3 -3
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/docs.py +3 -1
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/cli.py +35 -3
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/scan.py +35 -1
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/store.py +29 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/pyproject.toml +3 -3
- {capt_hook-3.7.0 → capt_hook-3.8.0}/LICENSE +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/README.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/.claude-plugin/plugin.json +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/__main__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/app.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/classifiers/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/classifiers/conductor.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/classifiers/droid.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/classifiers/native.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/cli.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/command.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/conditions.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/context.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/decisions.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/dispatch.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/events.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/file.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/llm/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/loader.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/log.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/capt-hook.toml +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/commands.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/plans.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/prompts.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/review.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/stewardship.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/general/tasks.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/manager.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/python/capt-hook.toml +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/python/style.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/python/testing.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/packs/python/toolchain.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/commands.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/lint.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/llm.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/nudge.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/primitives/workflow.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/prompt.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/py.typed +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/dashboard.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/fix.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/formats.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/judge.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/pipeline.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/repo.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/settings.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/review/sync.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/session.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/settings.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/signals/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/signals/nlp.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/SKILL.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/capt-hook-api.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/pattern-catalog.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/pitfalls.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/testing-hooks.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/bootstrapping-hooks/SKILL.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/scanning-sessions/SKILL.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/scanning-sessions/references/pr-workflow.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/scanning-sessions/references/review-cli.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/translating-styleguides/SKILL.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/translating-styleguides/references/llm-rule-patterns.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/translating-styleguides/references/matcher-reference.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/translating-styleguides/references/tier-rubric.md +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/state.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/style/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/style/matchers.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/style/scope.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/style/types.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/tasks.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/templates/example_hook.py.tmpl +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/testing/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/testing/helpers.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/testing/session_cache.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/testing/types.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/tests/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/tests/helpers.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/types.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/util/__init__.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/util/model_cache.py +0 -0
- {capt_hook-3.7.0 → capt_hook-3.8.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.8.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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
17
|
Classifier: Topic :: Software Development :: Testing
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Dist: cc-transcript>=
|
|
19
|
+
Requires-Dist: cc-transcript>=4,<5
|
|
20
20
|
Requires-Dist: pydantic>=2.0
|
|
21
21
|
Requires-Dist: pydantic-settings>=2.0
|
|
22
22
|
Requires-Dist: tree-sitter>=0.24
|
|
@@ -30,7 +30,7 @@ Requires-Dist: wn>=1.1.0
|
|
|
30
30
|
Requires-Dist: lazy-object-proxy>=1.12.0
|
|
31
31
|
Requires-Dist: filelock>=3
|
|
32
32
|
Requires-Dist: loguru>=0.7.3
|
|
33
|
-
Requires-Dist: spawnllm>=0.
|
|
33
|
+
Requires-Dist: spawnllm>=0.2.0
|
|
34
34
|
Requires-Dist: pytest>=8.0 ; extra == 'dev'
|
|
35
35
|
Requires-Dist: pytest-asyncio>=0.24 ; extra == 'dev'
|
|
36
36
|
Requires-Dist: pyright>=1.1 ; extra == 'dev'
|
|
@@ -12,7 +12,9 @@ from captain_hook import Allow, FilePath, Input, Tool, UsedSkill, Warn, nudge
|
|
|
12
12
|
nudge(
|
|
13
13
|
"You're editing documentation. Consult the writing-docs skill first for the "
|
|
14
14
|
"Diataxis modes, voice rules, and code-sample rules, then run "
|
|
15
|
-
"`slop-cop check <file> --lang=markdown` to catch prose tells before you finish."
|
|
15
|
+
"`slop-cop check <file> --lang=markdown` to catch prose tells before you finish. "
|
|
16
|
+
"slop-cop is a Go binary — if it's not on PATH, run the `/slop-cop-check` skill "
|
|
17
|
+
"(it installs it), never `uvx slop-cop`.",
|
|
16
18
|
only_if=[Tool("Write|Edit"), FilePath("**/*.md", "**/*.qmd", "docs/**", "README.md")],
|
|
17
19
|
skip_if=[UsedSkill("writing-docs|writing-docs:writing-docs")],
|
|
18
20
|
max_fires=1,
|
|
@@ -21,6 +21,8 @@ import click
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
22
|
from typing import Any
|
|
23
23
|
|
|
24
|
+
from cc_transcript.corrections import Correction
|
|
25
|
+
|
|
24
26
|
from captain_hook.cli import CliState
|
|
25
27
|
from captain_hook.review.judge import JudgeReport
|
|
26
28
|
from captain_hook.review.repo import RepoKey
|
|
@@ -229,26 +231,52 @@ def list_candidates(state: CliState, repo_: str | None) -> None:
|
|
|
229
231
|
click.echo(candidate_line(row))
|
|
230
232
|
|
|
231
233
|
|
|
234
|
+
def correction_lines(correction: Correction) -> tuple[str, ...]:
|
|
235
|
+
match correction.correction_origin:
|
|
236
|
+
case "session" | "git":
|
|
237
|
+
return (
|
|
238
|
+
f" correction ({correction.correction_origin}):",
|
|
239
|
+
f" - {correction.correction_old}",
|
|
240
|
+
f" + {correction.correction_new}",
|
|
241
|
+
)
|
|
242
|
+
case _ if correction.correction_text:
|
|
243
|
+
return (f" correction note: {correction.correction_text}",)
|
|
244
|
+
case _:
|
|
245
|
+
return ()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def correction_block(correction: Correction) -> str:
|
|
249
|
+
return "\n".join(
|
|
250
|
+
(
|
|
251
|
+
f"- {correction.incorrect_file} (session {correction.session_id}):",
|
|
252
|
+
f" - {correction.incorrect_old}",
|
|
253
|
+
f" + {correction.incorrect_new}",
|
|
254
|
+
*correction_lines(correction),
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
232
259
|
@review.command()
|
|
233
260
|
@click.argument("candidate_id", type=int)
|
|
234
261
|
def show(candidate_id: int) -> None:
|
|
235
|
-
"""Show one candidate's row
|
|
262
|
+
"""Show one candidate's row, its threshold status, and the shared ledger's faulted edits."""
|
|
236
263
|
from captain_hook.review.judge import REVIEW_PROMPT_VERSION
|
|
237
264
|
from captain_hook.review.settings import ReviewSettings
|
|
238
265
|
from captain_hook.review.store import ReviewStore
|
|
239
266
|
|
|
240
267
|
settings = ReviewSettings()
|
|
241
268
|
|
|
242
|
-
async def go() -> tuple[dict[str, object], ThresholdStatus, bool]:
|
|
269
|
+
async def go() -> tuple[dict[str, object], ThresholdStatus, bool, tuple[Correction, ...]]:
|
|
243
270
|
async with await ReviewStore.open(settings.db_path) as store:
|
|
244
271
|
return (
|
|
245
272
|
await store.candidate(candidate_id),
|
|
246
273
|
await store.threshold_status(candidate_id, settings=settings, prompt_version=REVIEW_PROMPT_VERSION),
|
|
247
274
|
await store.eligible(candidate_id, settings=settings, prompt_version=REVIEW_PROMPT_VERSION),
|
|
275
|
+
await store.correction_evidence(candidate_id),
|
|
248
276
|
)
|
|
249
277
|
|
|
250
278
|
try:
|
|
251
|
-
row, status, ok = asyncio.run(go())
|
|
279
|
+
row, status, ok, evidence = asyncio.run(go())
|
|
252
280
|
except LookupError as exc:
|
|
253
281
|
raise click.ClickException(str(exc)) from exc
|
|
254
282
|
for key, value in row.items():
|
|
@@ -257,6 +285,10 @@ def show(candidate_id: int) -> None:
|
|
|
257
285
|
f"thresholds: sessions={status.sessions} days={status.days} open_prs={status.open_prs} "
|
|
258
286
|
f"single_observation={status.single_observation} eligible={ok}"
|
|
259
287
|
)
|
|
288
|
+
if evidence:
|
|
289
|
+
click.echo("correction_evidence:")
|
|
290
|
+
for correction in evidence:
|
|
291
|
+
click.echo(correction_block(correction))
|
|
260
292
|
|
|
261
293
|
|
|
262
294
|
@review.command(name="threshold-check")
|
|
@@ -30,6 +30,7 @@ from __future__ import annotations
|
|
|
30
30
|
|
|
31
31
|
from dataclasses import dataclass
|
|
32
32
|
from itertools import chain
|
|
33
|
+
from pathlib import Path
|
|
33
34
|
from typing import TYPE_CHECKING
|
|
34
35
|
|
|
35
36
|
from cc_transcript.activity import SessionActivity
|
|
@@ -76,7 +77,6 @@ from captain_hook.review.store import CandidateKind
|
|
|
76
77
|
|
|
77
78
|
if TYPE_CHECKING:
|
|
78
79
|
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
79
|
-
from pathlib import Path
|
|
80
80
|
from typing import Any
|
|
81
81
|
|
|
82
82
|
from cc_transcript.backend import ParsedTranscript
|
|
@@ -243,6 +243,39 @@ def transcript_repo(events: Sequence[TranscriptEvent]) -> RepoKey | None:
|
|
|
243
243
|
)
|
|
244
244
|
|
|
245
245
|
|
|
246
|
+
def transcript_cwd(events: Sequence[TranscriptEvent]) -> Path | None:
|
|
247
|
+
return next(
|
|
248
|
+
(Path(meta.cwd) for event in events if (meta := event_meta(event)) is not None if meta.cwd is not None),
|
|
249
|
+
None,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
async def record_corrections(
|
|
254
|
+
events: Sequence[TranscriptEvent], kept: Sequence[tuple[MiningSignal, FeedbackCandidate]], *, repo: Path | None
|
|
255
|
+
) -> None:
|
|
256
|
+
"""Grounds each user-correction candidate in the shared code-correction ledger.
|
|
257
|
+
|
|
258
|
+
For every kept user-correction signal (the FIX-mode ``hook_complaint`` is a
|
|
259
|
+
local hook misfire, not a code correction, so it is skipped), harvests the
|
|
260
|
+
edit the feedback faults around its anchor and appends one row to the family
|
|
261
|
+
ledger. Idempotent per anchor: a no-op when cc-pushback already wrote it, so
|
|
262
|
+
captain-hook only fills the ledger for sessions nobody else processed.
|
|
263
|
+
"""
|
|
264
|
+
from cc_transcript.corrections import CorrectionLog
|
|
265
|
+
from cc_transcript.extract import extract_correction, usable_backend
|
|
266
|
+
|
|
267
|
+
corrections = [(sig, candidate) for sig, candidate in kept if sig.kind != HOOK_COMPLAINT]
|
|
268
|
+
if not corrections:
|
|
269
|
+
return
|
|
270
|
+
activity = SessionActivity.from_events(corrections[0][0].session_id, events)
|
|
271
|
+
backend = usable_backend()
|
|
272
|
+
log = CorrectionLog.open()
|
|
273
|
+
for sig, candidate in corrections:
|
|
274
|
+
await extract_correction(
|
|
275
|
+
log, activity, candidate.ref, source="captain-hook", feedback=sig.text, repo=repo, backend=backend
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
246
279
|
async def ingest(
|
|
247
280
|
store: ReviewStore, parsed: ParsedTranscript, *, settings: ReviewSettings, repo_key: RepoKey | None
|
|
248
281
|
) -> ScanReport:
|
|
@@ -275,6 +308,7 @@ async def ingest(
|
|
|
275
308
|
await store.record_observation(
|
|
276
309
|
candidate_id, dedup_key=candidate.dedup_key, session_id=sig.session_id, occurred_at=sig.occurred_at
|
|
277
310
|
)
|
|
311
|
+
await record_corrections(parsed.events, kept, repo=transcript_cwd(parsed.events))
|
|
278
312
|
return ScanReport(scanned=1, inserted=inserted)
|
|
279
313
|
|
|
280
314
|
|
|
@@ -28,6 +28,7 @@ if TYPE_CHECKING:
|
|
|
28
28
|
from pathlib import Path
|
|
29
29
|
from typing import Any
|
|
30
30
|
|
|
31
|
+
from cc_transcript.corrections import Correction
|
|
31
32
|
from cc_transcript.ids import SessionId
|
|
32
33
|
from cc_transcript.mining.candidates import DedupKey
|
|
33
34
|
from cc_transcript.mining.confidence import Confidence
|
|
@@ -105,6 +106,14 @@ WHERE o.candidate_id = ? AND l.accepted = 1 AND l.confidence >= ?
|
|
|
105
106
|
|
|
106
107
|
OPEN_PRS_QUERY = "SELECT COUNT(*) AS n FROM candidates WHERE repo_key = ? AND status = ? AND pr_opened_at > ?"
|
|
107
108
|
|
|
109
|
+
OBSERVATION_ANCHORS_QUERY = """
|
|
110
|
+
SELECT DISTINCT e.session_id, e.event_uuid
|
|
111
|
+
FROM candidate_observations o
|
|
112
|
+
JOIN feedback_events e ON e.dedup_key = o.dedup_key
|
|
113
|
+
WHERE o.candidate_id = ? AND e.session_id IS NOT NULL AND e.event_uuid IS NOT NULL
|
|
114
|
+
ORDER BY o.id
|
|
115
|
+
"""
|
|
116
|
+
|
|
108
117
|
CANDIDATES_QUERY = """
|
|
109
118
|
SELECT c.*,
|
|
110
119
|
(SELECT e.text FROM candidate_observations o JOIN feedback_events e ON e.dedup_key = o.dedup_key
|
|
@@ -502,6 +511,26 @@ class ReviewStore(VerdictStoreMixin, FeedbackStore):
|
|
|
502
511
|
)
|
|
503
512
|
return str(rows[0]["summary"]) if (rows := [dict(row) async for row in cur]) else None
|
|
504
513
|
|
|
514
|
+
async def correction_evidence(self, candidate_id: int) -> tuple[Correction, ...]:
|
|
515
|
+
"""Returns the shared-ledger code corrections grounding a candidate's observations.
|
|
516
|
+
|
|
517
|
+
Joins each observation back to its feedback anchor ``(session_id,
|
|
518
|
+
event_uuid)`` and pulls the corrections the family ledger holds for that
|
|
519
|
+
anchor — the offending before/after edit the PR-drafting brain needs. The
|
|
520
|
+
reviewer's own per-session pass writes these rows, so a candidate that
|
|
521
|
+
crossed its thresholds carries its faulted edits.
|
|
522
|
+
"""
|
|
523
|
+
from cc_transcript.corrections import CorrectionLog
|
|
524
|
+
from cc_transcript.ids import EventUuid, SessionId
|
|
525
|
+
|
|
526
|
+
cur = await self.store.conn.execute(OBSERVATION_ANCHORS_QUERY, (candidate_id,))
|
|
527
|
+
log = CorrectionLog.open()
|
|
528
|
+
return tuple(
|
|
529
|
+
correction
|
|
530
|
+
for row in [dict(row) async for row in cur]
|
|
531
|
+
for correction in log.for_anchor(SessionId(str(row["session_id"])), EventUuid(str(row["event_uuid"])))
|
|
532
|
+
)
|
|
533
|
+
|
|
505
534
|
async def candidate_view(
|
|
506
535
|
self, row: dict[str, object], *, settings: ReviewSettings, prompt_version: int
|
|
507
536
|
) -> CandidateView:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "capt-hook"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.8.0"
|
|
4
4
|
description = "Declarative hook framework for Claude Code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "PolyForm-Noncommercial-1.0.0"
|
|
@@ -20,7 +20,7 @@ classifiers = [
|
|
|
20
20
|
]
|
|
21
21
|
requires-python = ">=3.13"
|
|
22
22
|
dependencies = [
|
|
23
|
-
"cc-transcript>=
|
|
23
|
+
"cc-transcript>=4,<5",
|
|
24
24
|
"pydantic>=2.0",
|
|
25
25
|
"pydantic-settings>=2.0",
|
|
26
26
|
"tree-sitter>=0.24",
|
|
@@ -34,7 +34,7 @@ dependencies = [
|
|
|
34
34
|
"lazy-object-proxy>=1.12.0",
|
|
35
35
|
"filelock>=3",
|
|
36
36
|
"loguru>=0.7.3",
|
|
37
|
-
"spawnllm>=0.
|
|
37
|
+
"spawnllm>=0.2.0",
|
|
38
38
|
]
|
|
39
39
|
|
|
40
40
|
[project.optional-dependencies]
|
|
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
|
|
File without changes
|
{capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/capt-hook-api.md
RENAMED
|
File without changes
|
|
File without changes
|
{capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/pitfalls.md
RENAMED
|
File without changes
|
{capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/authoring-hooks/references/testing-hooks.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capt_hook-3.7.0 → capt_hook-3.8.0}/captain_hook/skills/scanning-sessions/references/pr-workflow.md
RENAMED
|
File without changes
|
{capt_hook-3.7.0 → capt_hook-3.8.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
|