Skip to content

Commit 2c6f833

Browse files
committed
Merge remote-tracking branch 'origin/main' into frontend-auto-compaction-queue
2 parents b184dcf + 3e8ffb8 commit 2c6f833

File tree

70 files changed

+4692
-2495
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+4692
-2495
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
integration-test:
9696
name: Integration Tests
9797
timeout-minutes: 10
98-
runs-on: ${{ github.repository_owner == 'coder' && 'self-hosted' || 'ubuntu-latest' }}
98+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}
9999
steps:
100100
- name: Checkout code
101101
uses: actions/checkout@v4
@@ -104,41 +104,15 @@ jobs:
104104

105105
- uses: ./.github/actions/setup-mux
106106

107-
- name: Check if Ollama is pre-installed
108-
id: check-ollama
109-
run: |
110-
if systemctl is-active --quiet ollama 2>/dev/null && curl -sf http://localhost:11434/api/tags > /dev/null 2>&1; then
111-
echo "installed=true" >> $GITHUB_OUTPUT
112-
echo "✅ Ollama already running (self-hosted runner)"
113-
else
114-
echo "installed=false" >> $GITHUB_OUTPUT
115-
echo "⚙️ Ollama not found, will install"
116-
fi
117-
118-
- name: Setup Ollama
119-
# Only install Ollama if not already running (self-hosted runners have it pre-installed)
120-
if: steps.check-ollama.outputs.installed != 'true'
121-
uses: ./.github/actions/setup-ollama
122-
123-
# Ollama server started by setup-ollama action or pre-installed on self-hosted
124-
# Tests will pull models idempotently
125-
- name: Verify Ollama server
126-
run: |
127-
echo "Verifying Ollama server..."
128-
timeout 5 sh -c 'until curl -sf http://localhost:11434/api/tags > /dev/null 2>&1; do sleep 0.2; done'
129-
echo "Ollama ready - integration tests will pull models on demand"
130-
131107
- name: Build worker files
132108
run: make build-main
133109

134110
- name: Run all integration tests with coverage
135-
# TEST_OLLAMA=1 enables Ollama-specific tests (now included with all integration tests)
136111
# --silent suppresses per-test output (17+ test files × workers = overwhelming logs)
137112
run: TEST_INTEGRATION=1 bun x jest --coverage --maxWorkers=100% --silent ${{ github.event.inputs.test_filter || 'tests' }}
138113
env:
139114
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
140115
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
141-
OLLAMA_BASE_URL: http://localhost:11434/api
142116

143117
- name: Upload coverage to Codecov
144118
uses: codecov/codecov-action@v5

.storybook/preview.tsx

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,13 @@
1-
import React, { useEffect } from "react";
1+
import React from "react";
22
import type { Preview } from "@storybook/react-vite";
3-
import {
4-
ThemeProvider,
5-
useTheme,
6-
type ThemeMode,
7-
} from "../src/browser/contexts/ThemeContext";
3+
import { ThemeProvider, type ThemeMode } from "../src/browser/contexts/ThemeContext";
84
import "../src/browser/styles/globals.css";
95

10-
const ThemeStorySync: React.FC<{ mode: ThemeMode }> = ({ mode }) => {
11-
const { theme, setTheme } = useTheme();
12-
13-
useEffect(() => {
14-
if (theme !== mode) {
15-
setTheme(mode);
16-
}
17-
}, [mode, setTheme, theme]);
18-
19-
return null;
20-
};
21-
226
const preview: Preview = {
237
globalTypes: {
248
theme: {
259
name: "Theme",
2610
description: "Choose between light and dark UI themes",
27-
defaultValue: "dark",
2811
toolbar: {
2912
icon: "mirror",
3013
items: [
@@ -35,12 +18,22 @@ const preview: Preview = {
3518
},
3619
},
3720
},
21+
initialGlobals: {
22+
theme: "dark",
23+
},
3824
decorators: [
3925
(Story, context) => {
40-
const mode = (context.globals.theme ?? "dark") as ThemeMode;
26+
// Default to dark if mode not set (e.g., Chromatic headless browser defaults to light)
27+
const mode = (context.globals.theme as ThemeMode | undefined) ?? "dark";
28+
29+
// Apply theme synchronously before React renders - critical for Chromatic snapshots
30+
if (typeof document !== "undefined") {
31+
document.documentElement.dataset.theme = mode;
32+
document.documentElement.style.colorScheme = mode;
33+
}
34+
4135
return (
42-
<ThemeProvider>
43-
<ThemeStorySync mode={mode} />
36+
<ThemeProvider forcedTheme={mode}>
4437
<Story />
4538
</ThemeProvider>
4639
);
@@ -55,8 +48,8 @@ const preview: Preview = {
5548
},
5649
chromatic: {
5750
modes: {
58-
dark: { globals: { theme: "dark" } },
59-
light: { globals: { theme: "light" } },
51+
dark: { theme: "dark" },
52+
light: { theme: "light" },
6053
},
6154
},
6255
},

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ help: ## Show this help message
112112
@echo 'Usage: make [target]'
113113
@echo ''
114114
@echo 'Available targets:'
115-
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
115+
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
116116

117117
## Development
118118
ifeq ($(OS),Windows_NT)

bun.lock

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
"": {
66
"name": "@coder/cmux",
77
"dependencies": {
8-
"@ai-sdk/anthropic": "^2.0.44",
9-
"@ai-sdk/google": "^2.0.38",
10-
"@ai-sdk/openai": "^2.0.66",
11-
"@ai-sdk/xai": "^2.0.33",
8+
"@ai-sdk/anthropic": "^2.0.47",
9+
"@ai-sdk/google": "^2.0.43",
10+
"@ai-sdk/openai": "^2.0.72",
11+
"@ai-sdk/xai": "^2.0.36",
1212
"@lydell/node-pty": "1.1.0",
13-
"@openrouter/ai-sdk-provider": "^1.2.2",
13+
"@openrouter/ai-sdk-provider": "^1.2.5",
1414
"@radix-ui/react-checkbox": "^1.3.3",
1515
"@radix-ui/react-dialog": "^1.1.15",
1616
"@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -22,7 +22,7 @@
2222
"@radix-ui/react-tabs": "^1.1.13",
2323
"@radix-ui/react-toggle-group": "^1.1.11",
2424
"@radix-ui/react-tooltip": "^1.2.8",
25-
"ai": "^5.0.93",
25+
"ai": "^5.0.101",
2626
"ai-tokenizer": "^1.0.4",
2727
"chalk": "^5.6.2",
2828
"cors": "^2.8.5",
@@ -31,7 +31,7 @@
3131
"disposablestack": "^1.1.7",
3232
"electron-updater": "^6.6.2",
3333
"express": "^5.1.0",
34-
"ghostty-web": "next",
34+
"ghostty-web": "0.2.1",
3535
"jsonc-parser": "^3.3.1",
3636
"lru-cache": "^11.2.2",
3737
"lucide-react": "^0.553.0",
@@ -137,21 +137,21 @@
137137

138138
"@adobe/css-tools": ["@adobe/css-tools@4.4.4", "", {}, "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg=="],
139139

140-
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.44", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-o8TfNXRzO/KZkBrcx+CL9LQsPhx7PHyqzUGjza3TJaF9WxfH1S5UQLAmEw8F7lQoHNLU0IX03WT8o8R/4JbUxQ=="],
140+
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-YioBDTTQ6z2fijcOByG6Gj7me0ITqaJACprHROis7fXFzYIBzyAwxhsCnOrXO+oXv+9Ixddgy/Cahdmu84uRvQ=="],
141141

142-
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@vercel/oidc": "3.0.3" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-c++qOKfjKokTPAJ+vP9UXXNuTQ819yEDCZVXBhpZbgRly1P4fHTJbIAwuh+Qxxe9Bmtu8PEta0JGYZxc+hm7/Q=="],
142+
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.15", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-i1YVKzC1dg9LGvt+GthhD7NlRhz9J4+ZRj3KELU14IZ/MHPsOBiFeEoCCIDLR+3tqT8/+5nIsK3eZ7DFRfMfdw=="],
143143

144-
"@ai-sdk/google": ["@ai-sdk/google@2.0.38", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z+RFCxRA/dSd3eCkGBlnk79nz3jv8vwaW42gVc+qDuMofNfvjRz19rjnkFNuYQ6cEUcPKCo0P1rD/JLeTN2Z5A=="],
144+
"@ai-sdk/google": ["@ai-sdk/google@2.0.43", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qO6giuoYCX/SdZScP/3VO5Xnbd392zm3HrTkhab/efocZU8J/VVEAcAUE1KJh0qOIAYllofRtpJIUGkRK8Q5rw=="],
145145

146-
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.68", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qUSLFkqgUoFArzBwttu0KWVAZYjbsdZGOklSJXpfZ2nDC61yseHxtcnuG8u6tqKnGXDh4eakEgREDWU2sRht7A=="],
146+
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.72", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9j8Gdt9gFiUGFdQIjjynbC7+w8YQxkXje6dwAq1v2Pj17wmB3U0Td3lnEe/a+EnEysY3mdkc8dHPYc5BNev9NQ=="],
147147

148148
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.27", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bpYruxVLhrTbVH6CCq48zMJNeHu6FmHtEedl9FXckEgcIEAi036idFhJlcRwC1jNCwlacbzb8dPD7OAH1EKJaQ=="],
149149

150150
"@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="],
151151

152152
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="],
153153

154-
"@ai-sdk/xai": ["@ai-sdk/xai@2.0.33", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.27", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-0+S+hxbAj8dA8/3dYQsmgkVkPcs8yptO1ueLWtJpa6PYjrdyliDcPSCZREL8aE76vHGvFsYlRABFfH9Ps2M8tg=="],
154+
"@ai-sdk/xai": ["@ai-sdk/xai@2.0.36", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.27", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tQuCDVNK4W4fiom59r2UnU7u9SAz58fpl5yKYoS9IbMOrDRO3fzQGWmj2p8MUvz9LzXf6hiyUkVNFGzzx+uZcw=="],
155155

156156
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
157157

@@ -523,7 +523,7 @@
523523

524524
"@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="],
525525

526-
"@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@1.2.3", "", { "dependencies": { "@openrouter/sdk": "^0.1.8" }, "peerDependencies": { "ai": "^5.0.0", "zod": "^3.24.1 || ^v4" } }, "sha512-a6Nc8dPRHakRH9966YJ/HZJhLOds7DuPTscNZDoAr+Aw+tEFUlacSJMvb/b3gukn74mgbuaJRji9YOn62ipfVg=="],
526+
"@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@1.2.5", "", { "dependencies": { "@openrouter/sdk": "^0.1.8" }, "peerDependencies": { "ai": "^5.0.0", "zod": "^3.24.1 || ^v4" } }, "sha512-NrvJFPvdEUo6DYUQIVWPGfhafuZ2PAIX7+CUMKGknv8TcTNVo0TyP1y5SU7Bgjf/Wup9/74UFKUB07icOhVZjQ=="],
527527

528528
"@openrouter/sdk": ["@openrouter/sdk@0.1.11", "", { "dependencies": { "zod": "^3.25.0 || ^4.0.0" }, "peerDependencies": { "@tanstack/react-query": "^5", "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["@tanstack/react-query", "react", "react-dom"] }, "sha512-OuPc8qqidL/PUM8+9WgrOfSR9+b6rKIWiezGcUJ54iPTdh+Gye5Qjut6hrLWlOCMZE7Z853gN90r1ft4iChj7Q=="],
529529

@@ -1085,7 +1085,7 @@
10851085

10861086
"@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="],
10871087

1088-
"@vercel/oidc": ["@vercel/oidc@3.0.3", "", {}, "sha512-yNEQvPcVrK9sIe637+I0jD6leluPxzwJKx/Haw6F4H77CdDsszUn5V3o96LPziXkSNE2B83+Z3mjqGKBK/R6Gg=="],
1088+
"@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
10891089

10901090
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
10911091

@@ -1115,7 +1115,7 @@
11151115

11161116
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
11171117

1118-
"ai": ["ai@5.0.94", "", { "dependencies": { "@ai-sdk/gateway": "2.0.10", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-PQs3H8xDhORG/L6eyR+SxAKUsa0ORO4ENvRovzGgPmPGCIlwle6UD5VIMQFtj1gvZk+BKBUVEFFwtkTeJTAURw=="],
1118+
"ai": ["ai@5.0.101", "", { "dependencies": { "@ai-sdk/gateway": "2.0.15", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/P4fgs2PGYTBaZi192YkPikOudsl9vccA65F7J7LvoNTOoP5kh1yAsJPsKAy6FXU32bAngai7ft1UDyC3u7z5g=="],
11191119

11201120
"ai-tokenizer": ["ai-tokenizer@1.0.4", "", { "peerDependencies": { "ai": "^5.0.0" }, "optionalPeers": ["ai"] }, "sha512-BHOUljsmH0SEO9bULQL3sz6pJ4jv00r+NHxX3kR6tn1suAAj6DDN4njSk+sqCOI5Cm6FqizUhDfoYZ0R+5/WVQ=="],
11211121

@@ -1789,7 +1789,7 @@
17891789

17901790
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
17911791

1792-
"ghostty-web": ["ghostty-web@0.2.1-next.3.g5e035a2", "", { "bin": { "ghostty-web": "bin/ghostty-web.js" } }, "sha512-iQFTRn3N3+yZJkr2AA3EUpDglL/Vyc2BiPfJuOBHt7b+JyrjLPJxIU37fsf/2+WnS9y0yFvMI3WAPrkGPA2iBw=="],
1792+
"ghostty-web": ["ghostty-web@0.2.1", "", {}, "sha512-wrovbPlHcl+nIkp7S7fY7vOTsmBjwMFihZEe2PJe/M6G4/EwuyJnwaWTTzNfuY7RcM/lVlN+PvGWqJIhKSB5hw=="],
17931793

17941794
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
17951795

docs/AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ gh pr view <number> --json mergeable,mergeStateStatus | jq '.'
2222
- Status decoding: `mergeable=MERGEABLE` clean; `CONFLICTING` needs resolution. `mergeStateStatus=CLEAN` ready, `BLOCKED` waiting for CI, `BEHIND` rebase, `DIRTY` conflicts.
2323
- If behind: `git fetch origin && git rebase origin/main && git push --force-with-lease`.
2424
- Never enable auto-merge or merge at all unless the user explicitly says "merge it".
25+
- Do not enable auto-squash or auto-merge on Pull Requests unless explicit permission is given.
2526
- PR descriptions: include only information a busy reviewer cannot infer; focus on implementation nuances or validation steps.
2627
- Title prefixes: `perf|refactor|fix|feat|ci|bench`, e.g., `🤖 fix: handle workspace rename edge cases`.
2728

@@ -155,3 +156,7 @@ gh pr view <number> --json mergeable,mergeStateStatus | jq '.'
155156

156157
- When Plan Mode is requested, assume the user wants the actual completed plan; do not merely describe how you would devise one.
157158
- Attach a net LoC estimate (product code only) to each recommended approach.
159+
160+
## Tool: status_set
161+
162+
- Set status url to the Pull Request once opened

0 commit comments

Comments
 (0)