Session Git — Concurrent Lanes (Spec & Rollout Plan)
Normative model for multiple sessions sharing branches; supersedes rigid one-session-one-branch wording in SAGP v1.2 §2 where it conflicts.
Session Git — Concurrent Lanes
1. Purpose
Align written process, tooling, and day-to-day practice. SAGP v1.2 still reads as one session → one branch (session-{N}). In production, teams routinely run 2–4 concurrent sessions on the same branch (often a range name such as session-264-269_new). That is valid; the doc and some checks were wrong, not the workflow.
This document is the authoritative spec for branch/session semantics. SAGP v1.3 (sessions-git-protocol.mdc) incorporates these rules by reference.
2. Problem statement
| Issue | Impact |
|---|---|
INIT steps say “expected branch = session-{N}” |
False failures in MCP preflight / agent confusion |
| “One branch per session” | Contradicts shared long-lived range branches |
| “Never commit to another session’s branch” | Misread as “one session per branch” instead of “don’t land unrelated work without attribution” |
What was always correct: [S{N}.{sub}] commit tags, explicit git add <files>, stash naming, and not working directly on main.
3. Target model (normative)
3.1 Definitions
- Session — A numbered unit of work (manifest
S{N}.json, MCPsessionNumber, history entries). - Branch lane — A Git branch used as a shared integration line for one or more sessions over time.
- Range branch — A lane whose name encodes a span (e.g.
session-264-269,session-264-269_new). It may intentionally correspond to multiple session IDs in that range. - Attribution — Per commit, via
[S{N}.{sub}]. The branch name does not uniquely identify a single session when multiple sessions share the lane.
3.2 Rules (replace rigid §2 branch rules)
- Many sessions MAY share one branch. Prefer one stable lane over spawning redundant
session-{N}branches when work is tightly coupled or concurrent. - Branch name = coarse scope, not ownership. It answers: “Which line of history / integration bucket?” not “who owns every commit.”
- Commit message = fine-grained ownership. Every commit MUST remain tagged with
[S{N}.{sub}]for the session that owns that change. - Preflight / MCP “synced” means: current branch plausibly relates to the enforced session (e.g. range token includes
N; optional cross-check against that session’s manifestgitBranchif present). It does not meanHEADmust equal onlysession-{N}. - Do not mix unrelated work without tagging. If you touch files for session B while on a lane also used for session A, split commits or clear
[S{B}.{sub}]on those commits — same as today; the rule is attribution, not branch exclusivity. main— unchanged: no direct commits; merge via PR or controlled merge policy.
3.2a Boundary: what changes vs what does not
| Stays the same | Changes only here |
|---|---|
sessions/manifests/S{N}.json — one file per session, session-scoped data only (schema, fields, progress as today) |
How Git is used: shared lanes, range branches, MCP branch policy, INIT wording |
Sub-session records may still include gitBranch as today (audit of which lane that sub-session used) |
Conflict avoidance = attribution ([S{N}.{sub}]), explicit git add, not “one branch per session” |
No new manifest fields are required for concurrent lanes. No aggregating multiple sessions into one manifest.
3.3 Naming conventions (flexible, not exhaustive)
| Pattern | Use when |
|---|---|
session-{N} |
Single-session lane or legacy; still allowed |
session-{A}-{B} / session-{A}-{B}_{suffix} |
Range / multi-session lane (common case: shared integration line for several sessions) |
Dropped from this spec: integrate/{N}-{M} disposable branches. Range lanes already act as the integration line for concurrent work; merging to main is the remaining integration step (PR / policy). If someone ever needs a throwaway pre-main combine, they can use any local branch name—no separate convention required.
Non-goals: Mandating a single global pattern for all repos; teams may keep local variants if attribution rules hold.
3.4 Manifests (sessions/manifests/S{N}.json)
- Unchanged: Each manifest remains only data for session N (per existing schema and team conventions).
gitBranchon sub-sessions (as today) — Optional audit of which lane that sub-session used; tooling may read it for hints, but Git flexibility does not depend on new manifest fields.
3.5 PRs and merges to main (resolved)
Decision: Yes — merge-related metadata must preserve session traceability.
- PR title — Include at least one
[S{N}.{sub}]tag (typically the primary session driving the PR). If several sessions share the lane with similar weight, use one tag in the title and list the rest in the description (e.g. “Also: [S268.2][S267.1]”). - Merge commit message (merge commits, or squash subject/body) — Include
[S{N}.{sub}]for every session that contributed material commits in that PR, or a single line such asSessions: S269.3, S268.2, S267.1sogit logremains grep-friendly. - Squash-merge — Default squash subject should carry the lead session tag; squash body should list other
[S*]tags copied from commits if multiple sessions are in the branch.
This keeps main history searchable by session tag without changing manifest layout.
3.6 Release notes / changelog (resolved)
Approach: Prefer automation from Git, not new manifest fields.
- Technical “what merged” —
git logonmainwith session tags ([S\d+(?:\.\d+)?\]) is the canonical list; scripts can group by session number. - User-facing changelog — Generate draft bullets from tagged merge/PR lines, then edit for readability; optional deep links to
docs/english/sessions/...or manifest titles read as reference (manifests stay per-session; they are not merged into a mega-file). - No requirement to mirror every commit in manifests; manifests remain session journals, not release registers.
4. Tooling expectations
| Layer | Behavior |
|---|---|
| Git | Source of truth for objects; branch is a pointer; tags in messages are authoritative for session attribution. |
| MCP preflight | Default multi-session branch policy (range-aware); MCP_GIT_BRANCH_POLICY=strict only if you want legacy session-{N}-only matching. |
| Git gateway / safe_commit | Same matcher as preflight; still enforces [S{N}.{sub}] and explicit file lists. |
| CI (future) | Optional: verify commit messages match regex ^\[S\d+(?:\.\d+)?\] on protected branches. |
5. Non-goals
- Replacing Git or commit tags with branch-only identity.
- Automatic inference of “which session” from branch name alone on shared lanes.
- Forcing one branch per developer or one branch per machine.
- Changing
sessions/manifests/S{N}.jsonschema or collapsing multiple sessions into one manifest — Git/process only.
6. Rollout plan
Phase 0 — Decisions (owner: you / tech lead)
- Accept concurrent-lanes as official; SAGP v1.3 + this spec published.
- Default MCP policy: multi-session (implemented in MCP);
strictis opt-in viaMCP_GIT_BRANCH_POLICY. - Manifests: keep per-session only; no schema change for concurrent lanes (see §3.2a).
Phase 1 — Documentation (high priority)
- Update
sessions-git-protocol.mdc: v1.3 — INIT, §2, §5, §8–§10, §13 flow, §14 replacesintegrate/*. -
AGENTS.md/CLAUDE.md— concurrent lanes + link to this spec. - This file status: active.
Phase 2 — Tooling polish (optional)
- Optional:
yarn session:checksoft-warning if currentgit branchdoes not reference enforced session (same heuristic as MCP multi-session policy), without requiring manifest schema changes. - Optional: script to draft release notes from
git log main --grep='\\[S'(or equivalent) grouped by session tag.
Phase 3 — Agent / human training
- Short internal note for agents: “Wrong branch” = attribution risk, not “branch string ≠ session-{N}.”
- Code review checklist: shared lane ⇒ verify commit tag matches owning session.
Phase 4 — Cleanup
- Archive or redirect any old diagrams/docs that show only
session-{N}. - Prune stale local branches (operational, not spec).
7. Success criteria
- Agents stop receiving false “branch mismatch” when on a valid range / shared lane.
- Written protocol matches how 2–4 concurrent sessions actually work.
- Attribution remains traceable via
[S{N}.{sub}]on every meaningful commit.
8. Resolved decisions (formerly open questions)
| Topic | Decision |
|---|---|
| PR / merge tagging | Yes — see §3.5 (titles + merge/squash messages carry [S{N}.{sub}] or an explicit session list). |
| Release / changelog | §3.6 — derive from Git (main log + tags); user-facing text is edited drafts; manifests stay per-session journals, not release databases. |
9. Revision history
| Version | Date | Notes |
|---|---|---|
| 1.0 draft | 2026-03-25 | Initial spec + plan |
| 1.1 draft | 2026-03-25 | Removed integrate/{N}-{M}; range lanes + merge to main replace that pattern |
| 1.2 draft | 2026-03-25 | §3.2a manifest boundary; §3.5–3.6 PR/changelog; no manifest schema changes; Phase 2 retargeted |
| 1.3 | 2026-03-25 | active — merged into SAGP v1.3, AGENTS.md, CLAUDE.md |