Skip to content

P-REPO.1: every session names its repo and where its commits go; spokes start from a repo picker (ADR-0406) - #393

Merged
mlcyclops merged 3 commits into
masterfrom
feat/session-repo-identity
Sep 27, 2026
Merged

mlcyclops merged 3 commits into
masterfrom
feat/session-repo-identity

Conversation

@emertins

@emertins emertins commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Owner request: it is hard to tell which repo a session works on and which GitHub repo its commits go to; in hub and spoke, typing a URL to start a spoke is cumbersome.

What changes

  • Which repo: taken from the session's own tool calls (edits, writes, commands' cwd / cd / git -C), for Main and every lane, replays included. Reads steer only until the first edit. Fallback: the folder's repo.
  • Where commits go: what a bare git push does (branch.pushRemote, remote.pushDefault, upstream remote, origin), URL via git remote get-url --push, parsed credential-free.
  • Shown in: titlebar chip (Main or attached spoke, click for details and Open on GitHub), sidebar workspace bar, grid lane strip, orbit spoke row, hub, spoke banner.
  • Spawn forms (grid New lane, orbit New spoke): searchable repo picker (local checkouts + the user's GitHub repos via gh or a saved token). Old folder / URL fields stay under Other folder or clone URL. Private GitHub picks clone with the gh sign-in.
  • Routes: /api/repo/context, /api/repo/choices, /api/repo/github; LaneView.repo.

Verification

  • make demo-P-REPO.1 (real git in temp repos: push precedence, token never in the view, activity tracking, picker list)
  • desktop/repo_identity.test.ts 15 pass; full bun test 5867 pass, 0 fail; tsc clean (renderer + server configs)
  • Booted engine served the rebuilt bundle; a resumed JanelleSEO session showed JanelleSEO · growth-tools -> emertins/JanelleSEO; a spoke was created from the picker and its card, orbit node, banner and titlebar showed main -> mlcyclops/LUCIDMeetingHub.

ADR-0406: 0402 is P-FLEET.L20 (#391), 0403 P-SWITCH.1 (#392), 0404 P-PROGRESS.1 (not yet in a PR), 0405 P-SCROLL.1 (#394). Master (073755b, #391 + #392) is merged in; conflicts in Makefile and fleet_orbit.ts imports resolved by keeping both sides; full bun test 5881 pass after the merge.

@mlcyclops mlcyclops left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Integration is clean (merged on top of #389, #392 and #391: tsc clean in root, desktop and server configs; the full bun suite passes 5881 / 0 fail; make demo-P-REPO.1 passes). I also drove it live on an isolated engine. The titlebar chip, sidebar bar, spoke banner and orbit node all showed ws · main -> mlcyclops/qa-demo-repo, and the New spoke picker listed the local checkout plus the gh repos. The UX works. Four defects need fixing before merge:

  1. Blocker, security: the engine probes model-named paths on the host before the gate decides. observeToolCall (desktop/repo_probe.ts ~164) takes paths straight from the initial tool_call notification. It then runs stat() (existingDir) and git -C <dir> rev-parse on them in the unsandboxed engine, for any absolute path, and it does this before a tool_call_update can say the call was denied. On Windows, a \\host\share\... path in a denied read makes the engine open SMB to that host as the user, which is the classic NTLM hash leak, and the AppContainer sandbox does not cover it. Confine candidates to the session's workspace plus granted roots (real-path compared), and drop UNC and device paths, before repoRootOf.
  2. cleanToolPath throws on a malformed file:// escape. cleanToolPath("file:///C:/a%zz.ts") throws URIError (reproduced). It runs synchronously inside the tool_call case of AcpBackend's onNotify (acp_backend.ts ~842), before the P-TASK subagent detection and the tool emit, so one bad path drops that tool card. Catch the decode failure and ignore the path.
  3. Lookalike hosts get rewritten to github.com. webUrlFor("github.com-evil.example", "github", "owner", "repo") returns https://github.com/owner/repo (reproduced). The chip says GitHub while pushes go elsewhere, and Open on GitHub opens an unrelated repo. Anchor the alias form (for example ^github\.com-[A-Za-z0-9_]+$, with no dots after the hyphen) or show the real host.
  4. The push target claims a destination where a bare git push refuses. In pushTarget (repo_identity.ts ~122), with the default push.default=simple, a new branch with no upstream makes git push error out. push.default=nothing errors too, and so does a detached HEAD. The chip still names origin/<branch> in all three cases. Return "no push target (set upstream)" for the refusal cases rather than a destination git will not use.

Non-blocking follow-ups:

  • Touches are committed on the initial tool_call, so a denied or failed edit still becomes the active repo. Stage them by toolCallId and apply them on a successful terminal update.
  • All paths in one call share a seq, so the first path wins: a move records oldPath, and cwd beats git -C.

Needs a rebase after #391 merges. Makefile demo targets and the fleet_orbit.ts ui import conflict, and both sides are additive. The import line becomes import { popover, showToast } from "./ui.ts"; plus your two repo imports.

@emertins emertins changed the title P-REPO.1: every session names its repo and where its commits go; spokes start from a repo picker (ADR-0404) P-REPO.1: every session names its repo and where its commits go; spokes start from a repo picker (ADR-0406) Sep 26, 2026
@mlcyclops
mlcyclops merged commit f31a7a0 into master Sep 27, 2026
8 checks passed
mlcyclops added a commit that referenced this pull request Sep 27, 2026
… renumber P-PROGRESS.1 to ADR-0409

Two merged branches (#396 P-SWITCH.2 and #397 P-PROGRESS.1) both claimed ADR-0404;
P-PROGRESS.1 moves to ADR-0409 in DECISIONS.md, the Makefile, PROGRESS.md and its
demo (harness/adr_numbering.test.ts caught it). Version 2.3.0-beta.9 in
desktop/package.json and desktop/version.ts; README beta call, bug template and
HANDOFF refreshed. #351 (desktop dependabot) left out: its Windows test gate failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants