@akira-tl/forgerelay 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +19 -11
- package/capabilities/workspace/managed-worktrees/GUIDE.md +4 -2
- package/dist/cli/config/migrate.js +5 -2
- package/dist/cli/init/setup-config.js +0 -2
- package/dist/cli/setup-support.js +3 -2
- package/dist/mcp/server/core/schemas.js +6 -0
- package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +4 -2
- package/dist/mcp/server/workspace/runtime/workspace-open-schema.js +6 -1
- package/dist/mcp/server/workspace/runtime/workspace-open.js +19 -13
- package/dist/runtime/config/definition/general-config.js +4 -3
- package/dist/runtime/config/external-mcp-config.js +4 -3
- package/dist/runtime/config/user-config.js +4 -1
- package/dist/runtime/config/validation/ports.js +9 -0
- package/dist/runtime/logging/logger.js +19 -19
- package/dist/ui/.vite/manifest.json +276 -276
- package/dist/ui/activity-panel-app.html +2 -2
- package/dist/ui/assets/activity-panel-app-Dq2xLIrs.css +1 -0
- package/dist/ui/assets/{activity-panel-app-BeDiwd7D.js → activity-panel-app-hkM8rX3z.js} +1 -1
- package/dist/ui/assets/{angular-html-DuoCE7nn.js → angular-html-UD0GEFFl.js} +1 -1
- package/dist/ui/assets/{angular-ts-D5tGk0hL.js → angular-ts-B2awh-Q1.js} +1 -1
- package/dist/ui/assets/{apl-lciOTPbw.js → apl-CpbhnJc8.js} +1 -1
- package/dist/ui/assets/{astro-vJbqfNnJ.js → astro-CkVVuF5B.js} +1 -1
- package/dist/ui/assets/{blade-C7655Q4K.js → blade-czG58aop.js} +1 -1
- package/dist/ui/assets/{c-DdHp1Jrw.js → c-DSq6h06b.js} +1 -1
- package/dist/ui/assets/{cobol-DgvzQxZP.js → cobol-CYnmhT2E.js} +1 -1
- package/dist/ui/assets/{coffee-BIjVUOUd.js → coffee-ClLhNqd5.js} +1 -1
- package/dist/ui/assets/{cpp-CU8tGzvI.js → cpp-BZDC6U43.js} +1 -1
- package/dist/ui/assets/{crystal-CUQAwsg9.js → crystal-BN9jCJyU.js} +1 -1
- package/dist/ui/assets/{css-DtMTqD3F.js → css-8dMfiihi.js} +1 -1
- package/dist/ui/assets/{edge-DoCX9RnL.js → edge-DemPBRNz.js} +1 -1
- package/dist/ui/assets/{elixir-DJxV9_U6.js → elixir-bLdHW8dz.js} +1 -1
- package/dist/ui/assets/{elm-DIgWqK4r.js → elm-DlZPcXmu.js} +1 -1
- package/dist/ui/assets/{erb-BHxP0c_e.js → erb-wmTqbHwm.js} +1 -1
- package/dist/ui/assets/{git-rebase-HbI_Vo8d.js → git-rebase-BqrZJVYO.js} +1 -1
- package/dist/ui/assets/{glimmer-js-CthY4Ty_.js → glimmer-js-CkPzdNHI.js} +1 -1
- package/dist/ui/assets/{glimmer-ts-B2-_A1Xz.js → glimmer-ts-Bd0vTdJC.js} +1 -1
- package/dist/ui/assets/{glsl-D9V9gq98.js → glsl-DKK0Kibz.js} +1 -1
- package/dist/ui/assets/{graphql-CddeAaS3.js → graphql-DmFr8ZvB.js} +1 -1
- package/dist/ui/assets/{hack-D_loGkOT.js → hack-BQcuk9lx.js} +1 -1
- package/dist/ui/assets/{haml-BoWDczd0.js → haml-Dbx0cG5B.js} +1 -1
- package/dist/ui/assets/{handlebars-ZoSOvw9y.js → handlebars-D0nD8yLi.js} +1 -1
- package/dist/ui/assets/{heavy-payload-DO34LwoZ.js → heavy-payload-CPOM8G8z.js} +3 -3
- package/dist/ui/assets/{html-CE-obXVo.js → html-9xkoIci1.js} +1 -1
- package/dist/ui/assets/{html-derivative-Cd-smAbW.js → html-derivative-Cg7n4YW0.js} +1 -1
- package/dist/ui/assets/{http-CZrkbrSl.js → http-Ckt_4_pP.js} +1 -1
- package/dist/ui/assets/{hurl-CxTuxBt1.js → hurl-BxMgqn9u.js} +1 -1
- package/dist/ui/assets/{java-BshLjCat.js → java-DxijgO-5.js} +1 -1
- package/dist/ui/assets/{javascript-D2pxQTiX.js → javascript-CusLzlRb.js} +1 -1
- package/dist/ui/assets/{jinja-kbfPP7-F.js → jinja-DBTRfImq.js} +1 -1
- package/dist/ui/assets/{jison-C2mt9l1M.js → jison-oCbVte0g.js} +1 -1
- package/dist/ui/assets/{json-DU_rg_AU.js → json-uq2yfoO2.js} +1 -1
- package/dist/ui/assets/{jsx-D_8aQMlx.js → jsx-B3AfJWyQ.js} +1 -1
- package/dist/ui/assets/{julia-BmefTaVV.js → julia-BFvq-UTm.js} +1 -1
- package/dist/ui/assets/{just-DXV8vk1S.js → just-Ck0W9Rcj.js} +1 -1
- package/dist/ui/assets/{latex-Cjm2MvGW.js → latex-BjKhTmaO.js} +1 -1
- package/dist/ui/assets/{liquid-DyQDlo0u.js → liquid-CsaE0q4b.js} +1 -1
- package/dist/ui/assets/{lua-B2A1vzzy.js → lua-D0MSBhv0.js} +1 -1
- package/dist/ui/assets/{marko-B9vOkXOU.js → marko-CTLxSPPr.js} +1 -1
- package/dist/ui/assets/{mdc-D42m6spU.js → mdc-BwDM_Bct.js} +1 -1
- package/dist/ui/assets/{nginx-TpfVxSUY.js → nginx-C5Q5rNaB.js} +1 -1
- package/dist/ui/assets/{nim-CJr5T1FK.js → nim-BjKHRt6k.js} +1 -1
- package/dist/ui/assets/{perl-cJZcsdm9.js → perl-BrABfniL.js} +1 -1
- package/dist/ui/assets/{php-CSZL5KRT.js → php-BWY__Khq.js} +1 -1
- package/dist/ui/assets/{pug-B1eMKzuA.js → pug-BD4PlwIK.js} +1 -1
- package/dist/ui/assets/{qml-Dl2_7zc9.js → qml-yQtdZNrK.js} +1 -1
- package/dist/ui/assets/{r-F0aaO9gG.js → r-D0tlixrf.js} +1 -1
- package/dist/ui/assets/{razor-BPnkSMCw.js → razor-CsmyuKJs.js} +1 -1
- package/dist/ui/assets/{regexp-BnGHMFbv.js → regexp-BXU4cTCD.js} +1 -1
- package/dist/ui/assets/{rst-B3CO7WYO.js → rst-CGlzAlrM.js} +1 -1
- package/dist/ui/assets/{ruby-B6VMzT1T.js → ruby-CRKDbfJj.js} +1 -1
- package/dist/ui/assets/{sas-Df2lHVuU.js → sas-CKDY6iPG.js} +1 -1
- package/dist/ui/assets/{scss-4XxI6sgu.js → scss-BCoXLSqD.js} +1 -1
- package/dist/ui/assets/{shellscript-DYASCN4r.js → shellscript-BVuRs_tF.js} +1 -1
- package/dist/ui/assets/{shellsession-Br6AGJO_.js → shellsession-alj1b7vN.js} +1 -1
- package/dist/ui/assets/{soy-p3ZNq1We.js → soy-BbQDrw9i.js} +1 -1
- package/dist/ui/assets/{sql-CAdv2OXL.js → sql-BdcqHaEA.js} +1 -1
- package/dist/ui/assets/{stata-Dx7yUbG_.js → stata-5IC5m_XB.js} +1 -1
- package/dist/ui/assets/{surrealql-6YsE8HQa.js → surrealql-BfVFLYzV.js} +1 -1
- package/dist/ui/assets/{svelte-YgzedwpD.js → svelte-B22aFi25.js} +1 -1
- package/dist/ui/assets/{templ-Bahqx3uD.js → templ-BRo7TcBX.js} +1 -1
- package/dist/ui/assets/{tex-o6fTQjkH.js → tex-CYhw-JbD.js} +1 -1
- package/dist/ui/assets/{ts-tags-BO-Co0Ju.js → ts-tags-C56aGOzq.js} +1 -1
- package/dist/ui/assets/{tsx-DtQe5AoH.js → tsx-IkFyQoro.js} +1 -1
- package/dist/ui/assets/{twig-BcUs6Kqc.js → twig-NkXaxf7l.js} +1 -1
- package/dist/ui/assets/{typescript-BPtM8h4u.js → typescript-AgbZakqy.js} +1 -1
- package/dist/ui/assets/{vue-5KkGUzJJ.js → vue-Cxz1Rk-f.js} +1 -1
- package/dist/ui/assets/{vue-html-Df_Xfsz9.js → vue-html-DWHLzP-w.js} +1 -1
- package/dist/ui/assets/{vue-vine-hUIe_u_Y.js → vue-vine-WR64TKte.js} +1 -1
- package/dist/ui/assets/{xml-C3Jy7as5.js → xml-CNdUn7jo.js} +1 -1
- package/dist/ui/assets/{xsl-BnF9OuFo.js → xsl-DLRRUZ98.js} +1 -1
- package/dist/ui/assets/{yaml-DyrFgCou.js → yaml-gltXViA8.js} +1 -1
- package/dist/workspace-colors.js +54 -0
- package/dist/workspaces/git/git-worktrees.js +53 -14
- package/dist/workspaces/inventory.js +2 -0
- package/dist/workspaces/presentation/workspace-presentation.js +13 -0
- package/dist/workspaces/relay/workspace-relay.js +3 -0
- package/dist/workspaces/sessions.js +28 -8
- package/dist/workspaces.js +9 -9
- package/docs/chatgpt-coding-workflow.md +16 -8
- package/docs/gotchas.md +2 -2
- package/package.json +2 -1
- package/schemas/v1/config.user.schema.json +2 -2
- package/scripts/ci/cmd-acceptance.mjs +3 -85
- package/scripts/ci/gates/acceptance-runtime.mjs +45 -0
- package/scripts/ci/gates/platform-tests.mjs +27 -17
- package/scripts/ci/gates/prepare-windows-shell-runtime.mjs +45 -0
- package/scripts/ci/gates/test-shard.mjs +29 -7
- package/scripts/ci/powershell51-acceptance.mjs +10 -91
- package/scripts/ci/pwsh-acceptance.mjs +7 -87
- package/scripts/ci/windows-product-acceptance.mjs +55 -0
- package/scripts/release/release-gate.test.mjs +121 -13
- package/scripts/release-parity.mjs +12 -1
- package/dist/ui/assets/activity-panel-app-DkfJzTZ3.css +0 -1
|
@@ -40,7 +40,9 @@ try {
|
|
|
40
40
|
console.log(`Using prepared acceptance install: ${prefix}`);
|
|
41
41
|
}
|
|
42
42
|
const shim = join(prefix, "forgerelay.cmd");
|
|
43
|
+
const powershellShim = join(prefix, "forgerelay.ps1");
|
|
43
44
|
assert.ok(existsSync(shim), `npm did not create the Windows launcher shim: ${shim}`);
|
|
45
|
+
assert.ok(existsSync(powershellShim), `npm did not create the PowerShell launcher shim: ${powershellShim}`);
|
|
44
46
|
|
|
45
47
|
const installedRoot = join(prefix, "node_modules", "@akira-tl", "forgerelay");
|
|
46
48
|
assert.ok(existsSync(join(installedRoot, "dist", "cli.js")), `installed package is missing dist/cli.js: ${installedRoot}`);
|
|
@@ -67,6 +69,14 @@ try {
|
|
|
67
69
|
installedRoot,
|
|
68
70
|
workspaceProbe,
|
|
69
71
|
});
|
|
72
|
+
if (runtime.family !== "cmd") {
|
|
73
|
+
await exercisePackagedPowerShellLauncher({
|
|
74
|
+
...runtime,
|
|
75
|
+
root,
|
|
76
|
+
projectRoot,
|
|
77
|
+
powershellShim,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
await exercisePackagedElevationContract(installedRoot, { root, projectRoot, shim, cmd });
|
|
@@ -148,6 +158,51 @@ async function exercisePackagedRuntime({ family, executable, doctorIdentity, roo
|
|
|
148
158
|
assert.equal(opened.instructionStatus, "loaded", `${family} shell Instructions were not advertised as loaded`);
|
|
149
159
|
}
|
|
150
160
|
|
|
161
|
+
async function exercisePackagedPowerShellLauncher({ family, executable, doctorIdentity, root, projectRoot, powershellShim }) {
|
|
162
|
+
const configDir = join(root, `config-launcher-${family}`);
|
|
163
|
+
const stateDir = join(root, `state-launcher-${family}`);
|
|
164
|
+
await Promise.all([
|
|
165
|
+
mkdir(configDir, { recursive: true }),
|
|
166
|
+
mkdir(stateDir, { recursive: true }),
|
|
167
|
+
]);
|
|
168
|
+
await writeFile(
|
|
169
|
+
join(configDir, "config.json"),
|
|
170
|
+
JSON.stringify({
|
|
171
|
+
host: "127.0.0.1",
|
|
172
|
+
port: 7678,
|
|
173
|
+
allowedRoots: [projectRoot],
|
|
174
|
+
stateDir,
|
|
175
|
+
worktreeRoot: join(root, `worktrees-launcher-${family}`),
|
|
176
|
+
commandShell: {
|
|
177
|
+
mode: "follow-launcher",
|
|
178
|
+
family,
|
|
179
|
+
executable,
|
|
180
|
+
},
|
|
181
|
+
shellInstructions: false,
|
|
182
|
+
}, null, 2),
|
|
183
|
+
"utf8",
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const result = spawnSync(
|
|
187
|
+
executable,
|
|
188
|
+
["-NoLogo", "-NoProfile", "-NonInteractive", "-File", powershellShim, "doctor"],
|
|
189
|
+
{
|
|
190
|
+
cwd: process.cwd(),
|
|
191
|
+
env: cleanAcceptanceEnv(configDir),
|
|
192
|
+
encoding: "utf8",
|
|
193
|
+
windowsHide: true,
|
|
194
|
+
timeout: 10_000,
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
if (result.error || result.status !== 0) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Packaged PowerShell launcher failed for ${family}: ${result.error?.message ?? result.stderr ?? result.status}`,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
assert.match(result.stdout ?? "", doctorIdentity);
|
|
203
|
+
assert.match(result.stdout ?? "", /Command shell source: launcher/);
|
|
204
|
+
}
|
|
205
|
+
|
|
151
206
|
async function exercisePackagedElevationContract(installedRoot, { root, projectRoot, shim, cmd }) {
|
|
152
207
|
const { assertRuntimePrivilegeAllowed, detectRuntimePrivilege, elevatedRuntimeWarning } = await importInstalled(
|
|
153
208
|
installedRoot,
|
|
@@ -66,17 +66,41 @@ test("cross-platform cloud CI splits shared tests from bounded platform acceptan
|
|
|
66
66
|
const workflow = await readFile(resolve(repoRoot, ".github/workflows/ci.yml"), "utf8");
|
|
67
67
|
assert.match(workflow, /core-contract:/);
|
|
68
68
|
assert.match(workflow, /core-tests:/);
|
|
69
|
-
for (const shard of [
|
|
69
|
+
for (const shard of [
|
|
70
|
+
"runtime-config",
|
|
71
|
+
"workspace-relay-auth",
|
|
72
|
+
"workspace-relay",
|
|
73
|
+
"workspace-lifecycle",
|
|
74
|
+
"workspace-state",
|
|
75
|
+
"mcp-core",
|
|
76
|
+
"mcp-server-ui",
|
|
77
|
+
"lsp",
|
|
78
|
+
"subagent",
|
|
79
|
+
"ui-cli",
|
|
80
|
+
]) {
|
|
70
81
|
assert.match(workflow, new RegExp(`\\b${shard}\\b`));
|
|
71
82
|
}
|
|
72
83
|
assert.match(workflow, /run:\s*npm run ci:contract/);
|
|
73
84
|
assert.match(workflow, /run:\s*npm run ci:test-shard -- \$\{\{ matrix\.shard \}\}/);
|
|
74
85
|
assert.match(workflow, /macos-platform:[\s\S]*run:\s*npm run ci:platform-tests/);
|
|
75
|
-
assert.match(workflow, /windows-platform:[\s\S]*
|
|
76
|
-
|
|
86
|
+
assert.match(workflow, /windows-platform:[\s\S]*runtime-process[\s\S]*workspace-filesystem/);
|
|
87
|
+
const windowsPlatform = workflow.match(/ windows-platform:[\s\S]*?(?=\n windows-product:)/)?.[0];
|
|
88
|
+
assert.ok(windowsPlatform, "Windows platform job must remain present");
|
|
89
|
+
assert.match(windowsPlatform, /uses:\s*actions\/cache@v4/);
|
|
90
|
+
assert.match(windowsPlatform, /path:\s*node_modules/);
|
|
91
|
+
assert.match(windowsPlatform, /runner\.os/);
|
|
92
|
+
assert.match(windowsPlatform, /runner\.arch/);
|
|
93
|
+
assert.match(windowsPlatform, /hashFiles\('\.nvmrc'\)/);
|
|
94
|
+
assert.match(windowsPlatform, /npm-11\.19\.1/);
|
|
95
|
+
assert.match(windowsPlatform, /hashFiles\('package-lock\.json'\)/);
|
|
96
|
+
assert.match(windowsPlatform, /id:\s*windows-npm-cli[\s\S]*path:\s*\.ci-npm-global/);
|
|
97
|
+
assert.match(windowsPlatform, /if:\s*steps\.windows-npm-cli\.outputs\.cache-hit != 'true'[\s\S]*npm install --global --prefix \.ci-npm-global npm@11\.19\.1/);
|
|
98
|
+
assert.match(windowsPlatform, /if:\s*steps\.windows-platform-deps\.outputs\.cache-hit != 'true'[\s\S]*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js ci --no-audit --no-fund/);
|
|
99
|
+
assert.match(windowsPlatform, /run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:platform-tests -- \$\{\{ matrix\.shard \}\}/);
|
|
100
|
+
assert.doesNotMatch(windowsPlatform, /npx --yes npm@11\.19\.1/);
|
|
77
101
|
assert.doesNotMatch(workflow, /run:\s*npm run ci:verify/);
|
|
78
102
|
assert.doesNotMatch(workflow, /run:\s*npm test/);
|
|
79
|
-
assert.doesNotMatch(workflow,
|
|
103
|
+
assert.doesNotMatch(workflow, /^\s*shell:/m);
|
|
80
104
|
assert.doesNotMatch(workflow, /run:\s*\|/);
|
|
81
105
|
});
|
|
82
106
|
|
|
@@ -138,7 +162,18 @@ test("release runtime and local parity share the checked-in Node contract", asyn
|
|
|
138
162
|
assert.match(ciWorkflow, /npm install --global npm@11\.19\.1/);
|
|
139
163
|
assert.ok(source.includes('["npm", "ci", "--no-audit", "--no-fund"]'));
|
|
140
164
|
assert.ok(source.includes('["npm", "run", "ci:contract"]'));
|
|
141
|
-
for (const shard of [
|
|
165
|
+
for (const shard of [
|
|
166
|
+
"runtime-config",
|
|
167
|
+
"workspace-relay-auth",
|
|
168
|
+
"workspace-relay",
|
|
169
|
+
"workspace-lifecycle",
|
|
170
|
+
"workspace-state",
|
|
171
|
+
"mcp-core",
|
|
172
|
+
"mcp-server-ui",
|
|
173
|
+
"lsp",
|
|
174
|
+
"subagent",
|
|
175
|
+
"ui-cli",
|
|
176
|
+
]) {
|
|
142
177
|
assert.match(source, new RegExp(`\\"${shard}\\"`));
|
|
143
178
|
}
|
|
144
179
|
assert.ok(source.includes('["npm", "run", "build"]'));
|
|
@@ -151,15 +186,27 @@ test("release runtime and local parity share the checked-in Node contract", asyn
|
|
|
151
186
|
assert.doesNotMatch(source, /\["npm", "test"\]/);
|
|
152
187
|
});
|
|
153
188
|
|
|
154
|
-
test("cloud verification builds one npm artifact
|
|
189
|
+
test("cloud verification builds one npm artifact while independent gates start immediately", async () => {
|
|
155
190
|
const workflow = await readFile(resolve(repoRoot, ".github/workflows/ci.yml"), "utf8");
|
|
156
|
-
assert.match(workflow, /package:[\s\S]*
|
|
191
|
+
assert.match(workflow, /package:[\s\S]*run:\s*npm run build[\s\S]*run:\s*npm run lsp:interop[\s\S]*run:\s*npm run release:pack/);
|
|
192
|
+
assert.doesNotMatch(workflow, /package:[\s\S]*needs:\s*core-contract/);
|
|
193
|
+
assert.match(workflow, /traffic-audit:[\s\S]*run:\s*npm run build:app[\s\S]*run:\s*npm run traffic:audit/);
|
|
194
|
+
assert.match(workflow, /macos-platform:[\s\S]*run:\s*npm run ci:platform-tests/);
|
|
195
|
+
assert.match(workflow, /macos-product:[\s\S]*needs:\s*package[\s\S]*run:\s*npm run config:product-accept/);
|
|
196
|
+
assert.match(workflow, /windows-platform:[\s\S]*runtime-process[\s\S]*workspace-filesystem/);
|
|
197
|
+
assert.match(workflow, /windows-product:[\s\S]*needs:\s*package[\s\S]*run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run windows:product-accept/);
|
|
198
|
+
assert.match(workflow, /windows-shell:[\s\S]*needs:\s*package[\s\S]*FORGERELAY_ACCEPTANCE_RUNTIME_ROOT:\s*\.release-runtime[\s\S]*run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run \$\{\{ matrix\.script \}\}/);
|
|
199
|
+
assert.match(workflow, /windows-shell:[\s\S]*id:\s*windows-shell-deps[\s\S]*path:\s*node_modules/);
|
|
200
|
+
assert.match(workflow, /if:\s*steps\.windows-shell-deps\.outputs\.cache-hit == 'true'[\s\S]*run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-shell-runtime/);
|
|
201
|
+
assert.match(workflow, /if:\s*steps\.windows-shell-deps\.outputs\.cache-hit != 'true'[\s\S]*run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-product/);
|
|
157
202
|
assert.equal((workflow.match(/run:\s*npm run release:pack/g) ?? []).length, 1);
|
|
158
203
|
assert.equal((workflow.match(/uses:\s*actions\/upload-artifact@v7/g) ?? []).length, 1);
|
|
159
|
-
assert.equal((workflow.match(/uses:\s*actions\/download-artifact@v7/g) ?? []).length,
|
|
204
|
+
assert.equal((workflow.match(/uses:\s*actions\/download-artifact@v7/g) ?? []).length, 4);
|
|
160
205
|
assert.match(workflow, /FORGERELAY_ACCEPTANCE_ARTIFACT_DIR:\s*\.release-package/);
|
|
161
|
-
assert.match(
|
|
162
|
-
assert.equal((workflow.match(/run:\s*npm run ci:prepare-windows-
|
|
206
|
+
assert.equal((workflow.match(/run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-product/g) ?? []).length, 2);
|
|
207
|
+
assert.equal((workflow.match(/run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-shell-runtime/g) ?? []).length, 1);
|
|
208
|
+
assert.match(workflow, /key:\s*windows-npm-cli-\$\{\{ runner\.os \}\}-\$\{\{ runner\.arch \}\}-node-\$\{\{ hashFiles\('\.nvmrc'\) \}\}-npm-11\.19\.1/);
|
|
209
|
+
assert.match(workflow, /npm install --global --prefix \.ci-npm-global npm@11\.19\.1 --no-audit --no-fund --prefer-offline/);
|
|
163
210
|
assert.equal((workflow.match(/run:\s*npm run traffic:audit/g) ?? []).length, 1);
|
|
164
211
|
assert.equal((workflow.match(/run:\s*npm run lsp:interop/g) ?? []).length, 1);
|
|
165
212
|
assert.match(workflow, /name:\s*npm-package/);
|
|
@@ -180,16 +227,46 @@ test("packaged acceptance scripts can consume the one downloaded release artifac
|
|
|
180
227
|
assert.match(prepareWindows, /resolveAcceptancePrefix/);
|
|
181
228
|
assert.match(prepareWindows, /"install", "--global", "--prefix"/);
|
|
182
229
|
|
|
230
|
+
const prepareShellRuntime = await readFile(
|
|
231
|
+
resolve(repoRoot, "scripts/ci/gates/prepare-windows-shell-runtime.mjs"),
|
|
232
|
+
"utf8",
|
|
233
|
+
);
|
|
234
|
+
assert.match(prepareShellRuntime, /resolveAcceptanceTarball/);
|
|
235
|
+
assert.match(prepareShellRuntime, /--strip-components=1/);
|
|
236
|
+
assert.match(prepareShellRuntime, /FORGERELAY_ACCEPTANCE_RUNTIME_ROOT/);
|
|
237
|
+
|
|
238
|
+
const acceptanceRuntime = await readFile(
|
|
239
|
+
resolve(repoRoot, "scripts/ci/gates/acceptance-runtime.mjs"),
|
|
240
|
+
"utf8",
|
|
241
|
+
);
|
|
242
|
+
assert.match(acceptanceRuntime, /FORGERELAY_ACCEPTANCE_RUNTIME_ROOT/);
|
|
243
|
+
assert.match(acceptanceRuntime, /resolveAcceptancePrefix/);
|
|
244
|
+
assert.match(acceptanceRuntime, /node_modules/);
|
|
245
|
+
assert.match(acceptanceRuntime, /dist", "cli\.js"/);
|
|
246
|
+
|
|
183
247
|
for (const relativePath of [
|
|
184
248
|
"scripts/ci/config-v2-product-acceptance.mjs",
|
|
185
249
|
"scripts/ci/windows-product-acceptance.mjs",
|
|
250
|
+
]) {
|
|
251
|
+
const source = await readFile(resolve(repoRoot, relativePath), "utf8");
|
|
252
|
+
assert.match(source, /resolveAcceptanceTarball/);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
for (const relativePath of [
|
|
186
256
|
"scripts/ci/pwsh-acceptance.mjs",
|
|
187
257
|
"scripts/ci/powershell51-acceptance.mjs",
|
|
188
258
|
"scripts/ci/cmd-acceptance.mjs",
|
|
189
259
|
]) {
|
|
190
260
|
const source = await readFile(resolve(repoRoot, relativePath), "utf8");
|
|
191
|
-
assert.match(source, /
|
|
261
|
+
assert.match(source, /acceptanceRuntimeModuleUrl/);
|
|
262
|
+
assert.doesNotMatch(source, /resolveAcceptanceTarball/);
|
|
263
|
+
assert.doesNotMatch(source, /resolveAcceptancePrefix/);
|
|
264
|
+
assert.doesNotMatch(source, /import\("\.\.\/\.\.\/dist\//);
|
|
192
265
|
}
|
|
266
|
+
|
|
267
|
+
const windowsProduct = await readFile(resolve(repoRoot, "scripts/ci/windows-product-acceptance.mjs"), "utf8");
|
|
268
|
+
assert.match(windowsProduct, /forgerelay\.ps1/);
|
|
269
|
+
assert.match(windowsProduct, /Command shell source: launcher/);
|
|
193
270
|
});
|
|
194
271
|
|
|
195
272
|
test("Windows product acceptance uses the supported Skills environment seam rather than a removed config key", async () => {
|
|
@@ -212,6 +289,20 @@ test("release workflow is tag-only and promotes the verified npm artifact withou
|
|
|
212
289
|
assert.doesNotMatch(workflow, /shell:\s*bash/);
|
|
213
290
|
});
|
|
214
291
|
|
|
292
|
+
test("manual Cloud CI verification can never publish a release", async () => {
|
|
293
|
+
const workflow = await readFile(
|
|
294
|
+
resolve(repoRoot, ".github/workflows/cloud-ci-verification.yml"),
|
|
295
|
+
"utf8",
|
|
296
|
+
);
|
|
297
|
+
assert.match(workflow, /workflow_dispatch:/);
|
|
298
|
+
assert.match(workflow, /uses:\s*\.\/\.github\/workflows\/ci\.yml/);
|
|
299
|
+
assert.match(workflow, /permissions:[\s\S]*contents:\s*read/);
|
|
300
|
+
assert.doesNotMatch(workflow, /release:publish/);
|
|
301
|
+
assert.doesNotMatch(workflow, /npm publish/);
|
|
302
|
+
assert.doesNotMatch(workflow, /contents:\s*write/);
|
|
303
|
+
assert.doesNotMatch(workflow, /id-token:\s*write/);
|
|
304
|
+
});
|
|
305
|
+
|
|
215
306
|
test("manual Windows shell acceptance can never publish a release", async () => {
|
|
216
307
|
const workflow = await readFile(
|
|
217
308
|
resolve(repoRoot, ".github/workflows/windows-shell-acceptance.yml"),
|
|
@@ -221,9 +312,26 @@ test("manual Windows shell acceptance can never publish a release", async () =>
|
|
|
221
312
|
assert.match(workflow, /runs-on:\s*windows-2022/);
|
|
222
313
|
assert.match(workflow, /FORGERELAY_ACCEPTANCE_ARTIFACT_DIR:\s*\.release-artifacts/);
|
|
223
314
|
assert.match(workflow, /FORGERELAY_ACCEPTANCE_PREFIX:\s*\.release-installed/);
|
|
315
|
+
assert.match(workflow, /FORGERELAY_ACCEPTANCE_RUNTIME_ROOT:\s*\.release-runtime/);
|
|
224
316
|
assert.equal((workflow.match(/run:\s*npm run release:pack/g) ?? []).length, 1);
|
|
225
|
-
assert.equal((workflow.match(/
|
|
226
|
-
assert.match(
|
|
317
|
+
assert.equal((workflow.match(/uses:\s*actions\/upload-artifact@v7/g) ?? []).length, 1);
|
|
318
|
+
assert.equal((workflow.match(/uses:\s*actions\/download-artifact@v7/g) ?? []).length, 2);
|
|
319
|
+
assert.equal((workflow.match(/run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-product/g) ?? []).length, 2);
|
|
320
|
+
assert.equal((workflow.match(/run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:prepare-windows-shell-runtime/g) ?? []).length, 1);
|
|
321
|
+
assert.match(workflow, /id:\s*windows-shell-deps[\s\S]*path:\s*node_modules/);
|
|
322
|
+
assert.match(workflow, /key:\s*windows-npm-cli-\$\{\{ runner\.os \}\}-\$\{\{ runner\.arch \}\}-node-\$\{\{ hashFiles\('\.nvmrc'\) \}\}-npm-11\.19\.1/);
|
|
323
|
+
const windowsPlatform = workflow.match(/ windows-platform:[\s\S]*?(?=\n windows-product:)/)?.[0];
|
|
324
|
+
assert.ok(windowsPlatform, "manual Windows platform job must remain present");
|
|
325
|
+
assert.match(windowsPlatform, /uses:\s*actions\/cache@v4/);
|
|
326
|
+
assert.match(windowsPlatform, /id:\s*windows-npm-cli[\s\S]*path:\s*\.ci-npm-global/);
|
|
327
|
+
assert.match(windowsPlatform, /if:\s*steps\.windows-npm-cli\.outputs\.cache-hit != 'true'[\s\S]*npm install --global --prefix \.ci-npm-global npm@11\.19\.1/);
|
|
328
|
+
assert.match(windowsPlatform, /if:\s*steps\.windows-platform-deps\.outputs\.cache-hit != 'true'[\s\S]*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js ci --no-audit --no-fund/);
|
|
329
|
+
assert.match(windowsPlatform, /run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run ci:platform-tests -- \$\{\{ matrix\.shard \}\}/);
|
|
330
|
+
assert.doesNotMatch(windowsPlatform, /npx --yes npm@11\.19\.1/);
|
|
331
|
+
assert.match(workflow, /script:\s*pwsh:accept/);
|
|
332
|
+
assert.match(workflow, /script:\s*powershell51:accept/);
|
|
333
|
+
assert.match(workflow, /script:\s*cmd:accept/);
|
|
334
|
+
assert.match(workflow, /run:\s*node \.ci-npm-global\/node_modules\/npm\/bin\/npm-cli\.js run \$\{\{ matrix\.script \}\}/);
|
|
227
335
|
assert.doesNotMatch(workflow, /release:publish/);
|
|
228
336
|
assert.doesNotMatch(workflow, /npm publish/);
|
|
229
337
|
assert.doesNotMatch(workflow, /contents:\s*write/);
|
|
@@ -29,7 +29,18 @@ try {
|
|
|
29
29
|
`Node ${NODE_VERSION} / npm ${NPM_VERSION} install`,
|
|
30
30
|
);
|
|
31
31
|
runNodeNpm(sandbox, env, ["npm", "run", "ci:contract"], "Cloud core contract");
|
|
32
|
-
for (const shard of [
|
|
32
|
+
for (const shard of [
|
|
33
|
+
"runtime-config",
|
|
34
|
+
"workspace-relay-auth",
|
|
35
|
+
"workspace-relay",
|
|
36
|
+
"workspace-lifecycle",
|
|
37
|
+
"workspace-state",
|
|
38
|
+
"mcp-core",
|
|
39
|
+
"mcp-server-ui",
|
|
40
|
+
"lsp",
|
|
41
|
+
"subagent",
|
|
42
|
+
"ui-cli",
|
|
43
|
+
]) {
|
|
33
44
|
runNodeNpm(
|
|
34
45
|
sandbox,
|
|
35
46
|
env,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.forgerelay-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.workspace-panel{background:var(--tool-card-header-bg);width:100%}.workspace-panel-header{grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;min-height:58px;padding:9px 12px;display:grid}.workspace-panel-icon{background:color-mix(in srgb, var(--tool-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--tool-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-panel-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-panel-title-group{gap:2px;min-width:0;display:grid}.workspace-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.workspace-panel-subtitle,.workspace-panel-mode{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.workspace-panel-subtitle{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.workspace-panel-mode{border:1px solid color-mix(in srgb, var(--tool-card-divider) 76%, transparent);white-space:nowrap;border-radius:999px;padding:2px 7px}.workspace-panel .workspace-details{overscroll-behavior:contain;border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);max-height:420px;overflow:hidden auto}.workspace-panel-pending-dot{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:999px;justify-self:center}.activity-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.forgerelay-panel .activity-panel{border:0;border-top:1px solid var(--tool-card-divider);border-radius:0}.activity-panel-header{width:100%;min-height:58px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:14px minmax(0,1fr) auto 20px;align-items:center;gap:10px;padding:9px 12px;display:grid}.activity-panel-header:hover{background:var(--tool-card-hover-bg)}.activity-panel-header:focus-visible{outline:2px solid color-mix(in srgb, var(--color-text-info,#38bdf8) 72%, transparent);outline-offset:-2px}.activity-panel-header-pending{cursor:default}.activity-panel-header-pending:hover{background:0 0}.activity-panel-pending-spacer{width:20px}.activity-panel-status{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:9999px;justify-self:center}.activity-panel-status.state-done{background:var(--color-success-text,#6fda83);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent)}.activity-panel-status.state-error{background:var(--color-danger-text,#ee7676);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent)}.activity-panel-title-group{gap:2px;min-width:0;display:grid}.activity-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.activity-panel-subtitle,.activity-panel-count{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.activity-panel-count{white-space:nowrap;font-weight:600}.activity-panel-count.state-working{color:var(--color-text-info,#38bdf8)}.activity-panel-count.state-done{color:var(--color-success-text,#6fda83)}.activity-panel-count.state-error{color:var(--color-danger-text,#ee7676)}.activity-panel-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.activity-viewport{overscroll-behavior:contain;max-height:420px;overflow:hidden auto}.activity-list{display:grid}.activity-group+.activity-group{border-top:1px solid var(--tool-card-divider)}.activity-group.grouped>.activity-row.parent{background:color-mix(in srgb, var(--color-background-secondary,#272727) 54%, transparent)}.activity-children{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);display:grid}.activity-row{--activity-accent:var(--color-text-secondary,#b6b6bd);--activity-phase:var(--color-text-tertiary,#a3a3aa);width:100%;min-height:46px;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:28px minmax(0,1fr) auto 16px;align-items:center;gap:10px;padding:7px 12px;display:grid}.activity-row.interactive{cursor:pointer}.activity-row.interactive:hover{background:var(--tool-card-hover-bg)}.activity-row.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--activity-accent) 68%, transparent);outline-offset:-2px}.activity-row.child{padding-left:34px;position:relative}.activity-row.child:before{background:color-mix(in srgb, var(--activity-accent) 26%, var(--tool-card-divider));content:"";width:1px;position:absolute;top:0;bottom:0;left:20px}.activity-row.child+.activity-row.child{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 52%, transparent)}.activity-row.kind-read{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.activity-row.kind-write{--activity-accent:var(--color-success-text,#6fda83)}.activity-row.kind-edit,.activity-row.kind-rename{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.activity-row.kind-delete{--activity-accent:var(--color-danger-text,#ee7676)}.activity-row.kind-shell{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.activity-row.kind-shell-result{--activity-accent:color-mix(in srgb, var(--color-success-text,#6fda83) 72%, var(--color-text-secondary,#b6b6bd))}.activity-row.kind-capability{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.activity-row.kind-batch{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #8b5cf6 66%)}.activity-row.phase-executing{--activity-phase:var(--color-text-info,#38bdf8)}.activity-row.phase-returned{--activity-phase:var(--color-warning-text,#e6b566)}.activity-row.phase-done{--activity-phase:var(--color-success-text,#6fda83)}.activity-row.phase-error{--activity-phase:var(--color-danger-text,#ee7676)}.activity-row.phase-executing{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-phase) 76%, transparent);background:color-mix(in srgb, var(--activity-phase) 5%, transparent)}.activity-row.phase-returned{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-phase) 68%, transparent)}.activity-row.phase-error{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-phase) 72%, transparent)}.activity-row.shell-result{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-accent) 68%, transparent)}.activity-icon{border:1px solid color-mix(in srgb, var(--activity-accent) 18%, transparent);background:color-mix(in srgb, var(--activity-accent) 9%, transparent);width:28px;height:28px;color:var(--activity-accent);border-radius:7px;place-items:center;display:grid}.activity-icon-svg{stroke-width:1.8px;width:15px;height:15px}.activity-main{gap:4px;min-width:0;display:grid}.activity-title-line{align-items:baseline;gap:8px;min-width:0;display:flex}.activity-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);flex:none;font-weight:600;line-height:1.35}.activity-member{color:var(--color-text-secondary,#d4d4d8);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,10px);flex:none;line-height:1.4}.activity-target{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.activity-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap;justify-content:flex-end;align-items:center;gap:8px;display:inline-flex}.activity-phase{color:var(--activity-phase);align-items:center;gap:5px;display:inline-flex}.activity-phase:before{content:"";background:currentColor;border-radius:9999px;width:6px;height:6px}.activity-progress-wrap{grid-template-columns:auto minmax(48px,110px);align-items:center;gap:8px;max-width:220px;display:grid}.activity-progress-counts{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap}.activity-progress-track{background:color-mix(in srgb, var(--activity-accent) 14%, var(--tool-card-divider));border-radius:9999px;height:3px;display:block;overflow:hidden}.activity-progress-fill{border-radius:inherit;background:var(--activity-accent);height:100%;display:block}.activity-empty,.activity-refresh-error{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:12px}.activity-refresh-error{border-top:1px solid var(--tool-card-divider);color:var(--color-danger-text,#ee7676)}.activity-detail-chevron,.activity-detail-spacer,.activity-detail-chevron.chevron{width:16px;height:16px}.activity-detail-chevron .icon-svg{width:13px;height:13px}.activity-entry.expanded>.activity-row{background:color-mix(in srgb, var(--activity-accent) 6%, transparent)}.activity-detail{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);background:color-mix(in srgb, var(--color-background-primary,#101114) 90%, transparent);display:grid}.activity-detail-section+.activity-detail-section{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 62%, transparent)}.activity-detail-rich{min-width:0;overflow:hidden}.activity-detail-rich .pierre-diff,.activity-detail-rich .pierre-file{border-radius:0}.activity-detail-label{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);letter-spacing:.02em;padding:8px 12px 0;font-weight:600}.activity-detail-section.error .activity-detail-label,.activity-detail-section.error .activity-detail-value{color:var(--color-danger-text,#ee7676)}.activity-detail-value{max-height:260px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:6px 12px 10px;line-height:1.5;overflow:auto}.activity-detail-status{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:10px 12px}.activity-detail-status.error{color:var(--color-danger-text,#ee7676)}.activity-terminal{background:var(--color-background-primary,#101114)}.activity-terminal-command,.activity-terminal-output{color:var(--color-text-primary,#f5f5f6);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;background:0 0;border:0;border-radius:0;margin:0;line-height:1.55}.activity-terminal-command{border-bottom:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-secondary,#c7c7ce);padding:9px 12px}.activity-terminal-output{max-height:320px;padding:10px 12px;overflow:auto}.activity-terminal-meta{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;padding:7px 12px}.activity-terminal-meta.status-running{color:var(--color-text-info,#38bdf8)}.activity-terminal-meta.status-done{color:var(--color-success-text,#6fda83)}.activity-terminal-meta.status-failed{color:var(--color-danger-text,#ee7676)}@media (width<=520px){.activity-panel-header{grid-template-columns:12px minmax(0,1fr) auto 18px;gap:8px;min-height:54px;padding:8px 10px}.activity-panel-subtitle,.activity-panel-count{font-size:10px}.activity-row{grid-template-columns:26px minmax(0,1fr) 18px;gap:6px 8px;min-height:48px;padding:8px 10px}.activity-row.child{padding-left:28px}.activity-row.child:before{left:16px}.activity-icon{align-self:start;width:26px;height:26px}.activity-title-line{gap:2px;display:grid}.activity-meta{grid-column:2;justify-content:flex-start}.activity-detail-chevron,.activity-detail-spacer{grid-area:1/3/span 2}.activity-progress-wrap{grid-template-columns:auto minmax(40px,1fr);max-width:none}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);color:var(--color-text-primary,#f5f5f6);--tool-card-border:color-mix(in srgb, var(--color-border-primary,#414141) 74%, transparent);--tool-card-header-bg:color-mix(in srgb, var(--color-background-secondary,#272727) 88%, transparent);--tool-card-body-bg:color-mix(in srgb, var(--color-background-primary,#181818) 94%, transparent);--tool-card-hover-bg:color-mix(in srgb, var(--color-background-tertiary,#343434) 46%, transparent);--tool-card-divider:color-mix(in srgb, var(--color-border-primary,#414141) 66%, transparent);--tool-accent:var(--color-text-secondary,#b6b6bd);--scrollbar-thumb:color-mix(in srgb, var(--color-text-tertiary,#8a8a8a) 56%, transparent);--scrollbar-thumb-hover:color-mix(in srgb, var(--color-text-secondary,#a8a8a8) 82%, transparent);background:0 0}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body{background:0 0;margin:0;overflow:hidden}.shell{width:100%;padding:0;overflow:hidden}.empty,.tool-card{--tool-accent-soft:color-mix(in srgb, var(--tool-accent) 12%, transparent);border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;box-shadow:none;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.tool-card.workspace,.tool-card.directory{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.tool-card.read,.tool-card.search{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.tool-card.write{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.edit,.tool-card.review{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.tool-card.delete{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.shell{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.tool-card.state-success{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.state-error{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.state-running{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 30%, #38bdf8 70%)}@supports selector(::-webkit-scrollbar){.pretty-scrollbar::-webkit-scrollbar{width:12px;height:12px}.pretty-scrollbar::-webkit-scrollbar-button{width:0;height:0;display:none}.pretty-scrollbar::-webkit-scrollbar-track{background:0 0}.pretty-scrollbar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb);background-clip:content-box;border:4px solid #0000;border-radius:9999px}.pretty-scrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-thumb:active{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-corner{background:0 0}}.empty{color:var(--color-text-secondary,#b6b6bd);font-size:var(--font-text-sm-size,13px);padding:14px 16px}.tool-header{width:100%;min-height:64px;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:11px;grid-template-columns:40px minmax(0,1fr) auto 20px;align-items:center;gap:12px;padding:10px 12px;display:grid}.tool-header:focus-visible,.review-diff-file-header:focus-visible,.review-more:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.tool-header:hover:not(:disabled){background:var(--tool-card-hover-bg)}.tool-header:disabled{cursor:default}.tool-icon{border:1px solid color-mix(in srgb, var(--tool-accent) 18%, transparent);background:var(--tool-accent-soft);width:40px;height:40px;color:var(--tool-accent);border-radius:10px;place-items:center;display:grid}.icon-svg{stroke-width:1.8px;width:20px;height:20px;display:block}.tool-main{gap:2px;min-width:0;display:grid}.tool-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,14px);font-weight:550;line-height:1.3}.tool-label{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);font-variant-numeric:tabular-nums;white-space:nowrap;align-items:center;gap:5px;display:inline-flex}.header-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);text-align:right;white-space:nowrap;line-height:1.35}.header-meta.empty{width:0}.add{color:var(--color-success-text,#6fda83)}.remove{color:var(--color-danger-text,#ee7676)}.chevron{width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);border-radius:7px;place-items:center;transition:background .14s,color .14s,transform .14s;display:grid}.tool-header:hover:not(:disabled) .chevron{color:var(--color-text-primary,#f5f5f6)}.chevron .icon-svg{width:15px;height:15px}.chevron.expanded{transform:rotate(180deg)}.chevron.loading{transform:none}.chevron.loading .icon-svg{fill:none;stroke-linecap:round;stroke-dasharray:38 14;animation:.7s linear infinite payload-spinner}@keyframes payload-spinner{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.chevron.loading .icon-svg{animation:none}}.tool-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg)}.workspace-details{max-height:420px;display:grid;overflow:auto}.workspace-rows{padding:4px 0;display:grid}.workspace-row{--workspace-row-accent:var(--tool-accent);grid-template-columns:22px minmax(116px,.24fr) minmax(0,1fr);align-items:center;gap:10px;min-height:40px;padding:7px 12px;display:grid}.workspace-row-icon{background:color-mix(in srgb, var(--workspace-row-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--workspace-row-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-row-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-key{min-height:22px;color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);align-items:center;font-weight:500;display:flex}.workspace-value{min-width:0;color:var(--color-text-secondary,#c7c7ce);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.45;overflow:hidden}.workspace-value.mono{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.workspace-base-value{align-items:center;gap:7px;min-width:0;display:flex}.workspace-base-value .workspace-value{flex:0 auto}.workspace-base-warning{width:18px;height:18px;color:var(--color-warning-text,#e6b566);cursor:help;flex:none;place-items:center;display:grid}.workspace-base-warning-svg{stroke-width:2px;width:14px;height:14px}.workspace-chip-list{flex-wrap:nowrap;align-items:center;gap:6px;min-width:0;display:flex;overflow:hidden}.workspace-chip{border:1px solid color-mix(in srgb, var(--tool-accent) 16%, var(--tool-card-divider));background:color-mix(in srgb, var(--tool-accent) 7%, transparent);max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);text-overflow:ellipsis;white-space:nowrap;border-radius:9999px;flex:none;align-items:center;gap:5px;padding:3px 8px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-chip-logo{object-fit:contain;flex:none;width:13px;height:13px;display:block}.workspace-chip-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.workspace-agent-profile{border:0;border-bottom:1px solid color-mix(in srgb, var(--tool-accent) 34%, var(--tool-card-divider));max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);white-space:nowrap;background:0 0;border-radius:0;align-items:center;gap:5px;padding:3px 2px 4px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-agent-profile-logo{object-fit:contain;flex:none;width:14px;height:14px;display:block}.workspace-agent-profile:hover{border-bottom-color:var(--tool-accent);color:var(--color-text-primary,#f5f5f6)}.workspace-agent-profile.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-bottom-style:dashed}.workspace-provider-logo{cursor:help;flex:none;place-items:center;width:20px;height:24px;display:inline-grid}.workspace-provider-logo-image{object-fit:contain;width:16px;height:16px;display:block}.workspace-provider-logo.muted{opacity:.62}.workspace-chip.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-style:dashed}.workspace-skills-row,.workspace-instructions-row,.workspace-agents-row{align-items:start}.workspace-instructions-row{--workspace-row-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.workspace-skills-row{--workspace-row-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #14b8a6 72%)}.workspace-agents-row{--workspace-row-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 30%, #8b5cf6 70%)}.workspace-skills-row .workspace-chip,.workspace-agents-row .workspace-chip,.workspace-agents-row .workspace-agent-profile{border-color:color-mix(in srgb, var(--workspace-row-accent) 28%, var(--tool-card-divider))}.workspace-skills-row .workspace-chip{background:color-mix(in srgb, var(--workspace-row-accent) 7%, transparent)}.workspace-skills-list,.workspace-agents-list{flex-wrap:wrap;overflow:visible}.workspace-instruction-status{border-radius:5px;flex:none;place-items:center;width:18px;height:18px;display:grid}.workspace-instruction-status.loaded{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.workspace-instruction-status.available,.workspace-instruction-status.disabled{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 9%, transparent);color:var(--color-text-tertiary,#a3a3aa)}.workspace-instruction-status.disabled{opacity:.65}.workspace-instruction-status.unavailable{background:color-mix(in srgb, var(--color-warning-text,#e6b566) 12%, transparent);color:var(--color-warning-text,#e6b566)}.workspace-instruction-status-svg{stroke-width:1.9px;width:12px;height:12px}.workspace-instruction-list{border:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 88%, transparent);border-radius:9px;min-width:0;display:grid;overflow:hidden}.workspace-instructions-content{min-width:0;display:block}.workspace-instructions-toggle{border:0;border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 72%, transparent);width:100%;min-height:32px;color:var(--tool-accent);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,11px);white-space:nowrap;border-radius:0 0 9px 9px;justify-content:center;align-items:center;padding:6px 10px;font-weight:550;line-height:1.25;display:flex}.workspace-instructions-toggle:hover{background:var(--tool-card-hover-bg)}.workspace-instructions-toggle:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:2px}.workspace-instruction-item+.workspace-instruction-item{border-top:1px solid var(--tool-card-divider)}.workspace-instruction-header{width:100%;min-width:0;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) 18px;align-items:center;gap:9px;padding:8px 10px;display:grid}.workspace-instruction-header.interactive{cursor:pointer}.workspace-instruction-header.interactive:hover{background:var(--tool-card-hover-bg)}.workspace-instruction-header.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.workspace-instruction-text{gap:2px;min-width:0;display:grid}.workspace-instruction-name{min-width:0;color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;font-weight:550;overflow:hidden}.workspace-instruction-path{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:1.35;overflow:hidden}.workspace-instruction-chevron{width:18px;height:18px;color:var(--color-text-tertiary,#a3a3aa);place-items:center;transition:transform .14s;display:grid}.workspace-instruction-item.expanded .workspace-instruction-chevron{transform:rotate(180deg)}.workspace-instruction-chevron-svg{width:14px;height:14px}.workspace-instruction-preview{border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--color-background-primary,#101114) 92%, transparent);max-height:300px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;font-size:11px;line-height:1.55;overflow:auto}.workspace-instruction-preview[hidden]{display:none}.review-header{grid-template-columns:40px minmax(0,1fr) auto 20px}.review-title-group{gap:3px;min-width:0;display:grid}.review-summary{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.review-diff-file-stats{align-items:center;gap:8px;display:flex}.review-empty{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,13px)}.review-more{border:0;border-top:1px solid var(--tool-card-divider);width:100%;min-height:40px;color:var(--color-text-tertiary,#a3a3aa);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,12px);text-align:left;background:0 0;padding:0 12px}.review-more:hover{background:var(--tool-card-hover-bg);color:var(--color-text-primary,#f5f5f6)}.review-diff{max-height:520px;display:grid;overflow:hidden auto}.review-diff-files{gap:0;padding:0;display:grid}.review-diff-file{border:0;border-radius:0;overflow:hidden}.review-diff-file+.review-diff-file{border-top:1px solid var(--tool-card-divider)}.review-diff-file-header{width:100%;min-height:42px;color:var(--color-text-primary,#f5f5f6);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;padding:0 12px;display:grid}.review-file-kind{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 10%, transparent);width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);border-radius:6px;align-self:center;place-items:center;font-size:10px;font-weight:700;display:grid}.review-file-kind.added{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.review-file-kind.edited,.review-file-kind.renamed,.review-file-kind.renamed-edited{background:color-mix(in srgb, var(--color-warning-text,#e6b566) 12%, transparent);color:var(--color-warning-text,#e6b566)}.review-file-kind.deleted{background:color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent);color:var(--color-danger-text,#ee7676)}.review-single-file{overflow:hidden}.review-diff-file-header:hover{background:var(--tool-card-hover-bg)}.review-diff-file-name,.review-diff-file-stats{text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:20px;overflow:hidden}.review-diff-file-name{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.review-diff-file-name.renamed{text-overflow:clip;align-items:center;gap:6px;min-width:0;display:flex}.review-diff-file-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:calc(50% - 10px);overflow:hidden}.review-diff-file-path.previous{color:var(--color-text-tertiary,#a3a3aa)}.review-diff-file-path.current{color:var(--color-text-primary,#f5f5f6)}.review-diff-file-arrow{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);flex:none}.review-diff-file-stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);font-variant-numeric:tabular-nums;justify-content:flex-end;overflow:visible}.status{font-size:var(--font-text-sm-size,12px);padding:10px 12px}.status.muted{color:var(--color-text-secondary,#b7b7bf)}.status.error{color:var(--color-danger-text,#ee7676)}.pierre-diff,.pierre-file{--diffs-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-light-bg:var(--color-background-primary,#fff);--diffs-dark-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);--diffs-header-font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);--diffs-font-size:var(--font-text-sm-size,12px);--diffs-line-height:20px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;max-height:420px;display:block;overflow:auto}.text-payload{max-height:420px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;line-height:1.55;overflow:auto}.text-payload.bash{color:var(--color-text-primary,#f5f5f6);background:var(--color-background-primary,#101114)}@media (width<=520px){.tool-header{grid-template-columns:36px minmax(0,1fr) auto 18px;gap:9px;min-height:58px;padding:9px 10px}.tool-icon{border-radius:9px;width:36px;height:36px}.chevron{width:18px;height:18px}.review-header{grid-template-columns:36px minmax(0,1fr) auto 18px}.workspace-row{grid-template-columns:22px minmax(0,1fr);gap:2px 8px;padding-block:8px}.workspace-row-icon{grid-row:1/span 2;align-self:start}.workspace-row>.workspace-key,.workspace-row>.workspace-value,.workspace-row>.workspace-chip-list,.workspace-row>.workspace-instructions-content{grid-column:2}}
|