Skip to content

--include-unattributed is inert: the skip guard compares "" against "_unattributed", so unattributable sessions always import #2353

Description

@chris-conte

Environment

gstack 1.60.1.0 · gbrain 0.42.66.0 (Postgres) · Linux

What happens

buildTranscriptPage stores the raw git remote on the page but writes the fallback into the frontmatter, and the later filter tests the fallback string:

// bin/gstack-memory-ingest.ts:704
const remote = resolveGitRemote(session.cwd);   // returns "" on failure (:681)
// :726 — frontmatter gets the fallback
`git_remote: ${remote || "_unattributed"}`,
// :747 — the page field gets the RAW value
git_remote: remote,
// bin/gstack-memory-ingest.ts:1170
if (!args.includeUnattributed && page.git_remote === "_unattributed") {

page.git_remote is "" whenever the remote could not be resolved, so "" === "_unattributed" is always false and the branch is dead. repoSlug (:687) does apply the fallback, so the slug and frontmatter both read _unattributed — only the guard's input doesn't.

buildArtifactPage gets this right: :784 stores git_remote: slug_repo, the already-defaulted value.

The earlier guard at :1165 (!session.cwd) doesn't cover this — these sessions do have a cwd, it just no longer resolves.

What I expected

With --include-unattributed off (the default), a session whose repo cannot be determined is skipped and counted in skipped_unattributed.

Minimal repro

mkdir -p /tmp/not-a-repo && cd /tmp/not-a-repo
# run any agent session here, then:
gstack-memory-ingest.ts            # no --include-unattributed
# → page transcripts/<agent>/_unattributed/<date>-<id> is imported
# → summary reports "skipped (unattrib): 0"

Why it matters

On one brain, 354 of 650 transcript pages carry git_remote: _unattributed — 54% of the corpus imported against the default policy.

The compounding factor is that the remote is resolved at ingest time from a cwd captured at session time. Of those 354 pages, 333 (94%) point at a directory that no longer exists, and 84 are under worktree paths. Agent sessions that run in ephemeral git worktrees are therefore systematically unattributable: git -C <deleted dir> remote get-url origin throws at :673 and returns "" every time.

The user-facing counter also reads 0 (:1887), so nothing signals that the policy isn't being applied.

Suggested fix

Normalise once, at the source — one line at :747:

git_remote: remote || "_unattributed",

Optionally, recover the attribution instead of discarding it: Claude Code encodes the project directory in the transcript path (~/.claude/projects/<encoded-cwd>/…), which survives worktree deletion and would correctly attribute most of these.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions