@@ -384,6 +384,122 @@ func TestRun_CursorImporterEndToEnd(t *testing.T) {
384384 }
385385}
386386
387+ // TestRun_StampsImporterGitAuthorOnCheckpointCommit proves an imported
388+ // checkpoint's underlying git commit on entire/checkpoints/v1 carries the
389+ // importer's configured git identity (resolved once per Run via
390+ // checkpoint.GetGitAuthorFromRepo), not an empty signature.
391+ //
392+ // Motivation: on the GitHub->mirror ingestion path, the data plane has no
393+ // pusher identity for imported sessions and falls back to the checkpoint
394+ // commit's git author. An empty author meant imported sessions couldn't be
395+ // attributed to the importer.
396+ func TestRun_StampsImporterGitAuthorOnCheckpointCommit (t * testing.T ) {
397+ t .Parallel ()
398+ repo , repoDir := initRepoWithCommit (t )
399+ claudeDir := t .TempDir ()
400+ writeFixtureSession (t , claudeDir , "sess-author.jsonl" )
401+
402+ res , err := Run (context .Background (), repo , claudeImporter {}, Options {
403+ RepoRoot : repoDir , OverridePath : claudeDir ,
404+ Now : time .Date (2026 , 6 , 25 , 0 , 0 , 0 , 0 , time .UTC ),
405+ })
406+ if err != nil {
407+ t .Fatal (err )
408+ }
409+ if res .TurnsImported != 2 {
410+ t .Fatalf ("want 2 imported, got %+v" , res )
411+ }
412+
413+ stores , err := cp .Open (context .Background (), repo , cp.OpenOptions {})
414+ if err != nil {
415+ t .Fatal (err )
416+ }
417+ ar , ok := stores .Persistent .(cp.AuthorReader )
418+ if ! ok {
419+ t .Fatalf ("persistent store %T does not implement AuthorReader" , stores .Persistent )
420+ }
421+ cid := DeriveCheckpointID ("sess-author" , "u1" )
422+ author , err := ar .GetCheckpointAuthor (context .Background (), cid )
423+ if err != nil {
424+ t .Fatal (err )
425+ }
426+ // initRepoWithCommit uses testutil.InitRepo, which configures this
427+ // repo-local git identity.
428+ const wantName , wantEmail = "Test User" , "test@example.com"
429+ if author .Name != wantName || author .Email != wantEmail {
430+ t .Fatalf ("checkpoint commit author = %+v, want Name=%q Email=%q (the repo's configured git identity)" ,
431+ author , wantName , wantEmail )
432+ }
433+ }
434+
435+ // TestRun_UnconfiguredGitIdentityFallsBackToDefaults proves that when the
436+ // importer's repo has no configured git user (no local or global user.name /
437+ // user.email), the imported checkpoint commit still gets a signature — the
438+ // same "Unknown"/"unknown@local" default checkpoint.GetGitAuthorFromRepo
439+ // already applies elsewhere, rather than an empty one.
440+ func TestRun_UnconfiguredGitIdentityFallsBackToDefaults (t * testing.T ) {
441+ // Cannot use t.Parallel(): isolates HOME via t.Setenv so this repo's
442+ // global git config resolution can't see the developer's real ~/.gitconfig.
443+ home := t .TempDir ()
444+ t .Setenv ("HOME" , home )
445+ t .Setenv ("XDG_CONFIG_HOME" , "" )
446+
447+ repoDir := t .TempDir ()
448+ repo , err := git .PlainInit (repoDir , false )
449+ if err != nil {
450+ t .Fatal (err )
451+ }
452+ // Seed one commit with a real timestamp (the anchor resolver's bounded
453+ // walk stops at commits older than its date cutoff; a zero-value When
454+ // would halt it immediately). The commit's own author signature is
455+ // independent of GetGitAuthorFromRepo's config-based resolution under
456+ // test here.
457+ wt , err := repo .Worktree ()
458+ if err != nil {
459+ t .Fatal (err )
460+ }
461+ testutil .WriteFile (t , repoDir , "f.txt" , "x" )
462+ if _ , err := wt .Add ("f.txt" ); err != nil {
463+ t .Fatal (err )
464+ }
465+ if _ , err := wt .Commit ("init" , & git.CommitOptions {
466+ Author : & object.Signature {Name : "Seed" , Email : "seed@test.com" , When : time .Now ()},
467+ }); err != nil {
468+ t .Fatal (err )
469+ }
470+
471+ claudeDir := t .TempDir ()
472+ writeFixtureSession (t , claudeDir , "sess-noauthor.jsonl" )
473+
474+ res , err := Run (context .Background (), repo , claudeImporter {}, Options {
475+ RepoRoot : repoDir , OverridePath : claudeDir ,
476+ Now : time .Date (2026 , 6 , 25 , 0 , 0 , 0 , 0 , time .UTC ),
477+ })
478+ if err != nil {
479+ t .Fatal (err )
480+ }
481+ if res .TurnsImported != 2 {
482+ t .Fatalf ("want 2 imported, got %+v" , res )
483+ }
484+
485+ stores , err := cp .Open (context .Background (), repo , cp.OpenOptions {})
486+ if err != nil {
487+ t .Fatal (err )
488+ }
489+ ar , ok := stores .Persistent .(cp.AuthorReader )
490+ if ! ok {
491+ t .Fatalf ("persistent store %T does not implement AuthorReader" , stores .Persistent )
492+ }
493+ cid := DeriveCheckpointID ("sess-noauthor" , "u1" )
494+ author , err := ar .GetCheckpointAuthor (context .Background (), cid )
495+ if err != nil {
496+ t .Fatal (err )
497+ }
498+ if author .Name != "Unknown" || author .Email != "unknown@local" {
499+ t .Fatalf ("checkpoint commit author = %+v, want the GetGitAuthorFromRepo defaults" , author )
500+ }
501+ }
502+
387503func TestRun_DryRunWritesNothing (t * testing.T ) {
388504 t .Parallel ()
389505 repo , repoDir := initRepoWithCommit (t )
0 commit comments