Skip to content

Key amikalog sessions by repo remote path, not basename - #277

Open
jdc123 wants to merge 1 commit into
mainfrom
amika/amikalog-repo-names
Open

Key amikalog sessions by repo remote path, not basename#277
jdc123 wants to merge 1 commit into
mainfrom
amika/amikalog-repo-names

Conversation

@jdc123

@jdc123 jdc123 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

amikalog beta:push filed each session in the org storage bucket under its
repo-root basename (e.g. amika). Two different repositories that share a
directory name — say github.com/acme/api and github.com/other/api, both
cloned as api — collided under the same bucket prefix.

This keys each session by the repository's full origin remote instead, so the
identity is globally unique.

Changes (go/internal/eventlog/)

  • Capture the remote. GatherGit now also runs git remote get-url origin
    and records it in a new git.remote field on GitInfo, normalized to
    host/owner/repo. normalizeRemoteURL understands the https://, ssh://,
    git://, and scp-like git@host:owner/repo forms, stripping the scheme, any
    credentials, a port, and a trailing .git. Empty for a repo with no origin.

  • New object-key layout. beta:push now files sessions under
    <repo-path>/sessions/<source>/<ts>_<session-id>.jsonl, where <repo-path>
    is the captured remote nested as folders:

    before:  amika/claude/sessions/<ts>_<sess>.jsonl
    after:   github.com/acme/amika/sessions/claude/<ts>_<sess>.jsonl
    
  • Fallbacks preserved. A repo with no origin remote falls back to its
    directory basename; a session with no git context at all to unknown-repo.
    The resolver prefers a git.remote from any event, so a session that
    straddles this change is still filed by remote once one appears.

  • Segment sanitizing. Each key segment is sanitized; : was added to the
    banned set because beta:fetch recreates the key tree on disk and : is an
    illegal filename byte on Windows.

Backward compatibility

  • On-disk layout is unchanged — this only affects the bucket object key.
  • No re-keying, no duplicates. A session's key is pinned in the push
    manifest on first upload, so sessions already pushed under the old layout keep
    their key; the new layout applies only to sessions pushed from here on. The
    bucket will hold a mix during the transition, which is expected and safe.
  • Legacy per-event event_*.json files still upload under the new layout too.

Testing

  • make lint, go vet, go build ./..., gofmt — all clean.
  • go test ./internal/eventlog/ passes, including a new
    TestPush_JSONLNestedRepoPathFromRemote (two same-basename repos land at
    distinct nested keys) and a normalizeRemoteURL table test covering every URL
    form plus file://, bare paths, and host-only input.
  • Verified the normalizer against this repo's real origin: all three URL forms
    resolve to github.com/gofixpoint/amika.

Docs

  • docs/amikalog.md — the git field row and the object-key section.
  • AGENTS.md — the eventlog package summary.

🤖 Generated with Claude Code

beta:push filed each session under its repo-root basename (e.g. `amika`),
so two different checkouts that share a directory name collided in the org
bucket. Capture the repository's `origin` remote, normalized to
`host/owner/repo`, in a new `git.remote` field and use it as the object
key, nested as folders with `sessions/<source>` after it:

    before:  amika/claude/sessions/<ts>_<sess>.jsonl
    after:   github.com/acme/amika/sessions/claude/<ts>_<sess>.jsonl

normalizeRemoteURL understands the https://, ssh://, git://, and scp-like
`git@host:owner/repo` forms, stripping the scheme, credentials, port, and
trailing `.git`. A repo with no `origin` falls back to its directory
basename, and a session with no git context to `unknown-repo`.

Session keys are pinned on first push, so sessions already uploaded under
the old layout keep their key; nothing is re-keyed or duplicated, and the
new layout applies to sessions pushed from here on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22afc7e236

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
return strings.ToLower(path.Join(repoSeg, u.relKey))
tail := strings.TrimPrefix(u.relKey, string(u.source)+"/sessions/")
return strings.ToLower(path.Join(repoPath, "sessions", string(u.source), tail))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve legacy object keys for size-only manifests

When a user has a manifest entry in the bare byte-size form that UnmarshalJSON still accepts, entry.ObjectKey is empty. If that already-uploaded session grows after upgrading, this new key builder uploads it to <repo-path>/sessions/<source>/... instead of the old <repo>/<source>/sessions/... key that the size-only manifest entry refers to, leaving the old object stale and creating a duplicate/incomplete session tree in beta:fetch. Populate the legacy object key when migrating size-only entries, or otherwise reconstruct the old layout for those entries before switching to the new layout.

Useful? React with 👍 / 👎.

Comment on lines +69 to +73
colon := strings.IndexByte(s, ':')
if colon < 0 {
return ""
}
host, remotePath = stripUserinfo(s[:colon]), s[colon+1:]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Treat Windows drive remotes as local paths

For a local origin such as C:\src\repo or C:/src/repo on Windows, git remote get-url origin returns a drive-letter path. This scp-like branch treats the drive colon as a host/path separator, so GatherGit records Remote as a C/... path and beta:push files the session under that local path prefix instead of falling back to the repo basename; it can also expose local checkout paths in shared storage. Check for drive-letter/local paths before treating a colon as scp syntax.

Useful? React with 👍 / 👎.

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.

1 participant