Skip to content

feat(claude): Add raw hook capture and Claude agent configuration#56

Open
ivke995 wants to merge 18 commits into
mainfrom
feat/claude-diff-trace
Open

feat(claude): Add raw hook capture and Claude agent configuration#56
ivke995 wants to merge 18 commits into
mainfrom
feat/claude-diff-trace

Conversation

@ivke995

@ivke995 ivke995 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@ivke995 ivke995 force-pushed the feat/claude-diff-trace branch 2 times, most recently from 53d3ae6 to a73ccfa Compare June 9, 2026 07:42
ivke995 and others added 6 commits June 9, 2026 15:59
Implement hidden `sce hooks claude-capture` subcommand for raw Claude
hook JSON intake with PostToolUse model enrichment from transcript.
Add Pkl-generated Claude project settings with capture hook config,
and Claude agent/skill/command definitions for the SCE workflow.

- Add ClaudeCapture subcommand to hooks CLI surface (hidden)
- Add ClaudeCaptureEvent enum: SessionStart, UserPromptSubmit,
  PostToolUse, Stop
- Implement PostToolUse model enrichment via claude_transcript
  JSONL transcript model extraction helper
- Refactor trace persistence into reusable building blocks
  (persist_serialized_trace_payload_at,
  persist_trace_payload_with_retries)
- Add RepoPaths::claude_capture_tmp_dir() for canonical path
  ownership of context/tmp/claude/
- Add Pkl-generated config/.claude/settings.json registering
  capture hooks for all four event types
- Add Claude agent, command, and skill definitions under .claude/
  enabling SCE workflow in Claude Code
- Update context documentation for new Claude capture surface

Co-authored-by: SCE <sce@crocoder.dev>
… intake

Remove the `sce hooks claude-capture` hidden CLI route,
`ClaudeCaptureEvent` enum variant, `claude_transcript.rs` enrichment
module, and `RepoPaths::claude_capture_tmp_dir()` — the raw JSON
diagnostic path that wrote Claude hook payloads under
`context/tmp/claude/` without DB persistence or cross-editor reuse.

Add `sce hooks session-model` STDIN intake for normalized model
attribution upsert into the new AgentTraceDb `session_models` table
(migration 008).  `diff-trace` now accepts optional `model_id` and
resolves it from `session_models` when absent, enabling cross-editor
reuse: OpenCode sends `model_id` directly, Claude relies on DB
resolution.

Generate a Claude TypeScript event-adapter runtime at
`.claude/plugins/sce-agent-trace.ts` that emits normalized
`session-model` and `diff-trace` payloads to the shared Rust intake.
Update the generated-config pipeline (Pkl renderers, OpenCode plugin
registration, settings) and build fileset to include the new
agent-trace-plugin source tree.

Update `context/` docs to reflect the removed raw capture route, the
new session-model command routing, and the cross-editor shared boundary
at `sce hooks diff-trace`.

Co-authored-by: SCE <sce@crocoder.dev>
Remove the unused CLI dev-dependency from Cargo.toml and Cargo.lock, leaving the crate without declared dev-dependencies.

Update the documented CLI dependency and styling baseline to reflect the current manifest state.

Co-authored-by: SCE <sce@crocoder.dev>
Claude sends model attribution via `session-model` at SessionStart
rather than including model_id in every diff-trace payload. The parser
previously required model_id, rejecting all Claude diff traces.

- Change DiffTraceInsert.model_id from &str to Option<&str>
- Change DiffTracePayload.model_id from String to Option<String>
- Add optional_string_field helper for JSON parsing
- Wire resolve_model closure for DB lookup when model_id absent
- Thread resolved model_id through persistence functions

Co-authored-by: SCE <sce@crocoder.dev>
Add checked-in diff_creation fixtures for Claude Write/Edit PostToolUse payloads and test deriveClaudeDiffTracePayload through the exported derivation seam. Cover create and edit scenarios with exact expected patch comparisons, and update Agent Trace and patch-service context to document the fixture coverage.

Co-authored-by: SCE <sce@crocoder.dev>
Delete unused input.json sidecars from the Claude diff-creation fixture suite.
The active golden tests consume claude-post-tool-use.json and expected.patch, so
the patch-service context now documents that fixture contract directly.

Co-authored-by: SCE <sce@crocoder.dev>
@ivke995 ivke995 force-pushed the feat/claude-diff-trace branch from d8df734 to 01a6359 Compare June 9, 2026 14:15
@ivke995 ivke995 marked this pull request as ready for review June 9, 2026 14:18
Comment thread cli/src/services/hooks/mod.rs Outdated
Comment thread cli/src/services/hooks/mod.rs Outdated
Comment thread cli/src/services/hooks/mod.rs Outdated
Comment thread config/.claude/plugins/sce-agent-trace.ts Outdated
try {
const parseResult = parseClaudeHookPayloadJson(rawJson);
if (parseResult.status !== "ok") {
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could handle this parsing failure better.

["hooks", "session-model"],
`${JSON.stringify({
sessionID: sessionId,
time: currentTimeMs(context.now),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just Date.now()?

Comment on lines +434 to +436
payload.tool_version,
payload.claude_version,
payload.version,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We expect claude to have different properties for version?

}

try {
const parseResult = parseClaudeHookPayloadJson(rawJson);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could parse hook payload at the top of the function and send parsed result to handlers.

Comment on lines +448 to +458
if (value === undefined) {
return undefined;
}

if (value === null) {
return null;
}

if (typeof value !== "string") {
return null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function could be simplified

function normalizeOptionalVersion(value: unknown): string | null {
	if (!value || typeof value !== "string") {
		return null;
	}

	const normalized = value.trim();
	return normalized.length === 0 ? null : normalized;
}

Comment on lines +183 to +184
"originalFile",
"original_file",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect this property in different formats?

ivke995 and others added 12 commits June 10, 2026 11:00
Share payload-kind-aware validation helpers across diff-trace and session-model hook payload parsing while preserving each command's user-facing error prefix.

Co-authored-by: SCE <sce@crocoder.dev>
Run config-lib Bun and Biome checks from config/lib inside a copied repo-shaped source tree, including the shared CLI diff_creation fixtures needed by agent-trace golden tests.

Records the source-layout contract for config-lib checks.

Co-authored-by: SCE <sce@crocoder.dev>
Co-authored-by: SCE <sce@crocoder.dev>
Introduce cli/src/services/structured_patch.rs to convert Claude
PostToolUse structured payloads into canonical ParsedPatch values.
Supports Write create and Edit structured patch tools with
deterministic skip reasons for unsupported events, tools, or payload
shapes. Register the module in services/mod.rs.

Co-authored-by: SCE <sce@crocoder.dev>
Migrate the Claude PostToolUse diff-creation golden fixture coverage
from TypeScript to Rust.

Co-authored-by: SCE <sce@crocoder.dev>
Introduce migration 009_add_diff_traces_payload_type to add a payload_type
column (TEXT NOT NULL DEFAULT 'patch') to the diff_traces table. This enables
generic storage of source payloads with explicit type discrimination: patch
for OpenCode unified-diff payloads and structured for Claude PostToolUse
structured payloads.

Update typed insert and query structs (DiffTraceInsert, DiffTracePatchRow,
ParsedDiffTracePatch) to carry payload_type, and add PAYLOAD_TYPE_PATCH
and PAYLOAD_TYPE_STRUCTURED constants. Wire PAYLOAD_TYPE_PATCH through the
existing sce hooks diff-trace hook runtime to preserve current OpenCode
behavior. Update recent-diff-trace query SQL, row parsing, and tests to
include the new column.

Co-authored-by: SCE <sce@crocoder.dev>
…trace hook

Extend `sce hooks diff-trace` STDIN intake to classify and persist Claude
structured `PostToolUse` payloads without converting them to unified-diff
text at insert time.

Co-authored-by: SCE <sce@crocoder.dev>
…ocessing

Update AgentTraceDb::recent_diff_trace_patches to dispatch on payload_type:
patch rows continue through existing unified-diff parsing, while structured
rows parse stored JSON and derive ParsedPatch via
structured_patch::derive_claude_structured_patch at read time.

Co-authored-by: SCE <sce@crocoder.dev>
Replace Bun/TypeScript Claude hook invocations with direct `sce hooks`
commands. Claude settings now pipe raw hook event JSON on STDIN:
`SessionStart` → `sce hooks session-model`, matched `PostToolUse` →
`sce hooks diff-trace`.

The Rust `session-model` intake detects Claude payloads via
`hook_event_name` and extracts session_id / model_id / time /
tool_version from the raw Claude event format, normalizing model_id
with a `claude/` prefix. The diff-trace intake already handled
Claude structured-patch derivation.

Co-authored-by: SCE <sce@crocoder.dev>
Claude diff-trace and session-model hooks are now handled by the Rust
CLI via `sce hooks` subcommands (completed in T06). This removes the
obsolete TypeScript Bun plugin runtime.

Co-authored-by: SCE <sce@crocoder.dev>
…ation

Remove stale references to the Claude TypeScript agent-trace runtime
and outdated "until T05" qualifiers across overview, architecture,
glossary, and SCE context files. Reflect the current direct
`sce hooks` boundary where Rust handles extraction, validation,
and persistence without a TypeScript intermediary.

Update the claude-rust-diff-trace plan status to mark T08 and T09
complete and append the final validation report with concrete
success-criteria evidence.

Co-authored-by: SCE <sce@crocoder.dev>
…orts

Update Claude Code settings to use single command strings instead
of separate command/args arrays for hook invocations.

Co-authored-by: SCE <sce@crocoder.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants