diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index c95cd52dda4..491d0cac794 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -112,7 +112,6 @@ All stable kinds (`patch`, `minor`, `major`) are computed off the latest _stable
The scheduled 2x/day RC cron in [`release-rc.yml`](../../actions/workflows/release-rc.yml) is independent and continues to run automatically from `main`.
-
## Release Channels
The public Homebrew cask tracks stable desktop releases:
diff --git a/.github/workflows/daily-mac-build.yml b/.github/workflows/daily-mac-build.yml
index e445045e67c..2ef3baed2fd 100644
--- a/.github/workflows/daily-mac-build.yml
+++ b/.github/workflows/daily-mac-build.yml
@@ -308,7 +308,6 @@ jobs:
echo "tag=$TAG" >>"$GITHUB_OUTPUT"
echo "notes_file=$notes_file" >>"$GITHUB_OUTPUT"
-
- name: Publish daily macOS artifacts
if: steps.freshness.outputs.should_build == 'true'
uses: nick-fields/retry@v4
diff --git a/.github/workflows/hourly-mac-build.yml b/.github/workflows/hourly-mac-build.yml
index 16e2f05579c..e072b0f9a10 100644
--- a/.github/workflows/hourly-mac-build.yml
+++ b/.github/workflows/hourly-mac-build.yml
@@ -290,7 +290,6 @@ jobs:
including back to Stable, works in-app from there."
echo "tag=$TAG" >>"$GITHUB_OUTPUT"
-
- name: Publish hourly macOS artifacts
if: steps.freshness.outputs.should_build == 'true'
uses: nick-fields/retry@v4
diff --git a/.github/workflows/pullfrog.yml b/.github/workflows/pullfrog.yml
index 19401170c0e..d5030252f88 100644
--- a/.github/workflows/pullfrog.yml
+++ b/.github/workflows/pullfrog.yml
@@ -34,8 +34,7 @@ jobs:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- GOOGLE_GENERATIVE_AI_API_KEY:
- ${{ secrets.GOOGLE_GENERATIVE_AI_API_KEY }}
+ GOOGLE_GENERATIVE_AI_API_KEY: ${{ secrets.GOOGLE_GENERATIVE_AI_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
diff --git a/.github/workflows/release-cut.yml b/.github/workflows/release-cut.yml
index c035080a203..af0fe9b45ba 100644
--- a/.github/workflows/release-cut.yml
+++ b/.github/workflows/release-cut.yml
@@ -844,6 +844,16 @@ jobs:
with:
ref: refs/tags/${{ needs.cut.outputs.tag }}
+ - name: Restore golden test harness from the workflow ref
+ shell: bash
+ env:
+ WORKFLOW_SHA: ${{ github.workflow_sha }}
+ run: |
+ git fetch --no-tags --depth=1 origin "$WORKFLOW_SHA"
+ git checkout "$WORKFLOW_SHA" -- \
+ tests/e2e/golden-source-control-open-diff.spec.ts \
+ tests/e2e/golden-terminal-file-link.spec.ts
+
- name: Install native build tools
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y build-essential python3 xvfb
@@ -946,6 +956,16 @@ jobs:
with:
ref: refs/tags/${{ needs.cut.outputs.tag }}
+ - name: Restore skill-sharing test harness from the workflow ref
+ shell: bash
+ env:
+ WORKFLOW_SHA: ${{ github.workflow_sha }}
+ run: |
+ git fetch --no-tags --depth=1 origin "$WORKFLOW_SHA"
+ git checkout "$WORKFLOW_SHA" -- \
+ src/main/skills/skill-freshness-inventory.test.ts \
+ src/main/skills/skill-provider-runtime-roots.test.ts
+
- uses: ./.github/actions/install-node-dependencies
with:
native-runtime: node
@@ -978,13 +998,26 @@ jobs:
steps:
- name: Install Ubuntu 20.04 prerequisites
- run: apt-get update && apt-get install -y build-essential ca-certificates git python3
+ run: apt-get update && apt-get install -y build-essential ca-certificates git python3 unzip
- name: Checkout
uses: actions/checkout@v6
with:
ref: refs/tags/${{ needs.cut.outputs.tag }}
+ - name: Trust the checked-out workspace in the job container
+ run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
+
+ - name: Restore skill-sharing test harness from the workflow ref
+ shell: bash
+ env:
+ WORKFLOW_SHA: ${{ github.workflow_sha }}
+ run: |
+ git fetch --no-tags --depth=1 origin "$WORKFLOW_SHA"
+ git checkout "$WORKFLOW_SHA" -- \
+ src/main/skills/skill-freshness-inventory.test.ts \
+ src/main/skills/skill-provider-runtime-roots.test.ts
+
- uses: ./.github/actions/install-node-dependencies
with:
native-runtime: node
diff --git a/AGENTS.md b/AGENTS.md
index 307c975d219..1fbce202438 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -7,13 +7,15 @@ All UI work — layout, color, typography, spacing, component selection, UX beha
Use the `$electron` skill and Playwright CDP for rendered Orca UI checks. Do not use computer-use for Orca UI validation.
# Style
+
## Reuse Before Reimplementing
Before writing new logic at any scale — a function, component, IPC channel, state store, or whole subsystem/flow — check whether an existing implementation already does the job (or nearly does). Extend or generalize it instead of building a parallel version; only write from scratch when nothing fits. Keep the check proportionate: a quick search for trivial code, a real one before building anything substantial.
## Concise/Brief Non-obvious Comments ONLY
- * DO NOT: be verbose, explain the obvious, walk through the code ("WHY not HOW")
- * BE CONCISE. 1 LINE if possible
+
+- DO NOT: be verbose, explain the obvious, walk through the code ("WHY not HOW")
+- BE CONCISE. 1 LINE if possible
## Lint Rules: Do Not Disable Max Lines
@@ -32,6 +34,7 @@ Never use vague names like `helpers`, `utils`, `common`, `misc`, or `shared-stuf
- **Lint**: `oxlint`, or `pnpm run check:code-quality:changed` for changed files (full `pnpm lint` is slow); format with `pnpm format`
# Considerations
+
## Worktree Safety
Always use the primary working directory (the worktree) for all file reads and edits. Never follow absolute paths from subagent results that point to the main repo.
diff --git a/README.md b/README.md
index 8de0ff8d2b9..82dfdbaa5c9 100644
--- a/README.md
+++ b/README.md
@@ -262,6 +262,7 @@ Want to contribute or run locally? See our [CONTRIBUTING.md](.github/CONTRIBUTIN
## Signed Builds
+
Windows code signing sponored/provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org).
## License
diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc
index 02bd0b02bc2..77e9d6e79ed 100644
--- a/config/reliability-gates.jsonc
+++ b/config/reliability-gates.jsonc
@@ -2148,9 +2148,7 @@
},
{
"file": "src/cli/runtime/serve-signal-exit-diagnostic.test.ts",
- "assertions": [
- "late update handoff failure cannot rearm termination after child exit"
- ]
+ "assertions": ["late update handoff failure cannot rearm termination after child exit"]
},
{
"file": "src/main/serve-update-handoff.test.ts",
@@ -16840,9 +16838,7 @@
},
{
"file": "src/main/browser/agent-browser-bridge-tab-routing.test.ts",
- "assertions": [
- "closing a tab retires the exact named agent-browser session"
- ]
+ "assertions": ["closing a tab retires the exact named agent-browser session"]
},
{
"file": "src/main/startup/serve-signal-handlers.test.ts",
diff --git a/config/scripts/build-orcad-prebuilds.mjs b/config/scripts/build-orcad-prebuilds.mjs
index 679625b9f6d..efbafbe9a1b 100644
--- a/config/scripts/build-orcad-prebuilds.mjs
+++ b/config/scripts/build-orcad-prebuilds.mjs
@@ -132,12 +132,16 @@ function compileNodePty(dir) {
return built
}
console.log('[orcad-prebuilds] compiling node-pty from patched source ...')
- const result = spawnSync(process.platform === 'win32' ? 'npx.cmd' : 'npx', ['node-gyp', 'rebuild'], {
- cwd: dir,
- stdio: 'inherit',
- env: process.env,
- windowsHide: true
- })
+ const result = spawnSync(
+ process.platform === 'win32' ? 'npx.cmd' : 'npx',
+ ['node-gyp', 'rebuild'],
+ {
+ cwd: dir,
+ stdio: 'inherit',
+ env: process.env,
+ windowsHide: true
+ }
+ )
if (result.status !== 0) {
throw new Error(`[orcad-prebuilds] node-gyp rebuild failed (status ${result.status})`)
}
diff --git a/config/scripts/build-orcad-prebuilds.test.mjs b/config/scripts/build-orcad-prebuilds.test.mjs
index 84c0e83c18f..c91c7e6cc9d 100644
--- a/config/scripts/build-orcad-prebuilds.test.mjs
+++ b/config/scripts/build-orcad-prebuilds.test.mjs
@@ -11,7 +11,8 @@ import {
slotName
} from './build-orcad-prebuilds.mjs'
-const PATCHED_BINDING_GYP = "'ldflags': ['-Wl,--no-as-needed,-l:libutil.so.1,-l:libpthread.so.0,--as-needed']"
+const PATCHED_BINDING_GYP =
+ "'ldflags': ['-Wl,--no-as-needed,-l:libutil.so.1,-l:libpthread.so.0,--as-needed']"
const PATCHED_PTY_CC = '__asm__(".symver openpty,openpty@" ORCA_GLIBC_COMPAT_VERSION);'
const dirs = []
@@ -107,8 +108,9 @@ describe('mergeManifest', () => {
it('does not duplicate a slot rebuilt twice', () => {
const once = mergeManifest(null, { slot: 'darwin-arm64', version: '1.1.0', nodeAbi: '127' })
- expect(mergeManifest(once, { slot: 'darwin-arm64', version: '1.1.0', nodeAbi: '127' }).slots)
- .toEqual(['darwin-arm64'])
+ expect(
+ mergeManifest(once, { slot: 'darwin-arm64', version: '1.1.0', nodeAbi: '127' }).slots
+ ).toEqual(['darwin-arm64'])
})
})
diff --git a/config/scripts/node-pty-job-ownership.cjs b/config/scripts/node-pty-job-ownership.cjs
index 35884c1414a..5ad578fd74a 100644
--- a/config/scripts/node-pty-job-ownership.cjs
+++ b/config/scripts/node-pty-job-ownership.cjs
@@ -1,10 +1,6 @@
'use strict'
-const NODE_PTY_JOB_EXPORTS = [
- 'listJobProcessIds',
- 'terminateJob',
- 'assignCurrentProcessToJob'
-]
+const NODE_PTY_JOB_EXPORTS = ['listJobProcessIds', 'terminateJob', 'assignCurrentProcessToJob']
function assertNodePtyJobOwnership({ nativeName, native, platform = process.platform }) {
if (platform !== 'win32' || nativeName !== 'conpty') {
diff --git a/config/scripts/release-e2e-dispatch-contract.test.mjs b/config/scripts/release-e2e-dispatch-contract.test.mjs
index 18fe76c4c44..d48c7b3fa30 100644
--- a/config/scripts/release-e2e-dispatch-contract.test.mjs
+++ b/config/scripts/release-e2e-dispatch-contract.test.mjs
@@ -10,6 +10,17 @@ const releaseWorkflow = parse(
const e2eWorkflow = parse(readFileSync(join(projectDir, '.github/workflows/e2e.yml'), 'utf8'))
describe('release E2E dispatch contract', () => {
+ it('validates immutable tags with the current golden test harness', () => {
+ const restoreStep = releaseWorkflow.jobs['terminal-rendering-golden'].steps.find(
+ (step) => step.name === 'Restore golden test harness from the workflow ref'
+ )
+
+ expect(restoreStep.env.WORKFLOW_SHA).toBe('${{ github.workflow_sha }}')
+ expect(restoreStep.run).toContain('git fetch --no-tags --depth=1 origin "$WORKFLOW_SHA"')
+ expect(restoreStep.run).toContain('golden-source-control-open-diff.spec.ts')
+ expect(restoreStep.run).toContain('golden-terminal-file-link.spec.ts')
+ })
+
it('dispatches tag-scoped E2E only after publication', () => {
const dispatchJob = releaseWorkflow.jobs['post-release-e2e']
const dispatchStep = dispatchJob.steps.find((step) => step.name === 'Dispatch tag-scoped E2E')
diff --git a/config/scripts/skill-sharing-release-workflow.test.mjs b/config/scripts/skill-sharing-release-workflow.test.mjs
index d2b6adcf7d4..b6611a1aa18 100644
--- a/config/scripts/skill-sharing-release-workflow.test.mjs
+++ b/config/scripts/skill-sharing-release-workflow.test.mjs
@@ -44,6 +44,48 @@ describe('skill-sharing release workflow', () => {
expect(command).toContain('src/shared/skill-bundle-install-contract.test.ts')
})
+ it('installs the archive tool required by Electron on the Linux floor', () => {
+ const linux = workflow.jobs['skill-sharing-linux-floor-release-gate']
+ const prerequisites = stepNamed(linux, 'Install Ubuntu 20.04 prerequisites')
+
+ expect(prerequisites.run).toMatch(/apt-get install[^\n]*\bunzip\b/)
+ })
+
+ it('trusts only the checked-out workspace before container git operations', () => {
+ const linux = workflow.jobs['skill-sharing-linux-floor-release-gate']
+ const trustWorkspace = stepNamed(linux, 'Trust the checked-out workspace in the job container')
+ const restoreHarness = stepNamed(
+ linux,
+ 'Restore skill-sharing test harness from the workflow ref'
+ )
+ const safeDirectoryCommands = linux.steps
+ .filter((step) => typeof step.run === 'string' && step.run.includes('safe.directory'))
+ .map((step) => step.run)
+
+ expect(trustWorkspace.run).toBe('git config --global --add safe.directory "$GITHUB_WORKSPACE"')
+ expect(linux.steps.indexOf(trustWorkspace)).toBeLessThan(linux.steps.indexOf(restoreHarness))
+ expect(safeDirectoryCommands).toEqual([
+ 'git config --global --add safe.directory "$GITHUB_WORKSPACE"'
+ ])
+ })
+
+ it('validates immutable tags with the current skill-sharing test harness', () => {
+ for (const jobName of [
+ 'skill-sharing-release-gate',
+ 'skill-sharing-linux-floor-release-gate'
+ ]) {
+ const restore = stepNamed(
+ workflow.jobs[jobName],
+ 'Restore skill-sharing test harness from the workflow ref'
+ )
+
+ expect(restore.env.WORKFLOW_SHA).toBe('${{ github.workflow_sha }}')
+ expect(restore.run).toContain('git fetch --no-tags --depth=1 origin "$WORKFLOW_SHA"')
+ expect(restore.run).toContain('skill-freshness-inventory.test.ts')
+ expect(restore.run).toContain('skill-provider-runtime-roots.test.ts')
+ }
+ })
+
it('archives bounded machine-readable evidence from every platform', () => {
for (const jobName of [
'skill-sharing-release-gate',
diff --git a/docs/STYLEGUIDE.md b/docs/STYLEGUIDE.md
index 06be8eda659..e21aaa89228 100644
--- a/docs/STYLEGUIDE.md
+++ b/docs/STYLEGUIDE.md
@@ -137,20 +137,20 @@ Browse `src/renderer/src/components/ui/` for the full list. Most wrap a Radix UI
When a control has multiple plausible primitives, use this fork:
-| You want… | Reach for | Don't use |
-| ------------------------------------------------------------ | -------------------------------------------------------------------- | ------------------------------------- |
-| Hover-only label on an icon-only button | `Tooltip` | `HoverCard` (too heavy), title attr |
-| Hover preview of richer content (avatar + summary) | `HoverCard` | `Tooltip` (no rich content) |
-| Click-revealed menu with actions | `DropdownMenu` | `Popover` with hand-rolled list |
-| Right-click contextual actions | `ContextMenu` | `DropdownMenu` (different invocation) |
-| Click-revealed surface with arbitrary content (form, picker) | `Popover` | `Dialog` (it traps focus and dims) |
-| Modal that demands a decision before you continue | `Dialog` | `Popover`, inline overlay |
-| Drawer / panel sliding in from an edge | `Sheet` | `Dialog` centered |
-| Single choice from a known list | `Select` | Custom listbox |
-| Single choice with search / fuzzy filtering | `Command` inside `Popover` | `Select` (no search) |
-| Multi-select with search | `repo-multi-combobox` (mirror its pattern) | Roll a new one |
-| Transient confirmation ("Saved", "Copied") | `sonner` toast | `Dialog`, inline banner |
-| Persistent inline status ("3 errors") | inline text + `Badge` | toast (toasts disappear) |
+| You want… | Reach for | Don't use |
+| ------------------------------------------------------------ | ------------------------------------------ | ------------------------------------- |
+| Hover-only label on an icon-only button | `Tooltip` | `HoverCard` (too heavy), title attr |
+| Hover preview of richer content (avatar + summary) | `HoverCard` | `Tooltip` (no rich content) |
+| Click-revealed menu with actions | `DropdownMenu` | `Popover` with hand-rolled list |
+| Right-click contextual actions | `ContextMenu` | `DropdownMenu` (different invocation) |
+| Click-revealed surface with arbitrary content (form, picker) | `Popover` | `Dialog` (it traps focus and dims) |
+| Modal that demands a decision before you continue | `Dialog` | `Popover`, inline overlay |
+| Drawer / panel sliding in from an edge | `Sheet` | `Dialog` centered |
+| Single choice from a known list | `Select` | Custom listbox |
+| Single choice with search / fuzzy filtering | `Command` inside `Popover` | `Select` (no search) |
+| Multi-select with search | `repo-multi-combobox` (mirror its pattern) | Roll a new one |
+| Transient confirmation ("Saved", "Copied") | `sonner` toast | `Dialog`, inline banner |
+| Persistent inline status ("3 errors") | inline text + `Badge` | toast (toasts disappear) |
If you find yourself styling around a primitive (`` to act like a `