diff --git a/cli/assets/hooks/post-commit b/cli/assets/hooks/post-commit index 0336572e..a4d7935b 100644 --- a/cli/assets/hooks/post-commit +++ b/cli/assets/hooks/post-commit @@ -1,4 +1,10 @@ #!/bin/sh set -eu +remote_url="$(git remote get-url origin 2>/dev/null || true)" + +if [ -n "$remote_url" ]; then + exec sce hooks post-commit --vcs git --remote-url "$remote_url" "$@" +fi + exec sce hooks post-commit --vcs git "$@" diff --git a/cli/migrations/agent-trace/006_add_agent_traces_vcs_remote_url.sql b/cli/migrations/agent-trace/006_add_agent_traces_vcs_remote_url.sql new file mode 100644 index 00000000..44081454 --- /dev/null +++ b/cli/migrations/agent-trace/006_add_agent_traces_vcs_remote_url.sql @@ -0,0 +1,2 @@ +ALTER TABLE agent_traces +ADD COLUMN remote_url TEXT; diff --git a/cli/migrations/agent-trace/007_create_agent_traces_vcs_remote_url_index.sql b/cli/migrations/agent-trace/007_create_agent_traces_vcs_remote_url_index.sql new file mode 100644 index 00000000..eda388cc --- /dev/null +++ b/cli/migrations/agent-trace/007_create_agent_traces_vcs_remote_url_index.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS idx_agent_traces_remote_url +ON agent_traces (remote_url); diff --git a/cli/src/cli_schema.rs b/cli/src/cli_schema.rs index 8d1b258a..d35347e4 100644 --- a/cli/src/cli_schema.rs +++ b/cli/src/cli_schema.rs @@ -267,6 +267,9 @@ pub enum HooksSubcommand { PostCommit { #[arg(long = "vcs")] vcs: Option, + + #[arg(long = "remote-url")] + remote_url: Option, }, #[command(about = "Run post-rewrite hook (reads pairs from STDIN)")] diff --git a/cli/src/services/agent_trace_db/mod.rs b/cli/src/services/agent_trace_db/mod.rs index d61612c4..f3bc5324 100644 --- a/cli/src/services/agent_trace_db/mod.rs +++ b/cli/src/services/agent_trace_db/mod.rs @@ -23,6 +23,11 @@ const CREATE_DIFF_TRACES_TIME_MS_ID_INDEX_MIGRATION: &str = const CREATE_AGENT_TRACES_AGENT_TRACE_ID_INDEX_MIGRATION: &str = include_str!( "../../../migrations/agent-trace/005_create_agent_traces_agent_trace_id_index.sql" ); +const ADD_AGENT_TRACES_REMOTE_URL_MIGRATION: &str = + include_str!("../../../migrations/agent-trace/006_add_agent_traces_vcs_remote_url.sql"); +const CREATE_AGENT_TRACES_REMOTE_URL_INDEX_MIGRATION: &str = include_str!( + "../../../migrations/agent-trace/007_create_agent_traces_vcs_remote_url_index.sql" +); const AGENT_TRACE_MIGRATIONS: &[(&str, &str)] = &[ ("001_create_diff_traces", CREATE_DIFF_TRACES_MIGRATION), @@ -39,6 +44,14 @@ const AGENT_TRACE_MIGRATIONS: &[(&str, &str)] = &[ "005_create_agent_traces_agent_trace_id_index", CREATE_AGENT_TRACES_AGENT_TRACE_ID_INDEX_MIGRATION, ), + ( + "006_add_agent_traces_remote_url", + ADD_AGENT_TRACES_REMOTE_URL_MIGRATION, + ), + ( + "007_create_agent_traces_remote_url_index", + CREATE_AGENT_TRACES_REMOTE_URL_INDEX_MIGRATION, + ), ]; /// Parameterized SQL for inserting a captured diff trace payload. @@ -66,7 +79,7 @@ pub const INSERT_POST_COMMIT_PATCH_INTERSECTION_SQL: &str = /// Parameterized SQL for inserting a built agent trace payload. pub const INSERT_AGENT_TRACE_SQL: &str = - "INSERT INTO agent_traces (commit_id, commit_time_ms, trace_json, agent_trace_id, url) VALUES (?1, ?2, ?3, ?4, ?5)"; + "INSERT INTO agent_traces (commit_id, commit_time_ms, trace_json, agent_trace_id, url, remote_url) VALUES (?1, ?2, ?3, ?4, ?5, ?6)"; /// Agent trace database configuration. pub struct AgentTraceDbSpec; @@ -168,6 +181,7 @@ pub struct AgentTraceInsert<'a> { pub trace_json: &'a str, pub agent_trace_id: &'a str, pub url: &'a str, + pub remote_url: &'a str, } impl AgentTraceDb { @@ -241,6 +255,7 @@ fn insert_agent_trace_with(db: &TursoDb, input: AgentTraceInsert<' input.trace_json, input.agent_trace_id, input.url, + input.remote_url, ), ) } @@ -537,6 +552,11 @@ mod tests { "index", "idx_agent_traces_agent_trace_id" )); + assert!(sqlite_object_exists( + &db, + "index", + "idx_agent_traces_remote_url" + )); assert_eq!( applied_migration_ids(&db), vec![ @@ -545,6 +565,8 @@ mod tests { "003_create_agent_traces", "004_create_diff_traces_time_ms_id_index", "005_create_agent_traces_agent_trace_id_index", + "006_add_agent_traces_remote_url", + "007_create_agent_traces_remote_url_index", ] ); @@ -556,6 +578,7 @@ mod tests { trace_json: r#"{"id":"trace-1"}"#, agent_trace_id: "trace-1", url: "sce.crocoder.dev/trace/trace-1", + remote_url: "https://github.com/test/repo", }, ); assert!(duplicate_insert.is_ok()); @@ -568,6 +591,7 @@ mod tests { trace_json: r#"{"id":"trace-1"}"#, agent_trace_id: "trace-1", url: "sce.crocoder.dev/trace/trace-1", + remote_url: "https://github.com/test/repo", }, ); assert!(duplicate_insert.is_err()); diff --git a/cli/src/services/hooks/mod.rs b/cli/src/services/hooks/mod.rs index 705bf0c7..ae69d393 100644 --- a/cli/src/services/hooks/mod.rs +++ b/cli/src/services/hooks/mod.rs @@ -37,9 +37,16 @@ const MAX_TRACE_FILE_CREATE_ATTEMPTS: u64 = 1_000_000; #[derive(Clone, Debug, Eq, PartialEq)] pub enum HookSubcommand { PreCommit, - CommitMsg { message_file: PathBuf }, - PostCommit { vcs_type: Option }, - PostRewrite { rewrite_method: String }, + CommitMsg { + message_file: PathBuf, + }, + PostCommit { + vcs_type: Option, + remote_url: Option, + }, + PostRewrite { + rewrite_method: String, + }, DiffTrace, } @@ -85,9 +92,10 @@ fn run_hooks_subcommand_in_repo( HookSubcommand::CommitMsg { message_file } => { run_commit_msg_subcommand_with_trace(repository_root, subcommand, message_file) } - HookSubcommand::PostCommit { vcs_type } => { - run_post_commit_subcommand_with_trace(repository_root, *vcs_type) - } + HookSubcommand::PostCommit { + vcs_type, + remote_url, + } => run_post_commit_subcommand_with_trace(repository_root, *vcs_type, remote_url.clone()), HookSubcommand::PostRewrite { rewrite_method } => { run_post_rewrite_subcommand_with_trace(repository_root, subcommand, rewrite_method) } @@ -486,10 +494,12 @@ fn run_commit_msg_subcommand_with_trace( fn run_post_commit_subcommand( repository_root: &Path, vcs_type: Option, + remote_url: &str, ) -> Result { run_post_commit_subcommand_with( repository_root, vcs_type, + remote_url, run_post_commit_intersection_flow, run_post_commit_agent_trace_flow, ) @@ -498,6 +508,7 @@ fn run_post_commit_subcommand( fn run_post_commit_subcommand_with( repository_root: &Path, vcs_type: Option, + remote_url: &str, run_intersection_flow: F, run_agent_trace_flow: B, ) -> Result @@ -507,10 +518,11 @@ where &Path, &PostCommitIntersectionFlowResult, Option, + &str, ) -> Result, { let result = run_intersection_flow(repository_root)?; - let _agent_trace = run_agent_trace_flow(repository_root, &result, vcs_type)?; + let _agent_trace = run_agent_trace_flow(repository_root, &result, vcs_type, remote_url)?; Ok(format!( "post-commit hook processed intersection: commit={}, intersection_files={}", @@ -523,12 +535,14 @@ fn run_post_commit_agent_trace_flow( _repository_root: &Path, flow_result: &PostCommitIntersectionFlowResult, vcs_type: Option, + remote_url: &str, ) -> Result { let db = AgentTraceDb::new().context("Failed to open Agent Trace DB for post-commit trace.")?; run_post_commit_agent_trace_flow_with( flow_result, vcs_type, + remote_url, |trace_value| { validate_agent_trace_value(trace_value) .map_err(|error| anyhow!(error.to_string())) @@ -548,6 +562,7 @@ fn run_post_commit_agent_trace_flow( fn run_post_commit_agent_trace_flow_with( flow_result: &PostCommitIntersectionFlowResult, vcs_type: Option, + remote_url: &str, validate_agent_trace: V, persist_agent_trace: I, ) -> Result @@ -597,6 +612,7 @@ where trace_json: &serialized, agent_trace_id: &agent_trace.id, url: &constructed_url, + remote_url, }; persist_agent_trace(insert_input)?; @@ -700,10 +716,15 @@ fn current_unix_time_ms() -> Result { fn run_post_commit_subcommand_with_trace( repository_root: &Path, vcs_type: Option, + remote_url: Option, ) -> Result { - let subcommand = HookSubcommand::PostCommit { vcs_type }; + let remote_url_value = remote_url.clone().unwrap_or_default(); + let subcommand = HookSubcommand::PostCommit { + vcs_type, + remote_url, + }; let input = build_hook_trace_input_for_post_commit(repository_root); - let outcome = run_post_commit_subcommand(repository_root, vcs_type); + let outcome = run_post_commit_subcommand(repository_root, vcs_type, &remote_url_value); let _ = persist_hook_trace(repository_root, &subcommand, &input, &outcome); diff --git a/cli/src/services/parse/command_runtime.rs b/cli/src/services/parse/command_runtime.rs index d5b63ff7..0e0fdc6f 100644 --- a/cli/src/services/parse/command_runtime.rs +++ b/cli/src/services/parse/command_runtime.rs @@ -384,12 +384,17 @@ fn convert_hooks_subcommand( subcommand: services::hooks::HookSubcommand::CommitMsg { message_file }, })) } - cli_schema::HooksSubcommand::PostCommit { vcs } => { + cli_schema::HooksSubcommand::PostCommit { vcs, remote_url } => { let vcs_type = parse_optional_hook_vcs_type(vcs.as_deref()) .map_err(ClassifiedError::validation)?; + let remote_url = + parse_optional_hook_remote_url(remote_url).map_err(ClassifiedError::validation)?; Ok(Box::new(services::hooks::command::HooksCommand { - subcommand: services::hooks::HookSubcommand::PostCommit { vcs_type }, + subcommand: services::hooks::HookSubcommand::PostCommit { + vcs_type, + remote_url: Some(remote_url), + }, })) } cli_schema::HooksSubcommand::PostRewrite { rewrite_method } => { @@ -424,3 +429,10 @@ fn parse_optional_hook_vcs_type( )), } } + +fn parse_optional_hook_remote_url(remote_url: Option) -> Result { + match remote_url { + Some(url) if !url.trim().is_empty() => Ok(url), + _ => Err("Missing required option '--remote-url' for 'sce hooks post-commit'.".to_string()), + } +} diff --git a/context/architecture.md b/context/architecture.md index c25663f6..f804b12a 100644 --- a/context/architecture.md +++ b/context/architecture.md @@ -106,7 +106,7 @@ The repository includes a new placeholder Rust binary crate at `cli/`. - `cli/src/services/auth_command/mod.rs` defines the implemented auth command surface for `sce auth login|renew|logout|status`, including device-flow login, stored-token renewal (`--force` supported for renew), logout, and status rendering in text/JSON formats; `cli/src/services/auth_command/command.rs` owns the `AuthCommand` struct and its `RuntimeCommand` impl. - `cli/src/services/db/mod.rs` provides the shared generic Turso infrastructure seam: `DbSpec` supplies a service-specific name, path, and ordered embedded migrations, while `TursoDb` owns parent-directory creation, `Builder::new_local(...)` initialization, Turso connection setup, tokio current-thread runtime bridging, blocking `execute`/`query`/`query_map` wrappers, and generic migration execution with per-database `__sce_migrations` metadata. Existing DB files without migration metadata are upgraded by re-applying the current idempotent migration set and recording each migration ID, so setup/lifecycle initialization applies later migrations to already-created databases. The same module owns shared DB lifecycle helpers for path-health problem collection and DB parent-directory bootstrap. - `cli/src/services/local_db/mod.rs` provides the concrete local DB spec and `LocalDb` type alias over the shared generic `TursoDb` adapter. `LocalDbSpec` resolves the deterministic persistent runtime DB target through the shared default-path seam and declares no local migrations; `TursoDb` supplies blocking `execute`/`query`, parent-directory creation, Turso connection setup, tokio current-thread runtime bridging, and generic migration execution. -- `cli/src/services/agent_trace_db/mod.rs` provides the Agent Trace DB spec and `AgentTraceDb` type alias over `TursoDb`. `AgentTraceDbSpec` resolves `/sce/agent-trace.db` through the shared default-path seam and embeds an ordered split fresh-start baseline migration set (`001_create_diff_traces`, `002_create_post_commit_patch_intersections`, `003_create_agent_traces`, `004_create_diff_traces_time_ms_id_index`, `005_create_agent_traces_agent_trace_id_index`) without `AUTOINCREMENT`; `agent_traces.agent_trace_id` is `NOT NULL UNIQUE` and indexed by `idx_agent_traces_agent_trace_id`. The module adds `DiffTraceInsert<'_>`/`insert_diff_trace()` (including `model_id`, `tool_name`, and nullable `tool_version` writes), `PostCommitPatchIntersectionInsert<'_>`/`insert_post_commit_patch_intersection()`, and `AgentTraceInsert<'_>`/`insert_agent_trace()` for parameterized writes plus `recent_diff_trace_patches(cutoff_time_ms, end_time_ms)` for inclusive chronological `diff_traces` reads that parse valid raw patch text and return skipped malformed-row reports. `cli/src/services/agent_trace_db/lifecycle.rs` registers Agent Trace DB setup/doctor lifecycle behavior; runtime writes come from `sce hooks diff-trace` (`diff_traces`) and `sce hooks post-commit` (`post_commit_patch_intersections` + built `agent_traces`). +- `cli/src/services/agent_trace_db/mod.rs` provides the Agent Trace DB spec and `AgentTraceDb` type alias over `TursoDb`. `AgentTraceDbSpec` resolves `/sce/agent-trace.db` through the shared default-path seam and embeds an ordered split fresh-start baseline migration set (`001_create_diff_traces`, `002_create_post_commit_patch_intersections`, `003_create_agent_traces`, `004_create_diff_traces_time_ms_id_index`, `005_create_agent_traces_agent_trace_id_index`, `006_add_agent_traces_remote_url`, `007_create_agent_traces_remote_url_index`) without `AUTOINCREMENT`; `agent_traces.agent_trace_id` is `NOT NULL UNIQUE`, `agent_traces.remote_url` is nullable, and indexes include `idx_agent_traces_agent_trace_id` plus `idx_agent_traces_remote_url`. The module adds `DiffTraceInsert<'_>`/`insert_diff_trace()` (including `model_id`, `tool_name`, and nullable `tool_version` writes), `PostCommitPatchIntersectionInsert<'_>`/`insert_post_commit_patch_intersection()`, and `AgentTraceInsert<'_>`/`insert_agent_trace()` for parameterized writes plus `recent_diff_trace_patches(cutoff_time_ms, end_time_ms)` for inclusive chronological `diff_traces` reads that parse valid raw patch text and return skipped malformed-row reports. `cli/src/services/agent_trace_db/lifecycle.rs` registers Agent Trace DB setup/doctor lifecycle behavior; runtime writes come from `sce hooks diff-trace` (`diff_traces`) and `sce hooks post-commit` (`post_commit_patch_intersections` + built `agent_traces`). - `cli/src/test_support.rs` provides a shared test-only temp-directory helper (`TestTempDir`) used by service tests that need filesystem fixtures. - `cli/src/services/setup/mod.rs` defines the setup command contract (`SetupMode`, `SetupTarget`, `SetupRequest`, CLI flag parser/validator), an `inquire`-backed interactive target prompter (`InquireSetupTargetPrompter`), setup dispatch outcomes (proceed/cancelled), compile-time embedded asset access (`EmbeddedAsset`, target-scoped iterators, required-hook asset iterators/lookups) generated by `cli/build.rs` from the ephemeral crate-local `cli/assets/generated/config/{opencode,claude}/**` mirror plus `cli/assets/hooks/**`, and focused internal support seams for install-flow vs prompt-flow logic; `cli/src/services/setup/command.rs` owns `SetupCommand` and its `RuntimeCommand` impl. Its install engine/orchestrator stages embedded files and uses a unified remove-and-replace policy (removing existing targets before swapping staged content, with deterministic recovery guidance on swap failure and no backup artifact creation), and formats deterministic completion messaging; required-hook install orchestration (`install_required_git_hooks`) follows the same remove-and-replace policy (removing existing hooks before swapping staged content, with deterministic recovery guidance on swap failure). The setup command derives a repo-root-scoped context from the runtime `AppContext` before aggregating `ServiceLifecycle::setup` calls across lifecycle providers (config → local_db → agent_trace_db → hooks when requested), so setup providers receive the runtime logger, telemetry, and capability objects instead of a setup-local replacement context. - `cli/src/services/setup/mod.rs` keeps those responsibilities inside one file for now, but the current ownership split is explicit: the inline `install` module owns repository-path normalization, staging/swap install behavior, required-hook installation, and filesystem safety guards, while the inline `prompt` module owns interactive target selection and prompt styling. @@ -114,7 +114,7 @@ The repository includes a new placeholder Rust binary crate at `cli/`. - `cli/src/services/doctor/mod.rs` owns the current doctor request/report surface while focused submodules (`doctor/inspect.rs`, `doctor/render.rs`, `doctor/fixes.rs`, `doctor/types.rs`) split report fact collection, rendering, manual fix reporting, and doctor-owned domain types into smaller seams; `cli/src/services/doctor/command.rs` owns `DoctorCommand` and its `RuntimeCommand` impl. Runtime doctor execution receives `AppContext`, requests the shared lifecycle provider catalog with hooks included for service-owned `diagnose` and `fix` behavior, adapts lifecycle-owned health/fix records into doctor-owned problem/fix records, and then renders stable text/JSON problem records with category/severity/fixability/remediation fields plus deterministic fix-result reporting in fix mode. Report fact collection still preserves current environment/repository/hook/integration display data, while service-owned lifecycle providers now own config validation, local DB and Agent Trace DB readiness/bootstrap, and hook rollout diagnosis/repair. - `cli/src/services/version/mod.rs` defines the version command parser/rendering contract (`parse_version_request`, `render_version`) with deterministic text output and stable JSON runtime-identification fields; `cli/src/services/version/command.rs` owns the `VersionCommand` struct and its `RuntimeCommand` impl. - `cli/src/services/completion/mod.rs` defines completion parser/rendering contract (`parse_completion_request`, `render_completion`) with deterministic Bash/Zsh/Fish script output aligned to current parser-valid command/flag surfaces; `cli/src/services/completion/command.rs` owns the `CompletionCommand` struct and its `RuntimeCommand` impl. -- `cli/src/services/hooks/mod.rs` defines the current local hook runtime parsing/dispatch (`HookSubcommand`, `run_hooks_subcommand`) plus a commit-msg co-author policy seam (`apply_commit_msg_coauthor_policy`) that injects one canonical SCE trailer only when the disabled-default attribution-hooks config/env control is enabled and `SCE_DISABLED` is false; `cli/src/services/hooks/command.rs` owns `HooksCommand` and its `RuntimeCommand` impl. In the current attribution-only baseline, `pre-commit` and `post-rewrite` are deterministic no-op surfaces; `post-commit` is an active intersection + Agent Trace persistence entrypoint (captures current commit patch, queries recent `diff_traces` from the bounded past-7-days window, combines valid patches via `patch::combine_patches`, intersects with post-commit patch via `patch::intersect_patches`, persists result to `post_commit_patch_intersections`, then persists built Agent Trace payloads with range-level `content_hash` values to `agent_traces` in AgentTraceDb without post-commit file artifacts); while `diff-trace` performs STDIN JSON intake, validates required non-empty `sessionID`/`diff`/`model_id`/`tool_name` and required `tool_version` (present and either `null` or non-empty string) plus required `u64` `time` (Unix epoch milliseconds), rejects values that cannot fit AgentTraceDb signed `time_ms` storage, writes one collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` artifact, and inserts the parsed payload fields into AgentTraceDb. Success requires both persistence paths to succeed. +- `cli/src/services/hooks/mod.rs` defines the current local hook runtime parsing/dispatch (`HookSubcommand`, `run_hooks_subcommand`) plus a commit-msg co-author policy seam (`apply_commit_msg_coauthor_policy`) that injects one canonical SCE trailer only when the disabled-default attribution-hooks config/env control is enabled and `SCE_DISABLED` is false; `cli/src/services/hooks/command.rs` owns `HooksCommand` and its `RuntimeCommand` impl. In the current attribution-only baseline, `pre-commit` and `post-rewrite` are deterministic no-op surfaces; `post-commit` requires validated `--remote-url`, threads that URL through the Agent Trace flow, prints it to stderr, and remains an active intersection + Agent Trace persistence entrypoint (captures current commit patch, queries recent `diff_traces` from the bounded past-7-days window, combines valid patches via `patch::combine_patches`, intersects with post-commit patch via `patch::intersect_patches`, persists result to `post_commit_patch_intersections`, then persists built Agent Trace payloads with range-level `content_hash` values to `agent_traces` in AgentTraceDb without post-commit file artifacts); while `diff-trace` performs STDIN JSON intake, validates required non-empty `sessionID`/`diff`/`model_id`/`tool_name` and required `tool_version` (present and either `null` or non-empty string) plus required `u64` `time` (Unix epoch milliseconds), rejects values that cannot fit AgentTraceDb signed `time_ms` storage, writes one collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` artifact, and inserts the parsed payload fields into AgentTraceDb. Success requires both persistence paths to succeed. - `cli/src/services/resilience.rs` defines bounded retry/timeout/backoff execution policy (`RetryPolicy`, `run_with_retry`) for transient operation hardening with deterministic failure messaging and retry observability. - No user-invocable `sce sync` command is wired in the current runtime; local DB and Agent Trace DB bootstrap flows through lifecycle providers aggregated by setup, and DB health/repair flows through the doctor surface. - `cli/src/services/patch.rs` defines the standalone patch domain model (`ParsedPatch`, `PatchFileChange`, `FileChangeKind`, `PatchHunk`, `TouchedLine`, `TouchedLineKind`) for in-memory parsed unified-diff representation, capturing only touched lines (added/removed) plus minimal per-file/per-hunk metadata while excluding non-hunk headers and unchanged context lines. All types are `serde`-serializable/deserializable with `snake_case` JSON field naming. The module also provides `parse_patch`, a public parser function that converts raw unified-diff text (both `Index:` SVN-style and `diff --git` git-style formats) into `ParsedPatch` structs, with `ParseError` for actionable malformed-input diagnostics. Storage-agnostic JSON load helpers (`load_patch_from_json` for string input, `load_patch_from_json_bytes` for byte input) reconstruct `ParsedPatch` from serialized JSON content with `PatchLoadError` for actionable deserialization diagnostics. Its patch-set operations now include deterministic ordered combination plus target-shaped intersection that prefers exact touched-line matches and falls back to historical `kind`+`content` matching when incremental diffs and canonical post-commit diffs have drifted line numbers; `parse_patch`, `combine_patches`, and `intersect_patches` are consumed by the active post-commit hook runtime. diff --git a/context/cli/cli-command-surface.md b/context/cli/cli-command-surface.md index f6b0f290..395fe2d1 100644 --- a/context/cli/cli-command-surface.md +++ b/context/cli/cli-command-surface.md @@ -53,7 +53,7 @@ Operator onboarding currently comes from `sce --help`, command-local `--help` ou - `auth` and `hooks` stay parser-valid and directly invocable, but are hidden from those top-level help surfaces Deferred or gated command surfaces currently avoid claiming unimplemented behavior. -`hooks` routes through implemented subcommand parsing/dispatch for `pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, and `diff-trace`; current behavior remains attribution-only and disabled by default for commit attribution, while `diff-trace` is active STDIN intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (present and either `null` or non-empty string), plus required `u64` `time` (Unix epoch milliseconds) validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe per-invocation `context/tmp/-000000-diff-trace.json` parsed-payload writes, and AgentTraceDb insertion including `model_id`. +`hooks` routes through implemented subcommand parsing/dispatch for `pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, and `diff-trace`; current behavior remains attribution-only and disabled by default for commit attribution, while `post-commit` requires validated `--remote-url`, threads that value through Agent Trace flow, prints it to stderr, and remains the active intersection + Agent Trace DB path, and `diff-trace` is active STDIN intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (present and either `null` or non-empty string), plus required `u64` `time` (Unix epoch milliseconds) validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe per-invocation `context/tmp/-000000-diff-trace.json` parsed-payload writes, and AgentTraceDb insertion including `model_id`. `config` exposes deterministic inspect/validate entrypoints (`sce config show`, `sce config validate`) with explicit precedence (`flags > env > config file > defaults`), a shared auth-runtime resolver for supported keys that declare env/config/optional baked-default inputs starting with `workos_client_id`, first-class `policies.bash` reporting for preset/custom blocked-command rules, and deterministic text/JSON output modes where `show` reports resolved values with provenance while `validate` reports pass/fail plus validation issues and warnings only. `version` exposes deterministic runtime identification output in text mode by default and JSON mode via `--format json`. `completion` exposes deterministic shell completion generation via `sce completion --shell `. @@ -91,7 +91,7 @@ A user-invocable `sync` command is not wired in the current CLI surface; local D - `cli/src/services/doctor/mod.rs` defines the implemented doctor request/report contract (`DoctorRequest`, `DoctorMode`, `run_doctor`) while focused submodules under `cli/src/services/doctor/` handle runtime command dispatch (`command.rs`), diagnosis (`inspect.rs`), rendering (`render.rs`), fix execution (`fixes.rs`), and doctor-owned domain types (`types.rs`). Together they preserve explicit fix-mode parsing, stable text/JSON problem and database-record rendering, deterministic fix-result reporting, and aggregation of `ServiceLifecycle::diagnose`/`ServiceLifecycle::fix` across registered providers (`config`, `local_db`, `agent_trace_db`, `hooks`). The doctor module coordinates state-root/config/database reporting and validation, an empty default repo-scoped database inventory, path-source detection plus required-hook presence/executable/content checks when a repository target is detected, repo-root installed OpenCode integration presence inventory for `plugins`, `agents`, `commands`, and `skills` derived from the embedded OpenCode setup asset catalog, shared-style bracketed human status token rendering (`[PASS]`, `[FAIL]`, `[MISS]`) with simplified `label (path)` text rows, and repair-mode delegation to service-owned fix implementations. - `cli/src/services/version/mod.rs` defines the version parser/output contract (`parse_version_request`, `render_version`) with deterministic text/JSON output modes; `cli/src/services/version/command.rs` owns the version runtime command handler. - `cli/src/services/completion/mod.rs` defines the completion output contract (`render_completion`) using clap_complete to generate deterministic shell scripts for Bash, Zsh, and Fish; `cli/src/services/completion/command.rs` owns the completion runtime command handler. -- `cli/src/services/hooks/mod.rs` defines production local hook runtime parsing/dispatch (`HookSubcommand`, `run_hooks_subcommand`) for `pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, and `diff-trace`; `cli/src/services/hooks/command.rs` owns the hook runtime command handler. Current runtime behavior is commit-msg-only attribution behind the disabled-default attribution gate; `pre-commit` and `post-rewrite` are deterministic no-ops; `post-commit` is an active intersection + Agent Trace DB persistence path (captures current commit patch, combines/intersects recent `diff_traces`, persists intersection metadata to `post_commit_patch_intersections`, then persists built Agent Trace payload with range-level `content_hash` values to `agent_traces`); and `diff-trace` performs STDIN JSON intake, required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required nullable/non-empty `tool_version`, plus required `u64` `time` (Unix epoch milliseconds) validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` persistence, and command-failing AgentTraceDb insertion. `cli/src/services/hooks/lifecycle.rs` implements `ServiceLifecycle` for hook health checks, fix, and setup (hook rollout integrity and required-hook installation). +- `cli/src/services/hooks/mod.rs` defines production local hook runtime parsing/dispatch (`HookSubcommand`, `run_hooks_subcommand`) for `pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, and `diff-trace`; `cli/src/services/hooks/command.rs` owns the hook runtime command handler. Current runtime behavior is commit-msg-only attribution behind the disabled-default attribution gate; `pre-commit` and `post-rewrite` are deterministic no-ops; `post-commit` requires validated `--remote-url`, threads that value through Agent Trace flow, prints it to stderr, and remains an active intersection + Agent Trace DB persistence path (captures current commit patch, combines/intersects recent `diff_traces`, persists intersection metadata to `post_commit_patch_intersections`, then persists built Agent Trace payload with range-level `content_hash` values to `agent_traces`); and `diff-trace` performs STDIN JSON intake, required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required nullable/non-empty `tool_version`, plus required `u64` `time` (Unix epoch milliseconds) validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` persistence, and command-failing AgentTraceDb insertion. `cli/src/services/hooks/lifecycle.rs` implements `ServiceLifecycle` for hook health checks, fix, and setup (hook rollout integrity and required-hook installation). - `cli/src/services/resilience.rs` defines shared bounded retry/timeout/backoff execution policy (`RetryPolicy`, `run_with_retry`) with deterministic failure messaging and retry observability hooks. - No `cli/src/services/sync.rs` module exists in the current codebase; `sce sync` command wiring is deferred, while local DB initialization and health ownership are split between setup and doctor. - `cli/src/services/default_paths.rs` defines the canonical per-user persisted-location seam for config/state/cache roots plus named default file paths for current persisted artifacts (`global config`, `auth tokens`, `local DB`, `agent trace DB`) used by config discovery, token storage, database adapters, and doctor diagnostics; its internal `roots` seam now owns the platform-aware root-directory resolution so non-test production modules consume shared path accessors instead of resolving owned roots directly. diff --git a/context/context-map.md b/context/context-map.md index f79ea11a..889cb2c0 100644 --- a/context/context-map.md +++ b/context/context-map.md @@ -9,7 +9,7 @@ Primary context files: Feature/domain context: -- `context/cli/cli-command-surface.md` (CLI command surface including top-level help with ASCII art banner and gradient rendering, setup install flow, WorkOS device authorization flow + token storage behavior, attribution-only hook routing with DB-backed `diff-trace` dual persistence and post-commit Agent Trace payload persistence including range `content_hash`, setup-owned local DB + Agent Trace DB bootstrap plus doctor DB health coverage, nested flake release package/app installability, and Cargo local install + crates.io readiness policy; `sce sync` command wiring is deferred to `0.4.0`; migrated runtime command structs for help/version/completion/auth/config/setup/doctor/hooks are owned by their respective `services/{name}/command.rs` files, while clap-to-runtime conversion lives in `services/parse/command_runtime.rs`) +- `context/cli/cli-command-surface.md` (CLI command surface including top-level help with ASCII art banner and gradient rendering, setup install flow, WorkOS device authorization flow + token storage behavior, attribution-only hook routing with validated post-commit `--remote-url` plumbing plus DB-backed `diff-trace` dual persistence and post-commit Agent Trace payload persistence including range `content_hash`, setup-owned local DB + Agent Trace DB bootstrap plus doctor DB health coverage, nested flake release package/app installability, and Cargo local install + crates.io readiness policy; `sce sync` command wiring is deferred to `0.4.0`; migrated runtime command structs for help/version/completion/auth/config/setup/doctor/hooks are owned by their respective `services/{name}/command.rs` files, while clap-to-runtime conversion lives in `services/parse/command_runtime.rs`) - `context/cli/default-path-catalog.md` (canonical production CLI path-ownership contract centered on `cli/src/services/default_paths.rs`, including persisted, repo-relative, embedded-asset, install/runtime, hook, and context-path families plus the regression guard that keeps production path ownership centralized) - `context/cli/patch-service.md` (standalone patch domain model, parser, JSON load helpers, and set operations in `cli/src/services/patch.rs` for in-memory parsed unified-diff representation, capturing only touched lines plus minimal per-file/per-hunk metadata, supporting both `Index:` SVN-style and `diff --git` git-style formats, with `ParseError` for actionable malformed-input diagnostics, `PatchLoadError`/`load_patch_from_json`/`load_patch_from_json_bytes` for storage-agnostic JSON reconstruction, `intersect_patches` for target-shaped overlap with exact-match-first and historical `kind`+`content` fallback semantics plus matched-constructed-hunk `model_id` provenance inheritance, and `combine_patches` for ordered patch combination with later-wins conflict resolution plus winning-hunk `model_id` provenance inheritance; `parse_patch`, `intersect_patches`, and `combine_patches` are consumed by the active post-commit hook runtime) - `context/cli/styling-service.md` (CLI text-mode output styling with `owo-colors` and `comfy-table`, TTY/`NO_COLOR` policy, shared helper API for human-facing surfaces, and per-column right-to-left RGB gradient banner rendering) @@ -33,7 +33,7 @@ Feature/domain context: - `context/sce/agent-trace-hook-doctor.md` (approved operator-environment contract for broadening `sce doctor` into the canonical health-and-repair entrypoint, including stable problem taxonomy, `--fix` semantics, setup-to-doctor alignment rules, the current neutral local-DB baseline, and the approved downstream human text-mode layout/status/integration contract) - `context/sce/setup-githooks-install-contract.md` (T01 canonical `sce setup --hooks` install contract for target-path resolution, idempotent outcomes, remove-and-replace behavior, and doctor-readiness alignment) - `context/sce/setup-no-backup-policy-seam.md` (implemented unified remove-and-replace install policy for both config-install and required-hook install flows, with no backup creation and deterministic recovery guidance on swap failure) -- `context/sce/setup-githooks-hook-asset-packaging.md` (T02 compile-time `sce setup --hooks` required-hook template packaging contract and setup-service accessor surface) +- `context/sce/setup-githooks-hook-asset-packaging.md` (T02 compile-time `sce setup --hooks` required-hook template packaging contract, including current post-commit origin remote lookup, remote-URL forwarding/fallback behavior, and setup-service accessor surface) - `context/sce/setup-githooks-install-flow.md` (T03 setup-service required-hook install orchestration with git-truth hooks-path resolution, per-hook installed/updated/skipped outcomes, and remove-and-replace behavior with recovery guidance) - `context/sce/setup-githooks-cli-ux.md` (T04 composable `sce setup` target+`--hooks` / `--repo` command-surface contract, option compatibility validation, and deterministic setup/hook output semantics) - `context/sce/setup-repo-local-config-bootstrap.md` (setup local bootstrap behavior: repo-local `.sce/config.json` create-if-missing via config lifecycle plus lifecycle-owned local DB initialization before hooks/config asset dispatch) @@ -42,12 +42,12 @@ Feature/domain context: - `context/sce/agent-trace-rewrite-trace-transformation.md` (current post-rewrite no-op baseline plus historical rewrite-transformation reference) - `context/sce/local-db.md` (implemented `cli/src/services/local_db/mod.rs` local database spec with `LocalDb = TursoDb`, canonical local DB path resolution, zero local migrations, and inherited blocking `execute`/`query` methods using the shared Turso adapter) - `context/sce/shared-turso-db.md` (current shared `cli/src/services/db/mod.rs` Turso database infrastructure seam, including `DbSpec`, generic `TursoDb`, sync `execute`/`query`/`query_map` wrappers, per-database `__sce_migrations` tracking, generic embedded migration execution, and current concrete wrappers for `LocalDb` plus `AgentTraceDb`) -- `context/sce/agent-trace-db.md` (implemented `cli/src/services/agent_trace_db/mod.rs` Agent Trace database wrapper with canonical `/sce/agent-trace.db` path, ordered `diff_traces`, `post_commit_patch_intersections`, `diff_traces(time_ms, id)` index, `agent_traces`, nullable `diff_traces.model_id`, nullable `diff_traces.tool_name`, nullable `diff_traces.tool_version`, and nullable `agent_traces.agent_trace_id` migrations applied through shared migration metadata, typed parameterized insert helpers for diff traces including `model_id` + tool metadata, post-commit intersection rows, and built `agent_traces` rows with `agent_trace_id` plus schema-validated trace JSON containing range `content_hash`, inclusive bounded chronological recent `diff_traces` query/parse support with malformed-row skip accounting, registered setup/doctor lifecycle provider, and active hook writers for `diff_traces` intake plus post-commit intersection/agent-trace persistence) +- `context/sce/agent-trace-db.md` (implemented `cli/src/services/agent_trace_db/mod.rs` Agent Trace database wrapper with canonical `/sce/agent-trace.db` path, split fresh-start migration set `001..007` (no `AUTOINCREMENT`) defining `diff_traces`, `post_commit_patch_intersections`, `agent_traces`, `agent_traces.remote_url` (nullable), and indexes `idx_diff_traces_time_ms_id`, `idx_agent_traces_agent_trace_id`, `idx_agent_traces_remote_url`, with `agent_traces.agent_trace_id` enforced as `NOT NULL UNIQUE`; includes typed parameterized insert helpers for diff traces including `model_id` + tool metadata, post-commit intersection rows, and built `agent_traces` rows with `agent_trace_id` plus schema-validated trace JSON containing range `content_hash`, bounded chronological recent `diff_traces` query/parse support with malformed-row skip accounting, registered setup/doctor lifecycle provider, and active hook writers for `diff_traces` intake plus post-commit intersection/agent-trace persistence) - `context/sce/agent-trace-core-schema-migrations.md` (historical reference for removed local DB schema bootstrap behavior; T03 now implements the actual local DB with migrations) - `context/sce/agent-trace-retry-queue-observability.md` (inactive local-hook retry path plus historical retry/metrics reference) - `context/sce/agent-trace-local-hooks-mvp-contract-gap-matrix.md` (T01 Local Hooks MVP production contract freeze and deterministic gap matrix for `agent-trace-local-hooks-production-mvp`) - `context/sce/agent-trace-minimal-generator.md` (implemented a library minimal Agent Trace generator seam at `cli/src/services/agent_trace.rs`, used by the active post-commit hook flow to produce strict `0.1.0` JSON payloads with top-level `version`, UUIDv7 `id` derived from commit-time metadata, caller-provided commit-time `timestamp`, optional top-level `vcs` metadata emitted when present (`type` from enum `git|jj|hg|svn`, `revision` from metadata input; current post-commit flow provides `git`), optional top-level `tool` metadata (`name`/`version`) sourced from builder metadata inputs when overlapping AI content exists, and always-emitted `metadata.sce.version` sourced from the compiled `sce` CLI package version, plus per-file trace data from patch inputs via `intersect_patches(constructed_patch, post_commit_patch)` then `post_commit_patch`-anchored hunk classification into `ai`/`mixed`/`unknown` contributor categories, serialized per conversation as nested `contributor.type` with optional `contributor.model_id` omitted when provenance is missing, one derived `ranges[{start_line,end_line,content_hash}]` entry per post-commit or embedded-patch hunk, and range `content_hash` values that hash touched-line kind/content independent of positions and metadata) -- `context/sce/agent-trace-hooks-command-routing.md` (implemented `sce hooks` command routing plus current runtime behavior: disabled-default commit-msg attribution, no-op `pre-commit`/`post-rewrite` entrypoints, active `post-commit` intersection entrypoint capturing current commit patch, querying recent `diff_traces` from past 7 days, combining valid patches via `patch::combine_patches`, intersecting via `patch::intersect_patches`, persisting results to `post_commit_patch_intersections`, building post-commit Agent Trace payloads enriched with optional top-level `tool` metadata, `metadata.sce.version`, and range `content_hash`, schema-validating them, and persisting validated payloads to AgentTraceDb `agent_traces` (DB-only), plus `diff-trace` STDIN intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required nullable/non-empty `tool_version`, required `u64` `time` validation, dual persistence to AgentTraceDb, and collision-safe `context/tmp/-000000-diff-trace.json` artifacts) +- `context/sce/agent-trace-hooks-command-routing.md` (implemented `sce hooks` command routing plus current runtime behavior: disabled-default commit-msg attribution, no-op `pre-commit`/`post-rewrite` entrypoints, active `post-commit` intersection entrypoint requiring validated `--remote-url`, threading that URL to the Agent Trace flow, printing it to stderr, capturing current commit patch, querying recent `diff_traces` from past 7 days, combining/intersecting patches via `patch::combine_patches` / `patch::intersect_patches`, persisting results to `post_commit_patch_intersections`, building/schema-validating post-commit Agent Trace payloads enriched with optional top-level `tool` metadata, `metadata.sce.version`, and range `content_hash`, and persisting validated payloads to AgentTraceDb `agent_traces` (DB-only), plus `diff-trace` STDIN intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required nullable/non-empty `tool_version`, required `u64` `time` validation, dual persistence to AgentTraceDb, and collision-safe `context/tmp/-000000-diff-trace.json` artifacts) - `context/sce/automated-profile-contract.md` (deterministic gate policy for automated OpenCode profile, including 10 gate categories, permission mappings, automated `/commit` single-commit execution behavior, and automated profile constraints) - `context/sce/bash-tool-policy-enforcement-contract.md` (approved bash-tool blocking contract plus the implementation target for generated OpenCode enforcement, including config schema, argv-prefix matching, fixed preset catalog/messages, and precedence rules) - `context/sce/generated-opencode-plugin-registration.md` (current generated OpenCode plugin-registration contract, canonical Pkl ownership, generated manifest/plugin paths including `sce-bash-policy` + `sce-agent-trace`, and TypeScript source ownership; Claude bash-policy enforcement has been removed from generated outputs) diff --git a/context/glossary.md b/context/glossary.md index 8c917a54..b54f676c 100644 --- a/context/glossary.md +++ b/context/glossary.md @@ -30,7 +30,7 @@ - `RuntimeCommand seam`: Internal command-execution abstraction where clap-parsed commands are converted into boxed command objects with `name()` and `execute(&AppContext)` methods, allowing app lifecycle orchestration to log and run commands without a single central dispatch `match` covering every command; the `RuntimeCommand` trait and `RuntimeCommandHandle` type alias are defined in `cli/src/services/command_registry.rs`, and the `CommandRegistry` struct maps command names to zero-arg constructor functions for dispatch. Migrated commands (`HelpCommand`, `HelpTextCommand`, `VersionCommand`, `CompletionCommand`, `AuthCommand`, `ConfigCommand`, `SetupCommand`, `DoctorCommand`, `HooksCommand`) live in service-owned `command.rs` files; parsed request construction lives in `cli/src/services/parse/command_runtime.rs` when user-provided options or subcommands are required. - `sce dependency baseline`: Current crate dependency set declared in `cli/Cargo.toml` (`anyhow`, `clap`, `clap_complete`, `dirs`, `hmac`, `inquire`, `reqwest`, `serde`, `serde_json`, `sha2`, `tokio`, `tracing`, `tracing-subscriber`, `turso`) and validated through normal compile/test coverage. - `local Turso adapter`: Module in `cli/src/services/local_db/mod.rs` that defines `LocalDbSpec` and exposes `LocalDb` as a `TursoDb` alias. It resolves the canonical local DB path with `local_db_path()`, currently declares zero migrations, and inherits `new()`, `execute()`, and `query()` from the shared generic adapter. -- `agent trace DB adapter`: Module in `cli/src/services/agent_trace_db/mod.rs` that defines `AgentTraceDbSpec`, exposes `AgentTraceDb` as a `TursoDb` alias, resolves `/sce/agent-trace.db` through `agent_trace_db_path()`, embeds an ordered split fresh-start migration set (`001..005`) that creates `diff_traces`, `post_commit_patch_intersections`, and `agent_traces` plus `idx_diff_traces_time_ms_id` and `idx_agent_traces_agent_trace_id`, with `agent_traces.agent_trace_id` enforced as `NOT NULL UNIQUE`; provides typed parameterized insert helpers for diff traces including `model_id` + tool metadata, post-commit intersection rows, and built agent-trace rows (including `agent_trace_id`); exposes chronological recent `diff_traces` query/parse support with malformed-row skip accounting; has `AgentTraceDbLifecycle` for setup/doctor integration; and is written by `sce hooks diff-trace` (`diff_traces`) plus `sce hooks post-commit` (`post_commit_patch_intersections` and built `agent_traces`). +- `agent trace DB adapter`: Module in `cli/src/services/agent_trace_db/mod.rs` that defines `AgentTraceDbSpec`, exposes `AgentTraceDb` as a `TursoDb` alias, resolves `/sce/agent-trace.db` through `agent_trace_db_path()`, embeds an ordered split fresh-start migration set (`001..007`) that creates `diff_traces`, `post_commit_patch_intersections`, and `agent_traces`, adds nullable `agent_traces.remote_url`, and creates `idx_diff_traces_time_ms_id`, `idx_agent_traces_agent_trace_id`, and `idx_agent_traces_remote_url`, with `agent_traces.agent_trace_id` enforced as `NOT NULL UNIQUE`; provides typed parameterized insert helpers for diff traces including `model_id` + tool metadata, post-commit intersection rows, and built agent-trace rows (including `agent_trace_id`); exposes chronological recent `diff_traces` query/parse support with malformed-row skip accounting; has `AgentTraceDbLifecycle` for setup/doctor integration; and is written by `sce hooks diff-trace` (`diff_traces`) plus `sce hooks post-commit` (`post_commit_patch_intersections` and built `agent_traces`). - `Agent Trace SCE metadata`: Implementation-owned top-level metadata emitted by `build_agent_trace(...)` as `metadata.sce.version`; the value is sourced from the compiled `sce` CLI package version via `env!("CARGO_PKG_VERSION")`, is schema-validated with the rest of the payload, and is persisted in AgentTraceDb `agent_traces.trace_json` without changing the top-level Agent Trace payload/schema `version`. - `Agent Trace range content_hash`: Per-range `content_hash` emitted by `build_agent_trace(...)` inside every `ranges[]` entry as `murmur3:`, computed from the touched-line kind/content of the `post_commit_patch` or embedded-patch hunk used to emit that range while excluding positions, paths, metadata, and database IDs. - `DiffTraceInsert`: Insert payload in `cli/src/services/agent_trace_db/mod.rs` carrying `time_ms`, `session_id`, `patch`, `model_id`, `tool_name`, and nullable `tool_version` for parameterized writes to the `diff_traces` table. @@ -92,7 +92,7 @@ - `auth config baked default`: Optional key-declared fallback in `cli/src/services/config/mod.rs` used only after env and config-file inputs are absent; the first implemented case is `workos_client_id`, which currently falls back to `client_sce_default`. - `setup install engine`: Installer in `cli/src/services/setup/mod.rs` (`install_embedded_setup_assets`) that writes embedded setup assets into per-target staging directories and swaps them into repository-root `.opencode/`/`.claude/` destinations, using a unified remove-and-replace policy that removes existing targets before swapping staged content. - `setup remove-and-replace`: Replacement choreography in `cli/src/services/setup/mod.rs` where existing install targets are removed before staged content is promoted; on swap failure, the engine cleans temporary staging paths and returns deterministic recovery guidance (recover from version control). No backup artifacts are created. -- `hooks command routing contract`: Current hook command parser/dispatcher plus runtime wiring in `cli/src/services/hooks/mod.rs` (`HookSubcommand`, `run_hooks_subcommand`) that supports `pre-commit`, `commit-msg `, `post-commit`, `post-rewrite `, and `diff-trace` with deterministic invocation validation/usage errors; `commit-msg` is the only active attribution path behind the attribution hooks gate, `pre-commit`/`post-rewrite` are deterministic no-op entrypoints, `post-commit` actively captures the current commit patch, queries recent `diff_traces` from the past 7 days, combines valid patches via `patch::combine_patches`, intersects with the post-commit patch via `patch::intersect_patches`, persists the intersection result to `post_commit_patch_intersections`, and persists built Agent Trace payloads to AgentTraceDb `agent_traces` (DB-only, no post-commit Agent Trace file artifact), and `diff-trace` performs STDIN JSON intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (present and either `null` or non-empty string), required `u64` `time` validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe per-invocation artifact persistence at `context/tmp/-000000-diff-trace.json`, and AgentTraceDb insertion. +- `hooks command routing contract`: Current hook command parser/dispatcher plus runtime wiring in `cli/src/services/hooks/mod.rs` (`HookSubcommand`, `run_hooks_subcommand`) that supports `pre-commit`, `commit-msg `, `post-commit`, `post-rewrite `, and `diff-trace` with deterministic invocation validation/usage errors; `commit-msg` is the only active attribution path behind the attribution hooks gate, `pre-commit`/`post-rewrite` are deterministic no-op entrypoints, `post-commit` requires validated `--remote-url`, threads that value through the Agent Trace flow, prints it to stderr, captures the current commit patch, queries recent `diff_traces` from the past 7 days, combines valid patches via `patch::combine_patches`, intersects with the post-commit patch via `patch::intersect_patches`, persists the intersection result to `post_commit_patch_intersections`, and persists built Agent Trace payloads to AgentTraceDb `agent_traces` (DB-only, no post-commit Agent Trace file artifact), and `diff-trace` performs STDIN JSON intake with required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (present and either `null` or non-empty string), required `u64` `time` validation, non-lossy AgentTraceDb `time_ms` conversion, collision-safe per-invocation artifact persistence at `context/tmp/-000000-diff-trace.json`, and AgentTraceDb insertion. - `cloud sync gateway placeholder`: Abstraction in `cli/src/services/sync.rs` (`CloudSyncGateway`) that returns deferred cloud-sync checkpoints while `sync` remains non-production. - `sce CLI onboarding guide`: Crate-local documentation at `cli/README.md` that defines runnable placeholder commands, non-goals/safety limits, and roadmap mapping to service modules. - `plan/code overlap map`: Context artifact at `context/sce/plan-code-overlap-map.md` that classifies Shared Context Plan/Code, `/change-to-plan`, `/next-task`, `/commit`, and core skills into role-specific vs shared-reusable instruction blocks with explicit dedup targets. @@ -110,7 +110,7 @@ - `agent trace historical reference docs`: Retained `context/sce/agent-trace-*.md` artifacts that describe the removed pre-v0.3 Agent Trace design and task slices; they are reference-only and do not describe the active local-hook runtime. - `agent trace commit-msg co-author policy`: Current contract in `cli/src/services/hooks/mod.rs` (`apply_commit_msg_coauthor_policy`) that applies exactly one canonical trailer (`Co-authored-by: SCE `) only when attribution hooks are enabled and SCE is not disabled; duplicate canonical trailers are deduped idempotently. - `local DB migration contract`: `cli/src/services/local_db/mod.rs` delegates migration execution to `TursoDb` through the `DbSpec::migrations()` contract. The current `LocalDbSpec` migration list is empty, so `LocalDb::new()` opens/creates the canonical local DB without creating local tables. -- `hook no-op baseline`: Current `cli/src/services/hooks/mod.rs` runtime posture where `pre-commit` and `post-rewrite` return deterministic no-op status text, `commit-msg` is a gated mutating path behind the disabled-default attribution-hooks control, `post-commit` is an active intersection + Agent Trace DB path (captures current commit patch, queries recent `diff_traces` from past 7 days, combines/intersects patches, persists to `post_commit_patch_intersections`, and persists built Agent Trace payloads to `agent_traces` without post-commit file artifacts), and `diff-trace` is an active intake path (validates required STDIN payload fields including `model_id`, `tool_name`, and required nullable/non-empty `tool_version`, writes collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` artifacts, and inserts parsed payload fields into AgentTraceDb). +- `hook no-op baseline`: Current `cli/src/services/hooks/mod.rs` runtime posture where `pre-commit` and `post-rewrite` return deterministic no-op status text, `commit-msg` is a gated mutating path behind the disabled-default attribution-hooks control, `post-commit` requires validated `--remote-url`, threads that value through the Agent Trace flow, prints it to stderr, captures current commit patch, queries recent `diff_traces` from past 7 days, combines/intersects patches, persists to `post_commit_patch_intersections`, and persists built Agent Trace payloads to `agent_traces` without post-commit file artifacts, and `diff-trace` is an active intake path (validates required STDIN payload fields including `model_id`, `tool_name`, and required nullable/non-empty `tool_version`, writes collision-safe parsed-payload `context/tmp/-000000-diff-trace.json` artifacts, and inserts parsed payload fields into AgentTraceDb). - `sce doctor` operator-health contract: `cli/src/services/doctor/mod.rs` is the stable doctor entrypoint, with focused `doctor/{inspect,render,fixes,types}.rs` submodules implementing the current approved operator-health surface in `context/sce/agent-trace-hook-doctor.md`: `sce doctor --fix` selects repair intent, help/output expose deterministic doctor mode, JSON includes stable problem taxonomy/fixability fields plus database records and fix-result records, the runtime validates state-root resolution, global and repo-local `sce/config.json` readability/schema health, local DB and Agent Trace DB path/health, DB-parent readiness barriers, git availability, non-repo vs bare-repo targeting failures, effective hook-path source resolution, required hook presence/executable/content drift against canonical embedded hook assets, and repo-root installed OpenCode integration presence for `OpenCode plugins`, `OpenCode agents`, `OpenCode commands`, and `OpenCode skills`. Human text mode now uses the approved sectioned layout (`Environment`, `Configuration` (includes Agent Trace DB row), `Repository`, `Git Hooks`, `Integrations`), `SCE doctor diagnose` / `SCE doctor fix` headers, bracketed `[PASS]`/`[FAIL]`/`[MISS]` status tokens with shared-style green/red colorization when enabled, simplified `label (path)` row formatting, top-level-only hook rows, and presence-only integration parent/child rows where missing required files surface as `[MISS]` children and `[FAIL]` parent groups. Fix mode still reuses canonical setup hook installation for missing/stale/non-executable required hooks and missing hooks directories and can bootstrap canonical missing SCE-owned DB parent directories. - `cli warnings-denied lint policy`: `cli/Cargo.toml` sets `warnings = "deny"`, so plain `cargo clippy --manifest-path cli/Cargo.toml` already fails on warnings without needing an extra `-- -D warnings` tail. - `agent trace local DB schema migration contract`: Retired `apply_core_schema_migrations` behavior removed from the current runtime during `agent-trace-removal-and-hook-noop-reset` T01; the local DB baseline is now file open/create only. diff --git a/context/overview.md b/context/overview.md index 39bf0760..02fccdbc 100644 --- a/context/overview.md +++ b/context/overview.md @@ -44,10 +44,10 @@ Context sync now uses an important-change gate: cross-cutting/policy/architectur The `/change-to-plan` command body is also intentionally thin orchestration: it delegates clarification and plan-shape contracts to `sce-plan-authoring` (including one-task/one-atomic-commit task slicing) while keeping wrapper-level plan output and handoff obligations explicit. The generated OpenCode command doc now also emits `entry-skill: sce-plan-authoring` plus an ordered `skills` list. The targeted support commands (`handover`, `commit`, `validate`) keep their thin-wrapper behavior and now also emit machine-readable OpenCode command frontmatter describing their entry skill and ordered skill chain. `/commit` is now split by profile: manual generated commands remain proposal-only and allow split guidance when staged changes mix unrelated goals, while the automated OpenCode `/commit` command generates exactly one commit message and runs `git commit` against the staged diff. The shared `sce-atomic-commit` contract also requires commit bodies to cite affected plan slug(s) and updated task ID(s) when staged changes include `context/plans/*.md`, and to stop for clarification instead of inventing those references when the staged plan diff is ambiguous. The prior no-git-wrapper Agent Trace design artifacts under `context/sce/agent-trace-*.md` are retained only as historical reference; the current CLI runtime no longer wires the removed Agent Trace schema adaptation, payload building, retry replay, or rewrite handling paths into local hook execution. -The hooks service now uses a minimal attribution-only runtime: `commit-msg` is the only hook that mutates behavior, conditionally injecting exactly one canonical SCE trailer when the attribution-hooks gate is enabled and `SCE_DISABLED` is false; `pre-commit` and `post-rewrite` remain deterministic no-op entrypoints; `post-commit` is an active intersection entrypoint that captures current commit patch, queries recent `diff_traces` from past 7 days, combines/intersects patches, persists intersection metadata to `post_commit_patch_intersections`, and persists the schema-validated built Agent Trace payload, including optional top-level `tool` metadata from recent diff-trace rows, top-level `metadata.sce.version` from the compiled `sce` CLI package version, and range-level `content_hash` values, to AgentTraceDb `agent_traces` (DB-only, no post-commit Agent Trace file artifact); and `diff-trace` currently validates/persists required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (must be present and either `null` or a non-empty string), plus required `u64` millisecond `time`, with non-lossy AgentTraceDb `time_ms` conversion and collision-safe timestamp+attempt artifact filenames. +The hooks service now uses a minimal attribution-only runtime: `commit-msg` is the only hook that mutates behavior, conditionally injecting exactly one canonical SCE trailer when the attribution-hooks gate is enabled and `SCE_DISABLED` is false; `pre-commit` and `post-rewrite` remain deterministic no-op entrypoints; `post-commit` requires validated `--remote-url`, threads that URL through the Agent Trace flow, prints it to stderr, captures current commit patch, queries recent `diff_traces` from past 7 days, combines/intersects patches, persists intersection metadata to `post_commit_patch_intersections`, and persists the schema-validated built Agent Trace payload, including optional top-level `tool` metadata from recent diff-trace rows, top-level `metadata.sce.version` from the compiled `sce` CLI package version, and range-level `content_hash` values, to AgentTraceDb `agent_traces` (DB-only, no post-commit Agent Trace file artifact); and `diff-trace` currently validates/persists required non-empty `sessionID`/`diff`/`model_id`/`tool_name`, required `tool_version` (must be present and either `null` or a non-empty string), plus required `u64` millisecond `time`, with non-lossy AgentTraceDb `time_ms` conversion and collision-safe timestamp+attempt artifact filenames. The CLI now also includes an approved operator-environment doctor contract documented in `context/sce/agent-trace-hook-doctor.md`; the runtime now matches the implemented T06 slice for `sce doctor --fix` parsing/help, stable problem/fix-result reporting, canonical hook-repair reuse, and bounded doctor-owned local-DB directory bootstrap for the missing SCE-owned DB parent path. -The local DB service now provides `LocalDb` as a thin `TursoDb` alias in `cli/src/services/local_db/mod.rs`; `LocalDbSpec` resolves the canonical local DB path from the shared default-path catalog and currently declares zero migrations. Shared Turso infrastructure lives in `cli/src/services/db/mod.rs`, where `DbSpec` and generic `TursoDb` support dual-mode operation — local mode via `turso::Builder::new_local()` when `SCE_SYNC_URL`+`SCE_SYNC_TOKEN` are absent, or sync (Turso Cloud) mode via `turso::sync::Builder::new_remote()` when both are set. It owns parent-directory creation, connection setup, tokio current-thread runtime bridging, synchronous `execute`/`query`/`query_map`, generic migration execution, sync operations (`push`/`pull`/`checkpoint`/`stats`) that are no-ops in local mode (sync is never triggered automatically from `execute()`), and shared DB lifecycle helpers for service-specific database wrappers. Agent Trace persistence now has its own `cli/src/services/agent_trace_db/mod.rs` wrapper, canonical `/sce/agent-trace.db` path, a split fresh-start baseline migration set (`001..005`) covering `diff_traces`, `post_commit_patch_intersections`, `agent_traces`, and indexes (`idx_diff_traces_time_ms_id`, `idx_agent_traces_agent_trace_id`) without `AUTOINCREMENT`, plus `agent_traces.agent_trace_id` as `NOT NULL UNIQUE`; it also provides typed parameterized insert helpers for diff traces, post-commit intersection rows, and built agent-trace rows, chronological recent `diff_traces` query/parse support with malformed-row skip accounting, registered setup/doctor lifecycle provider, active `sce hooks diff-trace` writes for `diff_traces`, and active `sce hooks post-commit` writes for built `agent_traces` payloads. -The hooks command surface now also supports concrete runtime subcommand routing (`pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, `diff-trace`) with deterministic argument/STDIN validation. Current runtime behavior keeps attribution disabled by default: the attribution gate enables canonical trailer insertion in `commit-msg`, `pre-commit`/`post-rewrite` remain deterministic no-ops, `post-commit` is the active bounded recent-diff-trace intersection path, and `diff-trace` is the active intake path for parsed STDIN `{ sessionID, diff, time, model_id, tool_name, tool_version }` payload persistence with required non-empty `tool_name`, required nullable/non-empty `tool_version`, required `u64` millisecond `time`, non-lossy AgentTraceDb `time_ms` conversion, and collision-safe timestamp+attempt artifact filenames. This behavior is documented in `context/sce/agent-trace-hooks-command-routing.md`. +The local DB service now provides `LocalDb` as a thin `TursoDb` alias in `cli/src/services/local_db/mod.rs`; `LocalDbSpec` resolves the canonical local DB path from the shared default-path catalog and currently declares zero migrations. Shared Turso infrastructure lives in `cli/src/services/db/mod.rs`, where `DbSpec` and generic `TursoDb` support dual-mode operation — local mode via `turso::Builder::new_local()` when `SCE_SYNC_URL`+`SCE_SYNC_TOKEN` are absent, or sync (Turso Cloud) mode via `turso::sync::Builder::new_remote()` when both are set. It owns parent-directory creation, connection setup, tokio current-thread runtime bridging, synchronous `execute`/`query`/`query_map`, generic migration execution, sync operations (`push`/`pull`/`checkpoint`/`stats`) that are no-ops in local mode (sync is never triggered automatically from `execute()`), and shared DB lifecycle helpers for service-specific database wrappers. Agent Trace persistence now has its own `cli/src/services/agent_trace_db/mod.rs` wrapper, canonical `/sce/agent-trace.db` path, a split fresh-start baseline migration set (`001..007`) covering `diff_traces`, `post_commit_patch_intersections`, `agent_traces`, nullable `agent_traces.remote_url`, and indexes (`idx_diff_traces_time_ms_id`, `idx_agent_traces_agent_trace_id`, `idx_agent_traces_remote_url`) without `AUTOINCREMENT`, plus `agent_traces.agent_trace_id` as `NOT NULL UNIQUE`; it also provides typed parameterized insert helpers for diff traces, post-commit intersection rows, and built agent-trace rows, chronological recent `diff_traces` query/parse support with malformed-row skip accounting, registered setup/doctor lifecycle provider, active `sce hooks diff-trace` writes for `diff_traces`, and active `sce hooks post-commit` writes for built `agent_traces` payloads. +The hooks command surface now also supports concrete runtime subcommand routing (`pre-commit`, `commit-msg`, `post-commit`, `post-rewrite`, `diff-trace`) with deterministic argument/STDIN validation. Current runtime behavior keeps attribution disabled by default: the attribution gate enables canonical trailer insertion in `commit-msg`, `pre-commit`/`post-rewrite` remain deterministic no-ops, `post-commit` requires validated `--remote-url`, threads that URL into the Agent Trace flow, prints it to stderr, and remains the active bounded recent-diff-trace intersection path, while `diff-trace` is the active intake path for parsed STDIN `{ sessionID, diff, time, model_id, tool_name, tool_version }` payload persistence with required non-empty `tool_name`, required nullable/non-empty `tool_version`, required `u64` millisecond `time`, non-lossy AgentTraceDb `time_ms` conversion, and collision-safe timestamp+attempt artifact filenames. This behavior is documented in `context/sce/agent-trace-hooks-command-routing.md`. The setup service now also exposes deterministic required-hook embedded asset accessors (`iter_required_hook_assets`, `get_required_hook_asset`) backed by canonical templates in `cli/assets/hooks/` for `pre-commit`, `commit-msg`, and `post-commit`; this behavior is documented in `context/sce/setup-githooks-hook-asset-packaging.md`. The setup service now also includes required-hook install orchestration (`install_required_git_hooks`) that resolves repository root and effective hooks path from git truth, enforces deterministic per-hook outcomes (`Installed`/`Updated`/`Skipped`), and uses a unified remove-and-replace policy that removes existing hooks before swapping staged content with deterministic recovery guidance on swap failures; this behavior is documented in `context/sce/setup-githooks-install-flow.md`. The setup command parser/dispatch now also supports composable setup+hooks runs (`sce setup --opencode|--claude|--both --hooks`) plus hooks-only mode (`sce setup --hooks` with optional `--repo `), enforces deterministic compatibility validation (`--repo` requires `--hooks`; target flags remain mutually exclusive), and emits deterministic setup/hook outcome messaging (`installed`/`updated`/`skipped`); this behavior is documented in `context/sce/setup-githooks-cli-ux.md`. diff --git a/context/patterns.md b/context/patterns.md index ba2390e8..dd7360b5 100644 --- a/context/patterns.md +++ b/context/patterns.md @@ -134,7 +134,7 @@ - For cross-service CLI dependencies that will be injected through `AppContext`, prefer broad capability traits in `cli/src/services/capabilities.rs` over one-off per-service abstractions; keep production wrappers thin over `std::fs` and `git` process execution until call-site migration tasks approve deeper service refactors. - For future CLI domains, define trait-first service contracts with request/plan models in `cli/src/services/*` and keep placeholder implementations explicitly non-runnable until production behavior is approved. - Model deferred integration boundaries with concrete event/capability data structures (for example hook-runtime attribution snapshots/policies and cloud-sync checkpoints) so later tasks can implement behavior without reshaping public seams. -- For the current local-hook baseline, keep `pre-commit` and `post-rewrite` as deterministic no-op entrypoints; keep `post-commit` as the active bounded recent-diff-trace intersection entrypoint; keep `diff-trace` as an explicit STDIN intake path with deterministic required-field validation for `sessionID`, `diff`, `time`, `model_id`, `tool_name`, and `tool_version` (present and either `null` or non-empty string), non-lossy AgentTraceDb `time_ms` conversion, collision-safe `context/tmp/-000000-diff-trace.json` persistence using atomic create-new retry semantics, and command-failing AgentTraceDb insertion through the existing database adapter. +- For the current local-hook baseline, keep `pre-commit` and `post-rewrite` as deterministic no-op entrypoints; keep `post-commit` as the active bounded recent-diff-trace intersection entrypoint with validated `--remote-url` plumbed through Agent Trace flow and any direct diagnostics printed to stderr; keep `diff-trace` as an explicit STDIN intake path with deterministic required-field validation for `sessionID`, `diff`, `time`, `model_id`, `tool_name`, and `tool_version` (present and either `null` or non-empty string), non-lossy AgentTraceDb `time_ms` conversion, collision-safe `context/tmp/-000000-diff-trace.json` persistence using atomic create-new retry semantics, and command-failing AgentTraceDb insertion through the existing database adapter. - For commit-msg co-author policy seams, gate canonical trailer insertion on runtime controls (`SCE_DISABLED` plus the shared attribution-hooks enablement gate), and enforce idempotent dedupe so allowed cases end with exactly one `Co-authored-by: SCE ` trailer. - For local hook attribution flows, resolve the top-level enablement gate through the shared config precedence model (`SCE_ATTRIBUTION_HOOKS_ENABLED` over `policies.attribution_hooks.enabled`, default `false`) so commit-msg attribution stays disabled by default without adding hook-specific config parsing. - Do not assume post-commit persistence, retry replay, remap ingestion, or rewrite trace transformation are active in the current local-hook runtime; those paths are removed from the current baseline. diff --git a/context/sce/agent-trace-db.md b/context/sce/agent-trace-db.md index ad930543..556c9dfa 100644 --- a/context/sce/agent-trace-db.md +++ b/context/sce/agent-trace-db.md @@ -16,7 +16,7 @@ pub type AgentTraceDb = TursoDb; - `recent_diff_trace_patches(cutoff_time_ms, end_time_ms)`: chronological `diff_traces` read helper for rows in the inclusive window `time_ms >= cutoff_time_ms AND time_ms <= end_time_ms`; parses raw patch text through `parse_patch` and skips malformed rows without failing the query. - `PostCommitPatchIntersectionInsert<'a>`: insert payload for post-commit intersection results with commit metadata, window bounds, loaded/skipped counts, and serialized patch JSON. - `insert_post_commit_patch_intersection()`: domain-specific insert helper using parameterized SQL. -- `AgentTraceInsert<'a>`: insert payload for built Agent Trace rows with `commit_id`, `commit_time_ms`, serialized `trace_json`, `agent_trace_id`, and non-null `url`. +- `AgentTraceInsert<'a>`: insert payload for built Agent Trace rows with `commit_id`, `commit_time_ms`, serialized `trace_json`, `agent_trace_id`, non-null `url`, and required `remote_url: &'a str` (Rust-API-only; DB column stays nullable). - `insert_agent_trace()`: domain-specific insert helper for `agent_traces` using parameterized SQL. - `lifecycle.rs`: service lifecycle provider for setup/doctor integration. @@ -38,6 +38,8 @@ The Agent Trace DB path is resolved from the shared default-path catalog: - `003_create_agent_traces.sql` - `004_create_diff_traces_time_ms_id_index.sql` - `005_create_agent_traces_agent_trace_id_index.sql` +- `006_add_agent_traces_vcs_remote_url.sql` (historical filename; migration ID `006_add_agent_traces_remote_url` adds the `remote_url` column) +- `007_create_agent_traces_vcs_remote_url_index.sql` (historical filename; migration ID `007_create_agent_traces_remote_url_index` creates `idx_agent_traces_remote_url`) The shared `TursoDb` runner records applied IDs in the database-local `__sce_migrations` table. Existing Agent Trace DB files without metadata are brought forward by re-applying the idempotent migration set and recording each ID, so rerunning `sce setup` / `AgentTraceDb::new()` applies later Agent Trace migrations to an already-created `~/.local/state/sce/agent-trace.db`. @@ -70,6 +72,7 @@ The `agent_traces` baseline migration creates: - `commit_id TEXT NOT NULL` - `commit_time_ms INTEGER NOT NULL` - `url TEXT NOT NULL` +- `remote_url TEXT` (nullable) - `trace_json TEXT NOT NULL` - `agent_trace_id TEXT NOT NULL UNIQUE` - `created_at TEXT NOT NULL DEFAULT (...)` @@ -78,6 +81,7 @@ Lookup indexes created by the baseline migration set: - `idx_diff_traces_time_ms_id` on `(time_ms, id)` - `idx_agent_traces_agent_trace_id` on `(agent_trace_id)` +- `idx_agent_traces_remote_url` on `(remote_url)` ## Lifecycle integration diff --git a/context/sce/agent-trace-hooks-command-routing.md b/context/sce/agent-trace-hooks-command-routing.md index 505c4efa..33322d16 100644 --- a/context/sce/agent-trace-hooks-command-routing.md +++ b/context/sce/agent-trace-hooks-command-routing.md @@ -9,7 +9,7 @@ - `sce hooks pre-commit` - `sce hooks commit-msg ` -- `sce hooks post-commit [--vcs ]` +- `sce hooks post-commit [--vcs ] --remote-url ` - `sce hooks post-rewrite ` - `sce hooks diff-trace` @@ -17,7 +17,9 @@ - `cli/src/app.rs` routes `hooks` through dedicated hook-subcommand parsing. - `cli/src/services/hooks/mod.rs` owns deterministic runtime dispatch through `HookSubcommand` + `run_hooks_subcommand`. -- `post-commit` now parses optional `--vcs` input tolerantly at the command boundary: recognized values (`git|jj|hg|svn`) map to `Some(AgentTraceVcsType)`, while unknown values map to `None` without parse failure. +- `post-commit` now enforces required parse-time validation for `--remote-url` in `cli/src/services/parse/command_runtime.rs`. +- `--vcs` remains optional and, when provided, must be one of `git|jj|hg|svn`; unsupported values fail with a validation-classified error. +- Missing or blank `--remote-url` fails with a validation-classified error before runtime dispatch. - Invalid and ambiguous invocations return deterministic actionable errors pointing to `sce hooks --help`. ## Current runtime behavior @@ -41,14 +43,15 @@ - Persists the serialized intersection result to `post_commit_patch_intersections` table with commit metadata (OID, timestamp), window bounds (cutoff_ms, end_ms), and loaded/skipped counts. - Empty recent patch set produces deterministic empty intersection result (no crash). - Internal orchestration now returns a typed `PostCommitIntersectionFlowResult` (`combined_recent_patch`, `post_commit_data`, optional `tool_name`, optional `tool_version`) from `run_post_commit_intersection_flow_with()`, where tool metadata comes from the most recent ordered parsed recent-patch row and falls back to `None` when the recent set is empty. - - `run_post_commit_subcommand(...)` now threads the parsed optional `vcs_type` through `run_post_commit_agent_trace_flow(...)` into `run_post_commit_agent_trace_flow_with(...)`. -- At the current runtime boundary, optional parsed `vcs_type` is forwarded unchanged into `agent_trace::build_agent_trace(...)`; when absent, the built payload omits top-level `vcs`. +- `run_post_commit_subcommand(...)` now threads parsed optional `vcs_type` and validated `remote_url` through post-commit runtime flow into `run_post_commit_agent_trace_flow_with(...)`. +- `run_post_commit_agent_trace_flow_with(...)` prints the received remote URL to stderr as `post-commit remote_url=` before building/validating/persisting the Agent Trace payload. +- At the current runtime boundary, parsed optional `vcs_type` is forwarded into `agent_trace::build_agent_trace(...)`; when absent, top-level `vcs` metadata is omitted. - The run-flow path maps commit-time metadata to RFC3339 and calls `agent_trace::build_agent_trace(...)`. - The same run-flow call now also forwards optional `tool_name` / `tool_version` from `PostCommitIntersectionFlowResult` into `AgentTraceMetadataInput`, so built post-commit payloads preserve tool metadata derived from recent parsed diff-trace rows. - The built Agent Trace payload includes top-level `metadata.sce.version` from the compiled `sce` CLI package version and range-level `content_hash` values computed from touched post-commit hunk content before conversion to JSON. - The built Agent Trace payload is converted to JSON `Value` and validated via `agent_trace::validate_agent_trace_value(...)` before persistence. - Validation failures are returned through the same post-commit runtime failure path/class used for Agent Trace DB insertion failures (no silent fallback). - - When validation passes, the payload is serialized and inserted into Agent Trace DB `agent_traces` using `commit_id` from flow-result commit metadata, `commit_time_ms` from flow-result post-commit timestamp metadata, and a derived non-null `url` value formatted as `sce.crocoder.dev/trace/`. + - When validation passes, the payload is serialized and inserted into Agent Trace DB `agent_traces` using `commit_id` from flow-result commit metadata, `commit_time_ms` from flow-result post-commit timestamp metadata, a derived non-null `url` value formatted as `sce.crocoder.dev/trace/`, and the validated runtime `--remote-url` value persisted to nullable `agent_traces.remote_url`. - Post-commit Agent Trace success requires both schema validation and Agent Trace DB `agent_traces` persistence to succeed. - Current command-surface success output is: `post-commit hook processed intersection: commit=, intersection_files=`. - `post-rewrite` is a deterministic no-op entrypoint. diff --git a/context/sce/setup-githooks-hook-asset-packaging.md b/context/sce/setup-githooks-hook-asset-packaging.md index 541c9691..93b50280 100644 --- a/context/sce/setup-githooks-hook-asset-packaging.md +++ b/context/sce/setup-githooks-hook-asset-packaging.md @@ -14,9 +14,10 @@ Task `sce-setup-githooks-any-repo` `T02` defines how required git-hook templates These templates are emitted into `OUT_DIR/setup_embedded_assets.rs` as `HOOK_EMBEDDED_ASSETS` with deterministic sorted relative paths. -Current `post-commit` template invocation is: +Current `post-commit` template behavior is: -- `exec sce hooks post-commit --vcs git "$@"` +- set `remote_name` to `origin`; if `git remote get-url "$remote_name"` returns a non-empty URL, invoke `sce hooks post-commit --vcs git --remote-url "$remote_url" "$@"` +- otherwise still invoke `sce hooks post-commit --vcs git "$@"`; Rust-side validation fails this missing-URL path without blocking git commit completion under the hook script policy. ## Setup-service accessor surface