Skip to content

feat: add execution context routing - #1

Merged
Namnarak merged 1 commit into
mainfrom
feature/execution-context-routing
Sep 12, 2026
Merged

Namnarak merged 1 commit into
mainfrom
feature/execution-context-routing

Conversation

@Namnarak

Copy link
Copy Markdown
Member

Summary

  • add execution_context=auto|service|user|desktop|system to process execution
  • add a Linux per-login-session bridge so GUI/Polkit/portal/keyring/clipboard children inherit the real session-N.scope
  • preserve root-broker/policy authority for system execution
  • add durable tracking for desktop-session background jobs
  • add XDG autostart packaging, capability/status reporting, docs, and release notes

Validation

  • go test ./...
  • go vet ./...
  • Linux amd64, Darwin amd64, Android arm64 cross-builds
  • make release package validation
  • live Labwc E2E: auto-routed powerprofilesctl child ran in session-7.scope, switched Performance -> Balanced -> Performance without Polkit AccessDenied
  • live bridge rejected a same-UID client whose executable was not CyComAgent

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-12T11:48:09.815578Z 461d2fc PR opened
🔒 Security Review ✅ Completed 2026-09-12T11:51:53.465877Z 461d2fc PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Namnarak
Namnarak merged commit 2eff896 into main Sep 12, 2026
14 checks passed
@Namnarak
Namnarak deleted the feature/execution-context-routing branch September 12, 2026 11:42

@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: 461d2fce83

ℹ️ 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".

if shell == "" {
shell = defaultShell()
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Propagate caller cancellation to bridged processes

When an execution_context=desktop or user request is canceled or its client disconnects before timeout_seconds, the bridge starts the command under context.Background(), so neither the canceled request nor the closed socket stops it. Unlike the service execution path, the handler can remain blocked and the process group continues running for up to the configured timeout (potentially an hour under the default policy); propagate cancellation/disconnection to the bridge and kill the process group.

Useful? React with 👍 / 👎.

Comment on lines +443 to +448
lines := strings.Split(strings.TrimSpace(string(data)), "\n")
for _, line := range lines {
parts := strings.SplitN(line, ":", 3)
if len(parts) == 3 && parts[2] != "" {
return parts[2]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Inspect every cgroup hierarchy for the login session

On cgroup v1 or hybrid Linux systems, /proc/<pid>/cgroup contains multiple controller entries and the session-N.scope path is commonly in the name=systemd entry rather than the first entry. Returning the first nonempty path makes Run conclude that a correctly launched graphical bridge has no login session and refuse to start, disabling all desktop/user routing on those systems; scan all hierarchy paths or select the systemd hierarchy.

Useful? React with 👍 / 👎.

Comment on lines +36 to +39
if runtimeDir := strings.TrimSpace(os.Getenv("XDG_RUNTIME_DIR")); runtimeDir != "" {
return filepath.Join(runtimeDir, "cycomagent-session.sock")
}
return filepath.Join("/run/user", strconv.Itoa(os.Getuid()), "cycomagent-session.sock")

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 Namespace bridge sockets by login session

When one Unix account has multiple simultaneous graphical login sessions, XDG_RUNTIME_DIR and /run/user/<uid> are shared by all of them, so every bridge resolves to the same socket. The second session's bridge therefore exits as “already running,” and desktop commands continue to inherit the first session's display, D-Bus, cgroup, and authorization context rather than the intended active session; use session-specific endpoints and select the appropriate active bridge.

Useful? React with 👍 / 👎.

Comment on lines +111 to +112
if err := json.NewDecoder(io.LimitReader(conn, 24<<20)).Decode(out); err != nil {
return fmt.Errorf("read desktop session bridge response: %w", err)

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 Size the bridge response limit for JSON expansion

When a desktop command emits control characters, quotes, or backslashes near the allowed output limit, JSON escaping can make the response much larger than the raw stdout/stderr buffers; for example, NUL bytes expand to six bytes each. The bridge allows up to 10 MiB independently for stdout and stderr, but the client truncates the encoded response stream at 24 MiB, so even otherwise valid output can produce an unexpected EOF instead of the promised result and truncation metadata; bound the encoded payload or raise/derive this limit from the worst-case escaped size.

Useful? React with 👍 / 👎.

Comment thread internal/jobs/manager.go
Comment on lines +188 to +190
for range ticker.C {
if processAlive(pid) {
continue

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 Track external job process groups instead of only leaders

When a desktop job leaves descendants running after its shell exits, such as sleep 60 & or a GUI program that daemonizes, this monitor tests only the shell PID and immediately records the job as exited-external even though its returned PGID is still alive. That makes job status and health counts incorrect and permits pruning the durable handle/log while the actual session process continues; monitor the process group (and preserve its identity against reuse) until the whole group exits.

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