From 024485f050bfaa7de1f746a1fb23fa3ba84edaf3 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sat, 9 May 2026 21:10:02 +0200 Subject: [PATCH] feat(traceability): append SF-Session id to autonomous commit messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - git-service.js autoCommit() accepts optional sessionId param - Appends 'SF-Session: ' trailer to commit message when present - Falls through cleanly when sessionId is undefined (quick tasks, templates) - worktree.js autoCommitCurrentBranch() forwards sessionId - auto-post-unit.js autoCommitUnit() reads session ID from getAutoSession() via s.cmdCtx?.sessionManager?.getSessionId?.() — same pattern as auto.js Mirrors Copilot's session logs linked to each commit for cross-session traceability. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/resources/extensions/sf/auto-post-unit.js | 3 +++ src/resources/extensions/sf/git-service.js | 5 +++-- src/resources/extensions/sf/worktree.js | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/resources/extensions/sf/auto-post-unit.js b/src/resources/extensions/sf/auto-post-unit.js index e7d0fa6ad..aa2b8aee0 100644 --- a/src/resources/extensions/sf/auto-post-unit.js +++ b/src/resources/extensions/sf/auto-post-unit.js @@ -165,6 +165,7 @@ import { join } from "node:path"; import { describeNextUnit } from "./auto-dashboard.js"; import { _resetHasChangesCache } from "./native-git-bridge.js"; import { autoCommitCurrentBranch } from "./worktree.js"; +import { getAutoSession } from "./auto/session.js"; /** * Detect summary files written directly to disk without the LLM calling @@ -336,11 +337,13 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) { if (LIFECYCLE_ONLY_UNITS.has(unitType)) { return null; } + const sessionId = getAutoSession().cmdCtx?.sessionManager?.getSessionId?.() ?? null; const commitMsg = autoCommitCurrentBranch( basePath, unitType, unitId, taskContext, + sessionId, ); if (commitMsg) { ctx?.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info"); diff --git a/src/resources/extensions/sf/git-service.js b/src/resources/extensions/sf/git-service.js index 607d5f714..ace1db004 100644 --- a/src/resources/extensions/sf/git-service.js +++ b/src/resources/extensions/sf/git-service.js @@ -504,7 +504,7 @@ export class GitServiceImpl { * Returns the commit message on success, or null if nothing to commit. * @param extraExclusions Additional paths to exclude from staging (e.g. [".sf/"] for pre-switch commits). */ - autoCommit(unitType, unitId, extraExclusions = [], taskContext) { + autoCommit(unitType, unitId, extraExclusions = [], taskContext, sessionId) { // Quick check: is there anything dirty at all? // Native path uses libgit2 (single syscall), fallback spawns git. if (!nativeHasChanges(this.basePath)) return null; @@ -512,9 +512,10 @@ export class GitServiceImpl { // After smart staging, check if anything was actually staged // (all changes might have been runtime files that got excluded) if (!nativeHasStagedChanges(this.basePath)) return null; - const message = taskContext + const base = taskContext ? buildTaskCommitMessage(taskContext) : `chore: auto-commit after ${unitType}\n\nSF-Unit: ${unitId}`; + const message = sessionId ? `${base}\nSF-Session: ${sessionId}` : base; nativeCommit(this.basePath, message, { allowEmpty: false }); // Absorb any preceding sf snapshot commits into this real commit. // Walk backwards from HEAD~1 counting consecutive snapshot subjects, diff --git a/src/resources/extensions/sf/worktree.js b/src/resources/extensions/sf/worktree.js index 0b3d1584b..c782e5bab 100644 --- a/src/resources/extensions/sf/worktree.js +++ b/src/resources/extensions/sf/worktree.js @@ -281,8 +281,9 @@ export function autoCommitCurrentBranch( unitType, unitId, taskContext, + sessionId, ) { - return getService(basePath).autoCommit(unitType, unitId, [], taskContext); + return getService(basePath).autoCommit(unitType, unitId, [], taskContext, sessionId); } // ─── Git HEAD Resolution ──────────────────────────────────────────────────── /**