Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
3e950ca
refactor(native-chat): group tool attribution modules (#33482)
nwparker Oct 25, 2026
3ff1f00
test: verify retry identities and complete boundary outputs (#33491)
OrcaWin Oct 25, 2026
0571e45
fix(kimi): keep a resumed Kimi pane resumable across the next Orca re…
nwparker Oct 25, 2026
a4e9000
fix(daemon): release the shell-ready barrier through Kiro's kiro-cli-…
nwparker Oct 25, 2026
3e6aa82
fix(codex): apply global ~/.codex/rules in Orca-managed Codex homes (…
nwparker Oct 25, 2026
069d85f
fix(terminal): a woken pane's new prompt starts on its own line when …
nwparker Oct 25, 2026
08019f4
fix(terminal): a WSL pane a relaunched window reattached keeps its fo…
nwparker Oct 25, 2026
048bc0f
refactor: group native chat edit and patch modules (#33497)
nwparker Oct 25, 2026
ca3bad5
test: remove redundant checks and strengthen runtime assertions (#33498)
OrcaWin Oct 25, 2026
346e2ac
fix(terminal): preserve answered snapshots across fit deadlines (#33474)
nwparker Oct 25, 2026
af99a03
fix(orchestration): re-press Enter when dsh's launchpad refuses a wor…
nwparker Oct 25, 2026
751591f
fix(runtime): let a settled screen clear a blocked agent prompt the l…
nwparker Oct 25, 2026
a5e948d
test: remove duplicate diff cases and repair audit fixtures (#33503)
OrcaWin Oct 25, 2026
48d8b35
fix(daemon): admit history shutdowns before connection preparation (#…
nwparker Oct 25, 2026
aa08c84
fix(ai-vault): list Claude sessions under a CLAUDE_CONFIG_DIR exporte…
nwparker Oct 25, 2026
7d6603a
[comment audit] Complete repository-wide comment cleanup (#33249)
OrcaWin Oct 25, 2026
2a28fc7
[comment audit] Finish launcher and configuration comment review (#33…
OrcaWin Oct 25, 2026
4b05f13
fix(agents): resume Hermes panes after a restart, on the pane's own s…
nwparker Oct 25, 2026
ced9a3d
test: remove mock-only cases and repair audit fixtures (#33509)
OrcaWin Oct 25, 2026
51dcef8
test: repair CLI and mobile fixtures and remove duplicate checks (#33…
OrcaWin Oct 25, 2026
526ffe3
fix(orchestration): start Antigravity workers in a terminal when its …
nwparker Oct 25, 2026
0044d2c
fix(agent-status): keep launch flags on a woken agent's record so a r…
nwparker Oct 25, 2026
7d18e19
test: strengthen CLI and mobile behavior checks (#33526)
OrcaWin Oct 25, 2026
5ac6834
test: strengthen CLI errors and mobile lifecycle checks (#33529)
OrcaWin Oct 25, 2026
a886dcd
fix: run topology SQLite fixture tests in Node (#33533)
nwparker Oct 25, 2026
309f819
fix(terminal): keep desktop history when a hidden pane is revealed (#…
nwparker Oct 25, 2026
0b8f519
fix(claude): show Needs You while an MCP elicitation dialog is open (…
nwparker Oct 25, 2026
e03786f
fix(worktrees): keep each same-path copy on its own host branch (#33428)
nwparker Oct 25, 2026
4af4bc1
fix(agents): resume an agent from the folder it ran in, not the pane'…
nwparker Oct 25, 2026
6b25598
test(runtime): compare existing-folder imports against the resolved t…
nwparker Oct 25, 2026
1661c3c
test: strengthen transport lifecycle and benchmark checks (#33538)
OrcaWin Oct 25, 2026
1bd308b
fix(usage): an idle Claude account whose access token lapsed reads as…
nwparker Oct 25, 2026
8b8d343
fix(terminal): keep desktop history in main's copy after a phone subs…
nwparker Oct 25, 2026
8c394bd
fix(orchestration): fail a Codex worker's dispatch when its session c…
nwparker Oct 25, 2026
d1590a7
test: honor startup paste timer delays and cancellation (#33550)
nwparker Oct 25, 2026
e13c47b
test: strengthen transport recovery and benchmark assertions (#33547)
OrcaWin Oct 25, 2026
6458c08
fix(orchestration): re-read an unrecognized foreground before refusin…
nwparker Oct 25, 2026
33c76d8
fix(agent-hooks): let the WSL hook relay run on orcad's pinned Node (…
nwparker Oct 25, 2026
cc0e35e
test: tighten transport, recovery, and diagnostic checks (#33559)
OrcaWin Oct 25, 2026
4e3014a
refactor: group native chat tool presentation modules (#33515)
nwparker Oct 25, 2026
a4e6e1f
fix(codex): migrate resumed Windows Codex sessions whose transcript h…
nwparker Oct 25, 2026
6c9c7b0
fix(worktree): start the agent when a workspace is opened during crea…
nwparker Oct 25, 2026
09873c1
test: strengthen relay, persistence, and benchmark checks (#33563)
OrcaWin Oct 25, 2026
c074ec5
fix(codex-accounts): keep the old login until re-auth finishes, and r…
nwparker Oct 25, 2026
7bbdc47
test: tighten relay assertions and repair benchmark checks (#33573)
OrcaWin Oct 25, 2026
dd797fc
fix(codex): a resting chat's skills probe no longer pins its worktree…
nwparker Oct 25, 2026
7423928
Open browser links beside their source (#32907)
AmethystLiang Oct 25, 2026
838134f
refactor: group PTY bindings and lifecycle suites (#33566)
nwparker Oct 25, 2026
95384a6
fix(terminal): frame CLI prompts for every recognized agent, not just…
nwparker Oct 25, 2026
9485e73
feat(browser): dock DevTools in the browser pane, with dock side, res…
AmoabaKelvin Oct 25, 2026
a944e37
fix(agent-status): let a pane's owner reclaim it from a nested agent'…
nwparker Oct 25, 2026
6808f4b
test: remove redundant checks and tighten runtime query coverage (#33…
OrcaWin Oct 25, 2026
55d12e1
fix(terminal): keep restored history when ConPTY repaints after a res…
nwparker Oct 25, 2026
038805f
feat(browser): ask before sites use the local network (#33399)
AmoabaKelvin Oct 25, 2026
f37c1f6
fix(pi): keep in-process subagent sessions from taking over the lead …
nwparker Oct 25, 2026
82a3214
fix(sleep): reopen a slept agent whose tab is gone in a fresh tab ins…
nwparker Oct 25, 2026
52c7f59
fix(native-chat): read WSL transcripts through guest directory symlin…
Kooooojun Oct 25, 2026
b1751c0
fix(terminal): show the stalled-daemon banner when the daemon is actu…
Jinwoo-H Oct 25, 2026
76029bf
fix(agent-status): status follows a terminal re-homed into a new tab …
nwparker Oct 25, 2026
cb82f94
OpenCode and Grok chats show the turns made outside them (#31616)
brennanb2025 Oct 25, 2026
f3364b8
fix(terminal): confirm a live agent's exit before resetting its mouse…
nwparker Oct 25, 2026
2f25699
fix(orchestration): let a new check --wait start while an old one is …
Jinwoo-H Oct 25, 2026
2990d27
fix(agent-hooks): follow Claude sessions continued into a daemon job …
nwparker Oct 25, 2026
9654684
fix(runtime): recognize Hermes readiness and its installed launcher (…
nwparker Oct 25, 2026
c6ce72d
refactor: group renderer session launch lifecycle (#33586)
nwparker Oct 25, 2026
e04f4dc
fix(mobile): keep a hook status that postdates the shell title on the…
nwparker Oct 25, 2026
bfa874a
fix(terminal): defer idle cursor resets until escape sequences finish…
nwparker Oct 25, 2026
7dfae5e
test: remove redundant metadata checks and strengthen runtime coverag…
OrcaWin Oct 25, 2026
06a3f88
fix(windows): capture Git Bash agent env with native Windows paths (#…
nwparker Oct 25, 2026
92fd257
fix(projects): refuse project setup on a paired server's SSH host wit…
nwparker Oct 25, 2026
843e502
fix(orchestration): point idle headless terminals at their mail (#33258)
nwparker Oct 25, 2026
d4cab5c
refactor: group local filesystem guards and search owners (#33624)
nwparker Oct 25, 2026
d1bbb8e
test: remove redundant renderer and shared checks and strengthen asse…
OrcaWin Oct 25, 2026
220d56f
fix(codex): index a new WSL account home before bridging history into…
nwparker Oct 25, 2026
25262fc
fix(daemon): let macOS terminal shells download cloud-only files (STA…
Jinwoo-H Oct 25, 2026
e26e418
Preserve uncertain goal text and accept distinct controls (#33022)
brennanb2025 Oct 25, 2026
a6c4507
fix(native-chat): a remembered effort a saved Pi listing lacks no lon…
nwparker Oct 25, 2026
9ac968f
test: strengthen Git and Linear assertions and remove redundant check…
OrcaWin Oct 25, 2026
65e513b
fix(daemon): recover lost macOS worker wake-ups in the packaged termi…
nwparker Oct 25, 2026
27e7f8f
Keep the permission pill inside Arguments and share the Permissions m…
brennanb2025 Oct 25, 2026
883b768
A chat never starts writing a conversation a terminal is still writin…
brennanb2025 Oct 25, 2026
3fbf89b
test: strengthen watcher and mobile async assertions (#33641)
OrcaWin Oct 25, 2026
47d1b31
refactor(mobile): group native chat send and stream state (#33640)
nwparker Oct 25, 2026
28de913
test(connectors): drive a connector conversation end to end on a head…
Jinwoo-H Oct 25, 2026
3b8e872
fix(codex): show HTTP usage while Codex's session index is stuck rebu…
nwparker Oct 25, 2026
eb49947
feat(browser): show agent browsing live, with a jump to the page from…
AmoabaKelvin Oct 25, 2026
395270f
Retry failed agent starts before rejecting your message (#33045)
brennanb2025 Oct 25, 2026
c77c3fe
Stabilize sidebar activity toggle placement (#33648)
AmethystLiang Oct 25, 2026
f53e7b0
test: strengthen filesystem and settings coverage; remove redundant c…
OrcaWin Oct 25, 2026
c6769fc
chore: post-merge cleanup for agent integration fixes (#33644)
nwparker Oct 25, 2026
7e8bf3d
fix(acp): OMP models other than the running one keep a remembered eff…
nwparker Oct 25, 2026
9639426
fix(agent-status): an Antigravity subagent finishing no longer ends i…
nwparker Oct 25, 2026
47ed6e1
fix(orchestration): wake an agent for new mail even while it still ho…
Jinwoo-H Oct 25, 2026
b7a6570
fix(accounts): an account-switch restart resumes Claude in the folder…
nwparker Oct 25, 2026
1b0e56e
feat(browser): make Orca shortcuts, split focus and mouse back/forwar…
AmoabaKelvin Oct 25, 2026
23798ef
Let chats follow the agent permission setting (#32334)
brennanb2025 Oct 25, 2026
f94b15e
fix(cli): a sandbox that denies chmod no longer breaks reading Orca's…
nwparker Oct 25, 2026
d9a7aa8
ci(wsl): rerun a WSL2 lane job once when its hosted runner freezes (#…
nwparker Oct 25, 2026
12cc6c5
fix(kiro): report status on Kiro's V3 engine, including the built-in …
nwparker Oct 25, 2026
553cbff
fix(antigravity): keep the selected account after agy refreshes its t…
nwparker Oct 25, 2026
cffb527
fix(usage): show a Claude Enterprise seat's monthly spend cap when it…
nwparker Oct 25, 2026
3aec926
Chat renames are saved as the chat's name, so Session History shows t…
brennanb2025 Oct 25, 2026
ddd55a4
Bound cwd permission probes during terminal session creation (#33643)
AmethystLiang Oct 25, 2026
d37c04c
Fix notification bell layout (#33683)
AmethystLiang Oct 25, 2026
5a4dd30
fix(ci): repair main's line limits and a stale test import (#33675)
brennanb2025 Oct 25, 2026
a5f7da4
revert(daemon): ship official Node in the macOS terminal host again, …
Jinwoo-H Oct 26, 2026
2209d55
fix(terminal): give the window and main's copy the daemon's ConPTY re…
nwparker Oct 26, 2026
3ffe2af
fix(terminal): preserve intact replay escape tails across fit deadlin…
nwparker Oct 26, 2026
bfc633a
Offer to resume chats after managed server updates (#28978)
brennanb2025 Oct 26, 2026
1b58be9
fix(ssh): retry over system ssh when ssh2 shares no algorithm with th…
nwparker Oct 26, 2026
5cf4805
fix(link-actions): dismiss the link chooser when an outside click sto…
nwparker Oct 26, 2026
478ad91
Add custom font family setting for native chat (#33687)
AmethystLiang Oct 26, 2026
c0a51bc
fix(ssh): don't refuse a host's move over a pane that saved no termin…
nwparker Oct 26, 2026
79a63f3
fix(orcad): bundle jsonc-parser's ESM build into the shipped CLI (#33…
nwparker Oct 26, 2026
8ee2f09
fix(orcad): drive Android emulators from headless orca serve hosts (#…
nwparker Oct 26, 2026
405ce9b
Stabilize notification dispatch tests with fixed timestamps (#33698)
AmethystLiang Oct 26, 2026
bd2f463
fix(daemon): roll the daemon-side terminal fixes since v1.4.240 into …
Jinwoo-H Oct 26, 2026
469eec3
merge: sync fork-main from stablyai/orca main (bd2f46359d1e)
karlorz Oct 26, 2026
a481567
fix(sync): lint and format fallout from upstream bd2f4635 merge
karlorz Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
48 changes: 12 additions & 36 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# A shebang plus CRLF makes vite's SSR transform emit a literal `#!` mid-module,
# so any suite importing the script dies at load with a SyntaxError. Pin the whole
# directory rather than the scripts that happen to have a test today.
# CRLF shebangs break Vite's SSR transform.
/config/scripts/**/*.mjs text eol=lf
/skill-guides/*.md text eol=lf
/skill-stubs/*.md text eol=lf
Expand All @@ -15,55 +13,33 @@
*.html text eol=lf
# Bundled plugin trees are byte-hashed; CRLF checkout would break the pinned hash.
/resources/plugins/** text eol=lf
# Relay assets are copied verbatim into the bundle and hashed byte-for-byte into
# .version, which names the immutable remote install dir. A CRLF checkout makes a
# Windows-built client disagree with a mac/Linux-built one on the same release,
# so one host ends up with two relay trees (#17886 review).
# Pin the bytes so a patch reads and diffs identically on every host. It is NOT
# what makes the hash right: pnpm hashes a patch LF-normalized, so a CRLF checkout
# cannot change it. Believing otherwise put a hand-computed raw digest in the
# lockfile twice and broke every install (#17886).
# These files are stored LF, which is not always the encoding they were written
# against -- @vscode/windows-process-tree ships CRLF sources -- so any code that
# runs `git apply` on one must force `-c core.autocrlf=input` rather than trust
# the host's setting. See config/scripts/windows-process-tree-gyp-rebuild.mjs.
# Keep patch diffs stable; pnpm hashes them with LF normalization.
# CRLF upstream sources still need git -c core.autocrlf=input apply (windows-process-tree-gyp-rebuild.mjs).
/config/patches/*.patch -text
# Same reason, and pnpm parses these too: a CRLF checkout makes the mobile
# patches unparseable, so Windows packaging dies on ERR_PNPM_INVALID_PATCH.
# CRLF patches fail pnpm parsing on Windows.
/mobile/patches/*.patch -text
# The xterm bundle hunks also make a diff nobody can read; review the hand-written
# source patch under xterm-src/ instead. The sibling patches stay diffable.
# Review xterm-src/ instead of generated bundle hunks.
/config/patches/@xterm__xterm@*.patch -diff
/config/patches/xterm-src/*.patch text eol=lf
# pnpm parses these unified diffs during Windows installs; keep checkout bytes stable.
/mobile/patches/*.patch -text
# Generated wrapper fixtures: collapse them in the PR diff so they stop drowning
# the reviewable change, and pin LF because they are compared byte-for-byte.
# Not -diff: the shell diff is the review surface when a wrapper does change.
# Collapse generated wrappers but keep diffs available; tests compare LF bytes.
/src/main/__fixtures__/shell-wrapper-snapshots/*.txt linguist-generated=true text eol=lf
# Captured agent PTY transcripts. -text, not `text eol=lf` like the wrapper snapshots above:
# these carry real CR and CRLF bytes as the terminal emitted them, and line-ending
# normalisation on a Windows checkout would rewrite the evidence the fixture exists to be.
# PTY transcripts must retain captured CR and CRLF bytes.
/src/main/runtime/__fixtures__/*.txt -text
/src/main/daemon/__fixtures__/pty-transcripts/*.txt -text
/src/renderer/src/components/terminal-pane/terminal-link-transcripts/*.txt -text whitespace=cr-at-eol
# Generated runtime English subset: compared byte-for-byte by
# verify:localization-runtime-catalog, so a CRLF checkout would fail the gate.
# verify:localization-runtime-catalog compares LF bytes.
/src/renderer/src/i18n/en-runtime-required.json linguist-generated=true text eol=lf
# Generated method->params catalog: compared byte-for-byte by
# verify:rpc-params-catalog, so a CRLF checkout would fail the gate.
# verify:rpc-params-catalog compares LF bytes.
/src/shared/rpc-contract/rpc-params-catalog.generated.ts linguist-generated=true text eol=lf
# Mobile RPC recording goldens: replay requires the file text to equal what rpc:record writes
# (LF), so a CRLF checkout would fail every golden.
# RPC recording goldens must match rpc:record's LF output.
/mobile/rpc-foundation/goldens/*.json text eol=lf
# Mobile web page source. Every text byte here is hashed into an asset digest and from
# there into buildId, so a CRLF Windows checkout would ship a different bundle id for
# identical source (91af2897 vs 9d78435e, measured on the bundle this replaced).
# Mobile build IDs hash source bytes; checkout line endings must match across hosts.
/mobile/src/** text eol=lf
/mobile/app/** text eol=lf
/mobile/web-entry/** text eol=lf
# The blanket pin above would mark a future binary as text; exempt the asset types an
# RN page actually carries.
# Preserve binary assets under the text-pinned mobile directories.
/mobile/src/**/*.png -text
/mobile/src/**/*.jpg -text
/mobile/src/**/*.jpeg -text
Expand Down
2 changes: 0 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Product source remains owned by its normal reviewers; localization inputs need focused review.
/src/renderer/src/i18n/locales/ @brennanb2025
/config/scripts/*localization*.mjs @brennanb2025
/config/scripts/*locale*.mjs @brennanb2025
/config/i18next.config.ts @brennanb2025

# The relay's deploy and operate surface: workspace, workflows, and the rollout lease action.
/cloud/ @Jinwoo-H
/.github/workflows/cloud-*.yml @Jinwoo-H
/.github/actions/cloud-sql-rollout-lease/ @Jinwoo-H
13 changes: 1 addition & 12 deletions .github/actions/cloud-sql-rollout-lease/gcloud-access-token.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
import { execFileSync } from 'node:child_process'

// DESIGN CHOICE: shell out to `gcloud auth print-access-token` instead of exchanging the
// external_account credentials file that google-github-actions/auth writes.
//
// Every workflow on the Cloud SQL rollout lease already runs google-github-actions/setup-gcloud
// right after auth (verified across all 11 mutating members), so gcloud is on PATH and already
// bound to the federated identity. Doing the exchange ourselves would mean reimplementing the STS
// token swap plus the service-account impersonation leg, in an action that must stay
// zero-dependency and is duplicated by hand into a second repo. gcloud already handles every ADC
// flavour and refreshes on its own. The metadata server is not an option: it does not exist on
// GitHub or Blacksmith runners.
//
// Consequence, documented in the README: the lease step MUST come after setup-gcloud.
// Use gcloud after setup-gcloud: it handles federated STS/impersonation and ADC refresh without dependencies or repo-local code in this duplicated action. Actions/Blacksmith runners have no metadata server.

const TOKEN_REUSE_MS = 40 * 60 * 1_000 // GCP access tokens live ~60 min; re-mint well before that.

Expand Down
3 changes: 1 addition & 2 deletions .github/actions/cloud-sql-rollout-lease/holder-identity.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Who we claim to be on the lease object. Shared by main and the detached renewer so both agree
// on the holder key without re-deriving it from a different set of environment variables.
// Main and detached renewer must derive the same holder key from one environment contract.

export function holderIdentity(explicitHolderKey) {
const repository = process.env.GITHUB_REPOSITORY ?? 'unknown'
Expand Down
3 changes: 1 addition & 2 deletions .github/actions/cloud-sql-rollout-lease/renew.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { createAccessTokenSource } from './gcloud-access-token.mjs'
import { renewerLogPath } from './runner-state.mjs'
import { CloudSqlRolloutLease, RENEW_INTERVAL_MS } from './storage-lease.mjs'

// Detached renewer. `main` spawns it, `post` kills it. It rewrites expires_at on the same
// generation-matched path as acquisition, and stops the moment the object stops being ours.
// Detached renewer shares acquisition’s generation-matched writes; stop when ownership changes. Main starts it and post kills it.

const MAX_LIFETIME_MS = 6 * 60 * 60 * 1_000 // Backstop if post never runs (runner killed).

Expand Down
3 changes: 1 addition & 2 deletions .github/actions/cloud-sql-rollout-lease/runner-state.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { appendFileSync } from 'node:fs'

// Action-state and output plumbing via the runner's file protocol, so the action needs no
// @actions/core dependency. Values are single-line by construction; anything else is rejected.
// Use runner files without @actions/core; reject multiline values rather than corrupting their protocol.

/** The detached renewer's stdio is ignored, so it appends here instead and `post` echoes it. */
export function renewerLogPath() {
Expand Down
8 changes: 1 addition & 7 deletions .github/actions/cloud-sql-rollout-lease/storage-lease.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
// Compare-and-swap lease over a single Cloud Storage object.
//
// Ported from apps/relay-fence-broker/src/mutation-lease.ts rather than imported: this action is
// duplicated verbatim into stablyai/orca, so it must carry no repo-local imports. Only the
// algorithm is shared (read metadata -> write with ifGenerationMatch -> 412 is a conflict ->
// generation-matched delete -> an expired record is free). The broker's token path is NOT shared;
// it reads the GCE metadata server, which does not exist on Actions runners.
// Ported CAS algorithm from relay-fence-broker/mutation-lease.ts: keep repo-local imports out of this duplicated action. Broker metadata-server tokens cannot work on Actions runners; use generation-matched writes/deletes, 412 conflicts and expiry.

export const LEASE_TTL_MS = 35 * 60 * 1_000
export const RENEW_INTERVAL_MS = 5 * 60 * 1_000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ const BUCKET = 'onorca-cloud-terraform-state'
const OBJECT = 'terraform/state/cloud-sql-rollout/production.lock'
const NOW = 1_756_000_000_000

/**
* Enough of the Cloud Storage JSON API to exercise real compare-and-swap semantics: generations
* increment, ifGenerationMatch is enforced, and a mismatch is a 412. `faults` injects failures.
*/
/** Model real GCS generation increments, ifGenerationMatch and 412 conflicts; faults inject failures. */
function fakeStorage({ object = null, faults = [] } = {}) {
const state = { object, requests: [] }
const fetcher = async (rawUrl, init = {}) => {
Expand Down
7 changes: 1 addition & 6 deletions .github/actions/install-mobile-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ description: Frozen pnpm install for the mobile/ project, whose node_modules the
runs:
using: composite
steps:
# Why a separate install: mobile is its own pnpm project, so the root install leaves
# mobile/node_modules empty and every mobile import resolves to nothing.
# Why no --ignore-scripts, unlike the root install: mobile's postinstall generates the
# gitignored terminal/mermaid webview engine modules that tracked source imports.
# The drift guard mirrors the root install so a stale mobile lockfile fails by name --
# mobile's lockfile carries patchedDependencies that a silent rewrite would drop.
# Install the separate mobile project: root install leaves its imports unresolved. Keep lifecycle scripts for generated terminal/mermaid engines; reject lockfile drift that could drop patchedDependencies.
- name: Install mobile dependencies
shell: bash
working-directory: mobile
Expand Down
5 changes: 1 addition & 4 deletions .github/actions/install-node-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,7 @@ runs:
rm -rf node_modules
fi

# Why --frozen-lockfile: re-resolving pulls ~62 MB of registry packuments per job
# (measured) to recompute what the lockfile already pins, and the `git diff` guard
# below fails the run whenever that recomputation would have changed anything. The
# guard stays so a stale lockfile still fails by name rather than by resolver error.
# Frozen install avoids ~62MB/job of redundant resolution; retain diff guard to name stale lockfiles explicitly.
- name: Install dependencies
shell: bash
run: |
Expand Down
29 changes: 6 additions & 23 deletions .github/actions/install-signpath-module/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,7 @@ runs:
# Why: force TLS 1.2 so gallery downloads work on older hosted images.
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

# Why: on some hosted Windows images `Register-PSRepository -Default`
# fails inside the legacy nuget.exe provider with "Missing option value
# for: '-source'", so PSGallery is never registered and the install
# below dies with "No repository with the name 'PSGallery'". PSResourceGet
# (bundled with PowerShell 7.4+) has PSGallery registered by default and
# avoids that code path, so prefer it and fall back to PowerShellGet only
# when it is absent.
# Prefer PSResourceGet (PowerShell 7.4+): legacy nuget Register-PSRepository can fail with “Missing option value for: -source” and leave PSGallery absent.
$useResourceGet = $null -ne (Get-Command -Name Install-PSResource -ErrorAction SilentlyContinue)

try {
Expand All @@ -53,9 +47,7 @@ runs:
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
}
} catch {
# Why: repository registration also talks to the gallery, so a gallery
# outage can fail here before a single install is attempted. The CDN
# fallback below does not need a registered repository, so keep going.
# Repository registration can fail during gallery outages; continue so the independent CDN fallback remains reachable.
Write-Warning "PSGallery repository registration failed: $_"
}

Expand Down Expand Up @@ -114,13 +106,8 @@ runs:
}
}

# Why: the gallery's package API (OData search + repository metadata) sits
# behind Azure Front Door and has returned 403/502/504 for every install
# attempt during gallery incidents, which hard-failed the whole Windows
# release job. The CDN that serves the nupkg itself is a separate origin
# and stays up through those incidents, so fall back to a pinned version
# fetched straight from it. The hash pin is mandatory: this route skips the
# gallery's package validation, so an unexpected payload must fail loudly.
# Gallery OData/metadata has returned 403/502/504 while the independent nupkg CDN stayed up.
# Fall back to a pinned version and mandatory hash because this bypasses gallery validation.
if (-not $installed) {
$version = $env:SIGNPATH_FALLBACK_VERSION
$expectedHash = $env:SIGNPATH_FALLBACK_SHA256
Expand All @@ -131,9 +118,7 @@ runs:
Remove-Item -LiteralPath $nupkg -Force
}

# Why two URLs: the /api/v2/package route 302s to the CDN and can serve
# while the OData search endpoint is failing; the CDN URL is the same
# redirect target reached directly when the api host is down entirely.
# Try the API’s CDN redirect, then the CDN directly if the API host is down.
$sources = @(
"https://www.powershellgallery.com/api/v2/package/SignPath/$version",
"https://cdn.powershellgallery.com/packages/signpath.$version.nupkg"
Expand Down Expand Up @@ -173,9 +158,7 @@ runs:
}

Remove-SignPathModuleDirectory
# Why a version-named subdirectory: PowerShell only treats a nested folder
# as a side-by-side module version when the name matches the manifest's
# ModuleVersion, which is what makes `Import-Module SignPath` resolve it.
# PowerShell resolves side-by-side modules only when the directory matches the manifest’s ModuleVersion.
$versionRoot = Join-Path -Path $signPathModulePath -ChildPath $version
New-Item -ItemType Directory -Path $versionRoot -Force | Out-Null
Expand-Archive -LiteralPath $nupkg -DestinationPath $versionRoot -Force
Expand Down
3 changes: 1 addition & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
version: 2
updates:
# Why only ripgrep: the bundled rg ships in every artifact and to SSH remotes, and a bump is a
# one-line pin change (the SSH cache keys on the binary's hash). Other dependencies stay manual.
# Automate only bundled ripgrep’s single pin; its hash invalidates SSH cache. Other dependency updates stay manual.
- package-ecosystem: npm
directory: /
schedule:
Expand Down
16 changes: 4 additions & 12 deletions .github/scripts/check-root-directory-entries.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { execFileSync } from 'node:child_process'
import { randomUUID } from 'node:crypto'

function readRootEntries(sha) {
// Why: a git pathname is arbitrary bytes, and 'utf8' folds every invalid
// sequence to U+FFFD — that mangles the reported name and makes two different
// entries compare equal, so a genuinely new one can slip past the Set below.
// latin1 maps each byte to one code unit, so the bytes survive the round trip.
// Git paths are arbitrary bytes; latin1 round-trips them while utf8 merges invalid sequences into U+FFFD, hiding distinct entries.
const stdout = execFileSync('git', ['ls-tree', '-z', '--name-only', sha], {
encoding: 'latin1',
stdio: ['ignore', 'pipe', 'inherit']
Expand Down Expand Up @@ -42,10 +39,7 @@ function checkRootDirectoryEntries(argv) {
)
console.log('Move each new entry under an existing top-level directory.')
console.log('Blocked entries:')
// Why: an entry name is attacker-controlled and may start with '::' (the runner
// trims leading spaces before matching) or embed a newline, so printing it bare
// lets a PR forge annotations. Fence the untrusted list with an unguessable
// stop-commands token, and write the raw bytes rather than a re-encoded string.
// Untrusted names can forge runner commands/newlines; fence them with a random stop-commands token and preserve raw bytes.
const resumeToken = randomUUID()
console.log(`::stop-commands::${resumeToken}`)
for (const entry of blockedEntries) {
Expand All @@ -56,12 +50,10 @@ function checkRootDirectoryEntries(argv) {
}

try {
// Why: process.exit truncates a piped write part-way through on macOS, so set
// exitCode and let node flush the blocked-entry list before it exits.
// Let piped output flush; process.exit can truncate it on macOS.
process.exitCode = checkRootDirectoryEntries(process.argv.slice(2))
} catch (error) {
// Why: git already reported the failure on the inherited stderr, so surface its
// status rather than a node stack trace. Anything else is a real bug — rethrow.
// Git already reported failures; preserve its exit status and rethrow other bugs.
if (typeof error.status !== 'number') {
throw error
}
Expand Down
4 changes: 1 addition & 3 deletions .github/scripts/pr-test-loc-table.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ export const LOC_BLOCK_END = '<!-- /orca-pr-loc -->'
export const LOC_HANDS_OFF_COMMENT =
'<!-- Programmatic LoC summary. Do not edit by hand; rewritten on every commit. -->'

// Why the __-wrapped names: they are unambiguous test-data markers, so a dir
// cannot be one by accident. Bare `fixtures/` is deliberately absent — it reads
// as a plausible prod module name, and this classifier bills every PR.
// __-wrapped segments unambiguously mark test data; bare fixtures/ could be production, and this classifier bills every PR.
const TEST_DIR_SEGMENT = /(?:^|\/)(?:__tests__|__fixtures__|__snapshots__|e2e|tests)(?:\/|$)/i
const TEST_FILENAME = /\.(?:test|spec|e2e)\.[^/]+$/i

Expand Down
Loading
Loading