Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
fc32aa2
fix(codex): preserve literal installed MCP server names (#1638)
zts212653 Oct 20, 2026
c086765
feat(plugins): grant Xiangqi ordinary owner conversation access (#1637)
zts212653 Oct 20, 2026
01378dd
fix(codex): allow read-only turns in non-Git projects (#1635)
YukinaXSer Oct 20, 2026
05e87ff
feat: 简化成员配置并提供自动团队协作引导 (#1519)
whutzefengxie-ops Oct 20, 2026
1fc3e69
fix(codex): declare native context window in custom-model catalog (#1…
zhongmingLL Oct 20, 2026
b4ee5d1
fix(runtime): 统一能力配置根并恢复原生 Kimi 的协作 MCP (#1643)
whutzefengxie-ops Oct 21, 2026
0a62a7e
fix(plugins): refresh catalog on explicit reads (#1645)
mindfn Oct 21, 2026
36e325a
feat(F232): Works 内直接预览已发布的 HTML widget (#1642)
liu-zhengdong Oct 21, 2026
44fb36e
docs(rich-blocks): remind cats inline on* handlers are stripped in ht…
liu-zhengdong Oct 21, 2026
591af70
fix(plugin): restore Windows local directory install (#1650) (#1652)
EdgarR1170 Oct 21, 2026
1167a07
feat(test): add cross-platform test-home wrapper for Windows (#1628) …
EdgarR1170 Oct 21, 2026
063f459
fix(onboarding): 全新安装从空名单开始,确认后再创建成员 (#1655)
whutzefengxie-ops Oct 21, 2026
2701db8
fix(codex): preserve native tool configuration across lifecycle (#1659)
whutzefengxie-ops Oct 21, 2026
1baaed2
fix(acp): safely bootstrap audited Windows providers on data volumes …
whutzefengxie-ops Oct 21, 2026
05017a3
fix(web): Windows sidebar parity - fonts, tooltips, pending decisions…
whutzefengxie-ops Oct 21, 2026
3c0a200
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1649)
zts212653 Oct 21, 2026
3498e59
fix(runtime): recover Windows child executions without owner manifest…
amazing-fish Oct 22, 2026
d74df47
sync: full source update with verified catalogue test repair
zts212653 Oct 22, 2026
80f0678
fix(windows): use Node clean-path in package scripts (#1634) (#1675)
EdgarR1170 Oct 22, 2026
7f8c01f
fix(settings): keep plugins wrapper height-constrained so plugin deta…
mindfn Oct 22, 2026
fd502b0
fix(ci): report public test timing targets as warnings (#1686)
zts212653 Oct 22, 2026
44a39e8
fix(ci): fetch history for MCP lineage checks (#1687)
zts212653 Oct 22, 2026
35e979e
fix(windows): run desktop npm dependencies through npm-cli.js (#1679)…
EdgarR1170 Oct 22, 2026
c00d364
fix(windows): make stale-process entrypoint explicit (#1629) (#1684)
EdgarR1170 Oct 22, 2026
584c585
fix(plugins): synchronize MCP lifecycle and contract compatibility (#…
mindfn Oct 22, 2026
1bc31c3
feat(agent-session): 会话契约与插件声明的 ACP Agent (#1665)
liu-zhengdong Oct 22, 2026
1f59d5c
fix: preserve configured proxies in isolated AGY launches (#1696)
YukinaXSer Oct 22, 2026
9ee517a
fix: reconcile invocation history with durable terminal lifecycle (#1…
amazing-fish Oct 22, 2026
d2d21e2
fix(claude): inject member context window into third-party CLI runs (…
zhongmingLL Oct 22, 2026
fb889d8
fix(runtime): use stable process birth identity across clock jumps (#…
zhongmingLL Oct 22, 2026
f5516af
feat(acp): configure plugin client libraries and persist role binding…
whutzefengxie-ops Oct 22, 2026
74ad585
fix(windows): pass browser test env through Node wrapper (#1634) (#1691)
EdgarR1170 Oct 22, 2026
c7be475
fix(windows): make plugin native Codex symlink EPERM actionable (#162…
EdgarR1170 Oct 22, 2026
76c2cda
fix(plugins): load local state before remote discovery (#1690)
mindfn Oct 22, 2026
2245dc6
docs(acp): clarify DSH custom LLM profile configuration (#1705)
whutzefengxie-ops Oct 22, 2026
5f1e8b8
fix(memory): respect runtimeEditable in IndexStatus feature flags (#1…
amazing-fish Oct 22, 2026
e2d9c24
fix(plugins): register MCP runtime credentials through env references…
mindfn Oct 22, 2026
538f33f
fix(windows): run API dev through a Node supervisor (#1634) (#1700)
EdgarR1170 Oct 22, 2026
d4b18b4
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1694)
zts212653 Oct 22, 2026
ecd1ba6
fix(windows): diagnose managed Codex layout symlink EPERM (#1709) (#1…
EdgarR1170 Oct 23, 2026
06225f2
fix(desktop): remove critical resource junction dependency on Windows…
whutzefengxie-ops Oct 23, 2026
f3d823d
fix(pi): 持久化内置桥原生会话并修复空响应转换 (#1706)
whutzefengxie-ops Oct 23, 2026
c14bab7
feat(F306): iCode carrier - ACP dialect, HTTP member gateway and ques…
yun1091724578 Oct 23, 2026
96b3688
fix(chat): use the member shell for plugin messages (#1712)
mindfn Oct 23, 2026
f7f64cc
feat(dsh): reuse custom LLM configuration for ACP members (#1707)
whutzefengxie-ops Oct 23, 2026
99c1ca9
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1714)
zts212653 Oct 23, 2026
b4cd5d6
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1715)
zts212653 Oct 24, 2026
14e32aa
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1716)
zts212653 Oct 24, 2026
eb05c1c
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1717)
zts212653 Oct 25, 2026
140670f
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1718)
zts212653 Oct 26, 2026
f005686
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1719)
zts212653 Oct 26, 2026
6d6ab22
fix(plugin): remove duplicate Host SDK permission state
mindfn Oct 26, 2026
06b0f47
fix(plugins): preserve historical controller receipt replays
mindfn Oct 26, 2026
dfc82b7
chore(mcp): refresh plugin install schema snapshot
mindfn Oct 26, 2026
a242f45
test(plugins): align recovery checks with current MCP carriers
mindfn Oct 26, 2026
fa1dc90
sync: cat-cafe 2c7987ca2bf5 → clowder-ai (daily draft) (#1721)
zts212653 Oct 26, 2026
f2a4ed8
test(plugins): retire remaining API grant fixture assumptions
mindfn Oct 26, 2026
40f83e1
test(plugins): exercise real ACP recovery lifecycle conflict
mindfn Oct 26, 2026
4dfcdd8
chore(fork): include latest upstream in Host cleanup candidate
mindfn Oct 26, 2026
c99c6f7
chore(fork): retain fork customizations on the complete Host cleanup
mindfn Oct 26, 2026
f517b82
chore(fork): record develop_base rebuild ancestry
mindfn 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.
10 changes: 7 additions & 3 deletions .claude/hooks/f24-compaction.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
// Managed Claude compaction carrier (Node canonical, #1542 successor of #1456).
// No shell utilities, no persistent local state, no project writes.
// Credit: ported from #1456 (.claude/hooks/f24-compaction.mjs by @amazing-fish).
let productName = '';
async function main() {
const invocationId = process.env.CAT_CAFE_INVOCATION_ID;
const callbackToken = process.env.CAT_CAFE_CALLBACK_TOKEN;
// Project settings also apply to ordinary Claude CLI sessions.
if (!invocationId || !callbackToken) return;
// Installed carrier dependencies are rooted at the trusted install, never cwd.
const { deploymentDefaults } = await import('../../packages/api/dist/agent-hooks/deployment-defaults.js');
productName = deploymentDefaults.brand.name;
let raw = '';
for await (const chunk of process.stdin) {
raw += chunk;
Expand All @@ -16,7 +20,7 @@ async function main() {
if (typeof input.session_id !== 'string' || !input.session_id || input.session_id.length > 500) {
throw new Error('hook_session_id_invalid');
}
const port = process.env.API_SERVER_PORT ?? '3004';
const port = process.env.API_SERVER_PORT ?? String(deploymentDefaults.apiPort);
if (!/^\d+$/.test(port) || Number(port) < 1 || Number(port) > 65535) throw new Error('hook_api_port_invalid');
const headers = {
'X-Invocation-Id': invocationId,
Expand Down Expand Up @@ -52,7 +56,7 @@ async function main() {
const result = await response.json();
if (phase === 'pre') {
if (result.contextEpoch?.status !== 'observed') throw new Error('hook_compaction_not_observed');
console.log(JSON.stringify({ systemMessage: 'Clowder AI recorded this invocation context compaction.' }));
console.log(JSON.stringify({ systemMessage: `${productName} recorded this invocation context compaction.` }));
} else {
if (result.postCompact?.status !== 'projected' || typeof result.postCompact.contextPacket !== 'string') {
throw new Error('hook_cold_projection_unavailable');
Expand All @@ -71,6 +75,6 @@ async function main() {
main().catch((error) => {
// Never print response bodies, callback credentials, or user payloads.
const reason = /^hook_[a-z_0-9]+$/.test(error.message) ? error.message : 'hook_request_failed';
console.error(`Clowder AI compaction hook: ${reason}`);
console.error(`${productName ? `${productName} ` : ''}compaction hook: ${reason}`);
process.exitCode = 1;
});
7 changes: 5 additions & 2 deletions .claude/hooks/f24-post-compact-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')

API_PORT="${API_SERVER_PORT:-3004}"
INVOCATION_ID="${CAT_CAFE_INVOCATION_ID:-}"
CALLBACK_TOKEN="${CAT_CAFE_CALLBACK_TOKEN:-}"

Expand Down Expand Up @@ -48,14 +47,18 @@ if [ "$AGE" -gt 1800 ]; then
fi

# Fetch latest sealed session digest (best-effort)
SCRIPT_ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) || exit 1
API_PORT="${API_SERVER_PORT:-$(node "$SCRIPT_ROOT/scripts/read-deployment-default.mjs" apiPort)}"
if [ -z "$API_PORT" ]; then exit 1; fi
DIGEST=$(curl -sf --max-time 5 \
-H "X-Invocation-Id: ${INVOCATION_ID}" \
-H "X-Callback-Token: ${CALLBACK_TOKEN}" \
"http://localhost:${API_PORT}/api/sessions/latest-digest?cliSessionId=$SESSION_ID" 2>/dev/null)
DIGEST_STATUS=$?

if [ "$DIGEST_STATUS" -ne 0 ] || [ -z "$DIGEST" ]; then
CONTEXT_PACKET="[F296 post-compact unsupported: Clowder AI projection unavailable]"
PRODUCT_NAME=$(node "$SCRIPT_ROOT/scripts/read-deployment-default.mjs" brand.name) || exit 1
CONTEXT_PACKET="[F296 post-compact unsupported: ${PRODUCT_NAME} projection unavailable]"
else
PROJECTION_STATUS=$(echo "$DIGEST" | jq -r '.postCompact.status // "unsupported"')
if [ "$PROJECTION_STATUS" = "projected" ]; then
Expand Down
4 changes: 3 additions & 1 deletion .claude/hooks/f24-pre-compact.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ TRIGGER=$(echo "$INPUT" | jq -r '.trigger')
LOG_FILE="/tmp/cat-cafe-hook-diagnostic.log"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] pre-compact fired, session=$SESSION_ID, trigger=$TRIGGER" >> "$LOG_FILE"

API_PORT="${API_SERVER_PORT:-3004}"
SCRIPT_ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) || exit 1
API_PORT="${API_SERVER_PORT:-$(node "$SCRIPT_ROOT/scripts/read-deployment-default.mjs" apiPort)}"
if [ -z "$API_PORT" ]; then exit 1; fi
INVOCATION_ID="${CAT_CAFE_INVOCATION_ID:-}"
CALLBACK_TOKEN="${CAT_CAFE_CALLBACK_TOKEN:-}"

Expand Down
10 changes: 5 additions & 5 deletions .claude/hooks/user-level/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# 用户级 Hooks(跟着人走,所有项目生效)

这些 hook 放在 `~/.claude/hooks/`(用户级),不是项目级。
项目里这份是**参考副本**,方便其他猫或新环境部署。
项目里这份是安装模板。安装器从当前部署档案绑定称谓;安装后的脚本不依赖当前项目、API 或配置文件。

## 部署方式

### Claude Code
```bash
cp .claude/hooks/user-level/session-*.sh ~/.claude/hooks/
chmod +x ~/.claude/hooks/session-*.sh # macOS/Linux; Windows Git Bash 可跳过
pnpm --filter @cat-cafe/api build
node desktop/scripts/sync-agent-hooks-offline.mjs --project-root "$PWD" --target-root "$HOME"
```
然后在 `~/.claude/settings.json` 的 `hooks` 里加 SessionStart 和 Stop 条目。
此入口与 Hub 的 Sync hooks 共用 producer,会写入 SessionStart 和 Stop 条目。
可参考同目录的 `claude-settings.template.json`;模板只使用 `$HOME`,不携带维护者机器上的绝对路径。
建议优先用 Hub 的 Sync hooks 一键修复;手动复制 template 后,Hub 可能因路径规范化差异继续提示 stale,此时按提示再 sync 一次即可。
也可以用 Hub 的 Sync hooks 一键修复。不要直接复制 `.sh` 模板;称谓变量必须由安装器作为数据绑定,不能在 shell 中求值执行。

> **Windows 用户**:需要安装 [Git for Windows](https://gitforwindows.org/)(提供 Git Bash)。
> Hook 命令通过 `bash` 显式调用,确保跨平台执行。如果不装 Git Bash,
Expand Down
6 changes: 3 additions & 3 deletions .claude/hooks/user-level/session-start-recall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ if [ -n "$UNTRACKED_DOCS" ]; then
WARNINGS="${WARNINGS}
⚠️ docs/ 下有未跟踪的 .md 文件(可能是你写的,也可能是别的猫正在写):
${UNTRACKED_DOCS}
→ 是你写的就 commit push;不是你写的别动,也别拿去问co-creator或跨线程催(写它的猫可能正在提交)
→ 是你写的就 commit push;不是你写的别动,也别拿去问${CO_CREATOR_ROLE}或跨线程催(写它的猫可能正在提交)
"
fi

Expand All @@ -131,7 +131,7 @@ if [ -n "$ROOT_IMAGES" ]; then
WARNINGS="${WARNINGS}
⚠️ 根目录有图片文件(截图应放 assets/screenshots/,设计稿放 designs/):
${ROOT_IMAGES}
→ 首个发现者直接处置,不等 owner、不跨线程协调、不问 operator:截图 → mv assets/screenshots/(gitignored,本体不 commit);明显设计稿 → designs/;未知文件不删。FYI 仅在零成本定位来源时事后发一行
→ 首个发现者直接处置,不等 owner、不跨线程协调、不问 ${DECISION_ROLE}:截图 → mv assets/screenshots/(gitignored,本体不 commit);明显设计稿 → designs/;未知文件不删。FYI 仅在零成本定位来源时事后发一行
"
fi

Expand All @@ -143,7 +143,7 @@ if [ -n "$ROOT_CLUTTER" ]; then
WARNINGS="${WARNINGS}
⚠️ 根目录有不该在这里的文件:
${ROOT_CLUTTER}
→ 是你放的就收走(截图 → assets/screenshots/,设计稿 → designs/);不是你放的别动,也别拿去问co-creator;未知文件不删
→ 是你放的就收走(截图 → assets/screenshots/,设计稿 → designs/);不是你放的别动,也别拿去问${CO_CREATOR_ROLE};未知文件不删
"
fi

Expand Down
6 changes: 3 additions & 3 deletions .claude/hooks/user-level/session-stop-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ if [ -n "$UNTRACKED_DOCS" ]; then
WARNINGS="${WARNINGS}
⚠️ 收尾检查:docs/ 下有未跟踪的 .md 文件(可能是你写的,也可能是别的猫正在写):
${UNTRACKED_DOCS}
→ 是你写的,先 commit push 再收工;不是你写的别动,也别拿去问co-creator
→ 是你写的,先 commit push 再收工;不是你写的别动,也别拿去问${CO_CREATOR_ROLE}
"
fi

Expand All @@ -67,7 +67,7 @@ if [ -n "$ROOT_IMAGES" ]; then
WARNINGS="${WARNINGS}
⚠️ 收尾检查:根目录有图片文件(截图应放 assets/screenshots/):
${ROOT_IMAGES}
→ 别走!首个发现者直接收拾,不跨线程协调、不问 operator:截图 mv assets/screenshots/(不 commit);设计稿 → designs/;未知文件不删
→ 别走!首个发现者直接收拾,不跨线程协调、不问 ${DECISION_ROLE}:截图 mv assets/screenshots/(不 commit);设计稿 → designs/;未知文件不删
"
fi

Expand All @@ -79,7 +79,7 @@ if [ -n "$ROOT_CLUTTER" ]; then
WARNINGS="${WARNINGS}
⚠️ 收尾检查:根目录有杂物文件:
${ROOT_CLUTTER}
→ 是你放的就收走再收工;不是你放的别动,也别拿去问co-creator;未知文件不删
→ 是你放的就收走再收工;不是你放的别动,也别拿去问${CO_CREATOR_ROLE};未知文件不删
"
fi

Expand Down
21 changes: 21 additions & 0 deletions .dir-exceptions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
{
"exceptions": [
{
"path": "packages/api/src/domains/collaborative-content/artifact-review",
"owner": "codex-astra",
"reason": "2026-10-21 daily sync: reviewed #5799 adds response-judgment and response-judgment-return, taking this directory from 24 to 26 files. They share the review reducer, return intent, sealed audience and owner revision checks. Keep those reviewed boundaries intact for this export; reassess a response/return subgroup with its store imports before expiry.",
"expiresAt": "2026-10-31",
"ticket": "F326 / cat-cafe#5799 / clowder-ai#1649"
},
{
"path": "packages/api/src/domains/workspace",
"owner": "codex-astra",
"reason": "2026-10-21 daily sync: reviewed #5799 adds workspace-video-snapshot, taking this directory from 24 to 25 files. The request-scoped immutable copy shares the existing workspace source revision, stream lifetime and security errors. Reassess the content-source/video snapshot subgroup together before expiry rather than move one authority-sensitive adapter only to reduce this count.",
"expiresAt": "2026-10-31",
"ticket": "F063/F326 / cat-cafe#5799 / clowder-ai#1649"
},
{
"path": "packages/api/src/infrastructure/capability-evolution/adapters",
"owner": "codex-astra",
"reason": "2026-10-21 daily sync: reviewed #5854 adds archive-source-repository, taking this directory from 24 to 25 files. The shared immutable historical repository identity is consumed by the Microduck and request-review adapters; it must not become deployment branding. Reassess an archive-provenance module boundary with all consumers before expiry, preserving those signed source coordinates.",
"expiresAt": "2026-10-31",
"ticket": "F330/F311 / cat-cafe#5854 / clowder-ai#1649"
},
{
"path": "packages/api/src/domains/collaborative-content/collective-artifact",
"owner": "codex61-sol",
Expand Down
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ EMBED_MODE=off
# TELEMETRY_HMAC_SALT=

# ── Logging 日志(可选)─────────────────────────────────────
# Windows ACP bootstrap and audit admission are separate, restart-only Host settings.
# Persist intranet configuration once in Host .env; plugins cannot enable these policies.
# CAT_CAFE_WINDOWS_ACP_BOOTSTRAP_MODE=strict
# CAT_CAFE_ACP_BOOTSTRAP_CONFIG_AUDIT_MODE=required
# trusted-host skips ancestor trust only; warn-bootstrap-root permits only verified existing ACP root changes.
# The legacy exact CAT_CAFE_TRUSTED_HOST_COMPATIBILITY=1 maps missing new keys to that narrow preset.
# Explicit strict/required win; audit exceptions are inactive outside Windows trusted-host.
# Deprecated alias remains for at least two applicable releases and 90 days, then review (no timed disable).
# ACP strict is unrelated to CAT_CAFE_STRICT_PROFILE_DEFAULTS.
# AUDIT_LOG_DIR changes require an API restart; existing explicit paths are never silently relocated.
# Log level: debug, info, warn, error

LOG_LEVEL=info
Expand Down
3 changes: 3 additions & 0 deletions .githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
set -euo pipefail
exec node "$(dirname "${BASH_SOURCE[0]}")/../scripts/secret-git-guard.mjs" message "$1"
5 changes: 5 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

BRANCH=$(git branch --show-current 2>/dev/null)
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
# Read INDEX blobs, not the worktree; do not print matched content on failure.
SECRET_GUARD="$(dirname "${BASH_SOURCE[0]}")/../scripts/secret-git-guard.mjs"
if ! node "$SECRET_GUARD" index; then
exit 1
fi
STAGED_FILES="$(git diff --cached --name-only || true)"
VERDICT_BRANCH_DOMAIN=""
VERDICT_ID=""
Expand Down
26 changes: 24 additions & 2 deletions .github/scripts/check-public-test-ci-contract.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { readFileSync } from 'node:fs';
import { parse } from 'yaml';

const workflow = parse(readFileSync(new URL('../workflows/ci.yml', import.meta.url), 'utf8'));
const lintCheckout = workflow.jobs.lint.steps.find((step) => step.uses === 'actions/checkout@v4');
assert.equal(
lintCheckout?.with?.['fetch-depth'],
0,
'the lint job runs MCP lineage checks and must fetch complete Git history',
);
const runtimeJobs = ['public-test-prepare', 'public-test-shards', 'public-test-summary'];
const versions = runtimeJobs.map((jobName) => {
const setupNode = workflow.jobs[jobName].steps.find((step) => step.uses === 'actions/setup-node@v4');
Expand Down Expand Up @@ -116,11 +122,27 @@ for (const [pattern, message] of [
]) {
assert.match(distributableLauncher, pattern, message);
}
assert.doesNotMatch(
summaryStep.run,
/--max-critical-path-ms\b/,
'public-test coverage must not fail solely because runner-dependent timing exceeds a target',
);
assert.match(
summaryStep.run,
/--max-critical-path-ms 600000(?:\s|$)/,
'public-test evidence must fail when the measured critical path exceeds 10 minutes',
/::warning title=Public test timing::/,
'public-test timing above the optimization target must remain visible as a warning',
);
assert.match(
summaryStep.run,
/GITHUB_STEP_SUMMARY/,
'public-test timing and runner consumption must remain visible in the job summary',
);
for (const job of ['public-test-shards', 'public-test-summary', 'public-test-serial']) {
assert.ok(
Number.isInteger(workflow.jobs[job]['timeout-minutes']) && workflow.jobs[job]['timeout-minutes'] > 0,
`${job} must retain a bounded job timeout for stuck processes`,
);
}

process.stdout.write(
`public-test CI contract OK (Node ${versions[0]}, owner ${distributableShardStep.env.DEFAULT_OWNER_USER_ID})\n`,
Expand Down
16 changes: 2 additions & 14 deletions .github/workflows/build-mac-dmg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
build:
name: DMG (${{ matrix.arch }})
runs-on: ${{ matrix.arch == 'x64' && 'macos-15-intel' || 'macos-latest' }}
timeout-minutes: 60
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
Expand All @@ -59,19 +59,6 @@ jobs:
with:
fetch-depth: 0

- name: Sync desktop/package.json version
shell: bash
run: |
VERSION="${{ inputs.version }}"
node -e "
const fs = require('fs');
const path = 'desktop/package.json';
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
pkg.version = '$VERSION';
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
console.log('desktop/package.json version =', pkg.version);
"

- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
Expand All @@ -80,6 +67,7 @@ jobs:

- name: Build macOS DMG (${{ matrix.arch }})
env:
NODE_OPTIONS: --max-old-space-size=4096
CATCAFE_VERSION: ${{ inputs.version }}
run: |
chmod +x desktop/scripts/build-mac.sh
Expand Down
23 changes: 10 additions & 13 deletions .github/workflows/build-windows-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,6 @@ jobs:
with:
fetch-depth: 0

- name: Sync desktop/package.json version
shell: bash
run: |
VERSION="${{ inputs.version }}"
node -e "
const fs = require('fs');
const path = 'desktop/package.json';
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
pkg.version = '$VERSION';
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
console.log('desktop/package.json version =', pkg.version);
"

- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
Expand All @@ -73,8 +60,18 @@ jobs:
$env:Path += ";C:\Program Files (x86)\Inno Setup 6"
iscc.exe /? | Select-Object -First 1

- name: Test native installer preparation and menu behavior
shell: pwsh
run: |
$env:ISCC_EXE = @('C:\Program Files\Inno Setup 7\ISCC.exe', 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe') |
Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1
if (-not $env:ISCC_EXE) { throw 'Native Inno compiler was not found after installation' }
node --test desktop/installer-preparation-log.test.js desktop/installer-no-icons.test.js
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Build Windows installer
env:
NODE_OPTIONS: --max-old-space-size=4096
CATCAFE_VERSION: ${{ inputs.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: pwsh
Expand Down
Loading