mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 11:20:42 +01:00
Merge origin/master and renumber routine migration
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
commit
8f70a8e125
374 files changed
+95243
-10084
No files matched your search
@@ -104,6 +104,7 @@ test("release verify workflow covers the same split test surface as stable PR ve
|
||||
assert.match(verifyWorkflow, /node \.\/scripts\/release-package-map\.mjs check/);
|
||||
assert.match(verifyWorkflow, /pnpm -r typecheck/);
|
||||
assert.match(verifyWorkflow, /pnpm build/);
|
||||
assert.match(verifyWorkflow, /pnpm --filter @paperclipai\/paperclip-runner check:all/);
|
||||
|
||||
for (const group of ["general-server", "general-workspaces-a", "general-workspaces-b"]) {
|
||||
assert.match(verifyWorkflow, new RegExp(`group: ${group}`));
|
||||
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
# Assert that PID 1 in this container reaps orphans the kernel re-parents onto it.
|
||||
#
|
||||
# Regression test for the zombie-exhaustion outage: with node as PID 1 and no
|
||||
# init, orphaned descendants of agent runs (git, claude, esbuild, sh, ...) are
|
||||
# never wait()ed, so they pin as zombies at ~79/h until the cgroup pid limit is
|
||||
# exhausted and *every* fork() in the container fails.
|
||||
#
|
||||
# Designed to run inside the image under its real ENTRYPOINT, so PID 1 is
|
||||
# exactly what a production container gets:
|
||||
#
|
||||
# docker run --rm -i <image> sh -s < scripts/assert-orphan-reaping.sh
|
||||
#
|
||||
# Exits 0 when the orphan is reaped, non-zero (with the observed state) when it
|
||||
# is left in Z.
|
||||
set -e
|
||||
|
||||
init_comm="$(cat /proc/1/comm)"
|
||||
echo "PID 1 = $init_comm"
|
||||
if [ "$init_comm" != "tini" ]; then
|
||||
echo "FAIL: PID 1 is '$init_comm', expected an init (tini)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pidfile="$(mktemp)"
|
||||
trap 'rm -f "$pidfile"' EXIT
|
||||
|
||||
# Read a field of /proc/<pid>/stat past the comm field, so a command name
|
||||
# containing spaces or parens cannot shift the offset. Field 1 of the remainder
|
||||
# is the state, field 2 is the ppid. Empty output means the pid is gone.
|
||||
stat_field() {
|
||||
sed -e 's/^.*) //' "/proc/$1/stat" 2>/dev/null | cut -d' ' -f"$2"
|
||||
}
|
||||
|
||||
# The leader exits immediately, orphaning the grandchild onto PID 1. The
|
||||
# grandchild publishes its own pid, then exits ~5s later. That lifetime is what
|
||||
# keeps the adoption check below honest: it must always land on a live process,
|
||||
# never on a corpse whose exit merely happened to outrun a slow leader.
|
||||
sh -c 'sh -c '\''echo $$ > "$0"; exec sleep 5'\'' "$1" & exit 0' _ "$pidfile"
|
||||
|
||||
i=0
|
||||
while [ ! -s "$pidfile" ]; do
|
||||
i=$((i + 1))
|
||||
if [ "$i" -gt 100 ]; then
|
||||
echo "FAIL: grandchild never reported its pid" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.05
|
||||
done
|
||||
gpid="$(cat "$pidfile")"
|
||||
|
||||
# The kernel re-parents the grandchild only once the leader has finished
|
||||
# exiting, and that can lag the grandchild's pid-file write. Sampling the ppid
|
||||
# once would read a leader that is merely slow to exit as a re-parenting
|
||||
# failure, so poll instead: the leader exits unconditionally, so ppid 1 is
|
||||
# reached in bounded time whenever adoption works at all.
|
||||
i=0
|
||||
while :; do
|
||||
ppid="$(stat_field "$gpid" 2)"
|
||||
if [ "$ppid" = "1" ]; then
|
||||
break
|
||||
fi
|
||||
if [ -z "$ppid" ]; then
|
||||
echo "FAIL: grandchild pid $gpid vanished before adoption could be observed; the probe proved nothing" >&2
|
||||
exit 1
|
||||
fi
|
||||
i=$((i + 1))
|
||||
if [ "$i" -gt 20 ]; then
|
||||
echo "FAIL: grandchild still parented to $ppid after 20 polls, never adopted by PID 1; the probe proved nothing" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.05
|
||||
done
|
||||
echo "orphaned grandchild pid=$gpid reparented to ppid=$ppid"
|
||||
|
||||
# Give an unreaped zombie a generous window to show itself before calling the
|
||||
# reap successful -- a pass here must mean "reaped", never "checked too early".
|
||||
i=0
|
||||
while [ "$i" -lt 100 ]; do
|
||||
if [ ! -e "/proc/$gpid" ]; then
|
||||
echo "PASS: PID 1 reaped orphaned pid $gpid"
|
||||
exit 0
|
||||
fi
|
||||
i=$((i + 1))
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
state="$(stat_field "$gpid" 1)"
|
||||
echo "FAIL: pid $gpid still present after 100 polls (state=$state); PID 1 ('$init_comm') is not reaping adopted orphans" >&2
|
||||
exit 1
|
||||
@@ -43,4 +43,9 @@ echo "==> Verifying key binaries in image"
|
||||
claude --version 2>/dev/null || echo "claude CLI not found (OK in minimal builds)"
|
||||
'
|
||||
|
||||
echo "==> Verifying PID 1 is an init that reaps adopted orphans"
|
||||
# Piped in as CMD (`sh -s`) rather than `--entrypoint`, so the image's real
|
||||
# ENTRYPOINT still runs and PID 1 is exactly what a production container gets.
|
||||
"$RUNTIME" run --rm -i "$IMAGE_TAG" sh -s < "$REPO_ROOT/scripts/assert-orphan-reaping.sh"
|
||||
|
||||
echo "PASS: Docker build test succeeded"
|
||||
@@ -123,6 +123,26 @@ fi
|
||||
|
||||
subjects="$(git -C "$repo_dir" log --no-merges --format='%s' "$range")"
|
||||
|
||||
# Best-effort thoroughness: nest each referenced PR's own summary under its
|
||||
# subject line, so the skeleton is a genuinely thorough raw document at
|
||||
# creation time instead of a bare commit list. Prefers the PR template's
|
||||
# "What Changed" bullets, falls back to the first prose lines. Degrades
|
||||
# silently when gh or the network is unavailable (tests, offline runs);
|
||||
# set DRAFT_NOTES_SKIP_PR_ENRICHMENT=1 to disable explicitly.
|
||||
enrich_pr() {
|
||||
local pr_num="$1" pr_body excerpt
|
||||
[ "${DRAFT_NOTES_SKIP_PR_ENRICHMENT:-0}" = "1" ] && return 0
|
||||
pr_body="$(cd "$repo_dir" && gh pr view "$pr_num" --json body --jq .body 2>/dev/null || true)"
|
||||
[ -n "$pr_body" ] || return 0
|
||||
if printf '%s\n' "$pr_body" | grep -q '^## What Changed'; then
|
||||
excerpt="$(printf '%s\n' "$pr_body" | sed -n '/^## What Changed/,/^## /p' | grep -E '^- ' | head -3 || true)"
|
||||
else
|
||||
excerpt="$(printf '%s\n' "$pr_body" | grep -vE '^[[:space:]]*$|^#|^>|^<!--' | head -2 || true)"
|
||||
fi
|
||||
[ -n "$excerpt" ] || return 0
|
||||
printf '%s\n' "$excerpt" | sed 's/^/ > /'
|
||||
}
|
||||
|
||||
section() {
|
||||
local title="$1" pattern="$2" invert="${3:-false}" body
|
||||
if [ "$invert" = true ]; then
|
||||
@@ -132,7 +152,14 @@ section() {
|
||||
fi
|
||||
[ -n "$body" ] || return 0
|
||||
printf '## %s\n\n' "$title"
|
||||
printf '%s\n' "$body" | sed 's/^/- /'
|
||||
while IFS= read -r subject_line; do
|
||||
[ -n "$subject_line" ] || continue
|
||||
printf -- '- %s\n' "$subject_line"
|
||||
pr_ref="$(printf '%s' "$subject_line" | grep -oE '\(#[0-9]+\)$' | tr -dc '0-9' || true)"
|
||||
if [ -n "$pr_ref" ]; then
|
||||
enrich_pr "$pr_ref"
|
||||
fi
|
||||
done <<< "$body"
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdtempSync, readFileSync } from "node:fs";
|
||||
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
@@ -137,6 +137,76 @@ test("writes to releases/beta/v<version>.md inside the repo by default", () => {
|
||||
assert.match(body, /- feat: default path \(#1\)/);
|
||||
});
|
||||
|
||||
test("nests PR summaries under subjects when gh can serve them", () => {
|
||||
const dir = makeFixtureRepo();
|
||||
commit(dir, "feat: enriched work (#42)");
|
||||
git(dir, "tag", "beta/v2026.100.0-beta.0");
|
||||
|
||||
const binDir = join(dir, "fake-bin");
|
||||
execFileSync("mkdir", ["-p", binDir]);
|
||||
writeFileSync(
|
||||
join(binDir, "gh"),
|
||||
`#!/usr/bin/env bash
|
||||
echo "## Thinking Path"
|
||||
echo ""
|
||||
echo "## What Changed"
|
||||
echo ""
|
||||
echo "- Adds the enriched thing"
|
||||
echo "- Covers it with tests"
|
||||
echo ""
|
||||
echo "## Risks"
|
||||
`,
|
||||
{ mode: 0o755 }
|
||||
);
|
||||
|
||||
const out = join(dir, "draft.md");
|
||||
execFileSync(
|
||||
"bash",
|
||||
[script, "2026.100.0-beta.0", "--repo-dir", dir, "--out", out],
|
||||
{ encoding: "utf8", env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` } }
|
||||
);
|
||||
const body = readFileSync(out, "utf8");
|
||||
assert.match(body, /- feat: enriched work \(#42\)\n > - Adds the enriched thing\n > - Covers it with tests/);
|
||||
});
|
||||
|
||||
test("survives a PR body whose What Changed section has no bullets", () => {
|
||||
const dir = makeFixtureRepo();
|
||||
commit(dir, "feat: sparse body (#9)");
|
||||
git(dir, "tag", "beta/v2026.100.0-beta.0");
|
||||
|
||||
const binDir = join(dir, "fake-bin");
|
||||
execFileSync("mkdir", ["-p", binDir]);
|
||||
writeFileSync(
|
||||
join(binDir, "gh"),
|
||||
`#!/usr/bin/env bash
|
||||
echo "## What Changed"
|
||||
echo ""
|
||||
echo "## Risks"
|
||||
`,
|
||||
{ mode: 0o755 }
|
||||
);
|
||||
|
||||
const out = join(dir, "draft.md");
|
||||
execFileSync(
|
||||
"bash",
|
||||
[script, "2026.100.0-beta.0", "--repo-dir", dir, "--out", out],
|
||||
{ encoding: "utf8", env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` } }
|
||||
);
|
||||
const body = readFileSync(out, "utf8");
|
||||
assert.match(body, /- feat: sparse body \(#9\)\n/);
|
||||
});
|
||||
|
||||
test("skeleton stays clean when enrichment is unavailable", () => {
|
||||
const dir = makeFixtureRepo();
|
||||
commit(dir, "feat: plain work (#7)");
|
||||
git(dir, "tag", "beta/v2026.100.0-beta.0");
|
||||
|
||||
const { body } = runDraft(dir, "2026.100.0-beta.0");
|
||||
|
||||
assert.match(body, /- feat: plain work \(#7\)\n/);
|
||||
assert.doesNotMatch(body, / > /);
|
||||
});
|
||||
|
||||
test("rejects a malformed beta version", () => {
|
||||
const dir = makeFixtureRepo();
|
||||
assert.throws(() =>
|
||||
|
||||
@@ -1,285 +1,410 @@
|
||||
{
|
||||
"$comment": "Per-suite wall-clock durations (ms) for the general-server vitest lane, used by scripts/general-server-shard.mjs to balance suites across the PR shard matrix. Sampled from a real PR run of .github/workflows/pr.yml (actions run 30930345729, 2026-08-04) by diffing consecutive per-suite completion timestamps in the 'Run grouped general test suites' logs \u2014 that captures each suite's true serial cost (import + collect + tests), not just the vitest-reported test time. Suites missing here get the median weight, so the manifest only needs occasional refreshes.",
|
||||
"unit": "ms",
|
||||
"$comment": "Per-suite wall-clock durations (ms) for the general-server vitest lane, used by scripts/general-server-shard.mjs to balance suites across the PR shard matrix. Sampled from a real PR run of .github/workflows/pr.yml (actions run 32708351172, 2026-08-24) by diffing consecutive per-suite completion timestamps in the 'Run grouped general test suites' logs \u2014 that captures each suite's true serial cost (import + collect + tests), not just the vitest-reported test time. Suites missing here get the median weight, so the manifest only needs occasional refreshes.",
|
||||
"durations": {
|
||||
"server/src/__tests__/access-service.test.ts": 4415,
|
||||
"server/src/__tests__/access-validators.test.ts": 385,
|
||||
"server/src/__tests__/activity-log-responsible-user.test.ts": 8591,
|
||||
"server/src/__tests__/activity-service.test.ts": 4704,
|
||||
"server/src/__tests__/adapter-models.test.ts": 875,
|
||||
"server/src/__tests__/adapter-registry.test.ts": 880,
|
||||
"server/src/__tests__/adapter-session-codecs.test.ts": 343,
|
||||
"server/src/__tests__/agent-auth-jwt.test.ts": 408,
|
||||
"server/src/__tests__/agent-auth-middleware.test.ts": 1102,
|
||||
"server/src/__tests__/agent-instructions-service.test.ts": 1648,
|
||||
"server/src/__tests__/agent-invokability.test.ts": 2416,
|
||||
"server/src/__tests__/agent-permissions-service.test.ts": 439,
|
||||
"server/src/__tests__/agent-shortname-collision.test.ts": 1432,
|
||||
"server/src/__tests__/agent-skill-contract.test.ts": 218,
|
||||
"server/src/__tests__/agents-adapter-config-user-secret.test.ts": 4910,
|
||||
"server/src/__tests__/agents-pending-approval-config.test.ts": 4632,
|
||||
"server/src/__tests__/agents-service-clear-error.test.ts": 7537,
|
||||
"server/src/__tests__/agents-service-secret-bindings.test.ts": 4929,
|
||||
"server/src/__tests__/api-compression.test.ts": 337,
|
||||
"server/src/__tests__/app-hmr-port.test.ts": 4092,
|
||||
"server/src/__tests__/app-private-hostname-gate.test.ts": 2486,
|
||||
"server/src/__tests__/app-vite-dev-routing.test.ts": 2494,
|
||||
"server/src/__tests__/approvals-service.test.ts": 962,
|
||||
"server/src/__tests__/attachment-types.test.ts": 397,
|
||||
"server/src/__tests__/attention-service.test.ts": 6385,
|
||||
"server/src/__tests__/authorization-service.test.ts": 5178,
|
||||
"server/src/__tests__/aws-secrets-manager-provider.test.ts": 234,
|
||||
"server/src/__tests__/better-auth.test.ts": 707,
|
||||
"server/src/__tests__/board-claim.test.ts": 4169,
|
||||
"server/src/__tests__/board-mutation-guard.test.ts": 325,
|
||||
"server/src/__tests__/body-limits.test.ts": 139,
|
||||
"server/src/__tests__/budgets-service.test.ts": 4078,
|
||||
"server/src/__tests__/build-commit.test.ts": 204,
|
||||
"server/src/__tests__/build-version.test.ts": 2984,
|
||||
"server/src/__tests__/built-in-agents.test.ts": 12350,
|
||||
"server/src/__tests__/bundled-plugins.test.ts": 243,
|
||||
"server/src/__tests__/change-consent-gate.test.ts": 4031,
|
||||
"server/src/__tests__/claude-local-adapter-environment.test.ts": 656,
|
||||
"server/src/__tests__/claude-local-adapter.test.ts": 350,
|
||||
"server/src/__tests__/claude-local-execute.test.ts": 3017,
|
||||
"server/src/__tests__/claude-local-skill-sync.test.ts": 292,
|
||||
"server/src/__tests__/cleanup-removal-service.test.ts": 5080,
|
||||
"server/src/__tests__/cloud-image-bundled-plugins.test.ts": 227,
|
||||
"server/src/__tests__/codex-auth-reconciliation.test.ts": 1018,
|
||||
"server/src/__tests__/codex-local-adapter-environment.test.ts": 295,
|
||||
"server/src/__tests__/codex-local-adapter.test.ts": 343,
|
||||
"server/src/__tests__/codex-local-execute.test.ts": 1427,
|
||||
"server/src/__tests__/codex-local-skill-injection.test.ts": 301,
|
||||
"server/src/__tests__/codex-local-skill-sync.test.ts": 287,
|
||||
"server/src/__tests__/companies-service.test.ts": 6464,
|
||||
"server/src/__tests__/company-artifacts-service.test.ts": 5752,
|
||||
"server/src/__tests__/company-portability-import-batching.test.ts": 8001,
|
||||
"server/src/__tests__/company-search-extract-service.test.ts": 4856,
|
||||
"server/src/__tests__/company-search-service.test.ts": 6275,
|
||||
"server/src/__tests__/company-skill-import-boundary.test.ts": 5181,
|
||||
"server/src/__tests__/company-skill-policy-service.test.ts": 4598,
|
||||
"server/src/__tests__/company-skill-test-runs-service.test.ts": 8229,
|
||||
"server/src/__tests__/company-skills-catalog-service.test.ts": 7482,
|
||||
"server/src/__tests__/company-skills-detail.test.ts": 4940,
|
||||
"server/src/__tests__/company-skills-service.test.ts": 17289,
|
||||
"server/src/__tests__/company-skills.test.ts": 1551,
|
||||
"server/src/__tests__/config-file.test.ts": 270,
|
||||
"server/src/__tests__/cursor-local-adapter-environment.test.ts": 343,
|
||||
"server/src/__tests__/cursor-local-adapter.test.ts": 315,
|
||||
"server/src/__tests__/cursor-local-execute.test.ts": 1075,
|
||||
"server/src/__tests__/cursor-local-skill-injection.test.ts": 492,
|
||||
"server/src/__tests__/cursor-local-skill-sync.test.ts": 498,
|
||||
"server/src/__tests__/dashboard-service.test.ts": 4449,
|
||||
"server/src/__tests__/decision-retention-service.test.ts": 5741,
|
||||
"server/src/__tests__/decision-training.test.ts": 6474,
|
||||
"server/src/__tests__/decision-wakeup.test.ts": 233,
|
||||
"server/src/__tests__/decisions-service.test.ts": 6434,
|
||||
"server/src/__tests__/dev-runner-output.test.ts": 232,
|
||||
"server/src/__tests__/dev-runner-paths.test.ts": 141,
|
||||
"server/src/__tests__/dev-runner-snapshot.test.ts": 1148,
|
||||
"server/src/__tests__/dev-runner-worktree.test.ts": 213,
|
||||
"server/src/__tests__/dev-server-status.test.ts": 140,
|
||||
"server/src/__tests__/dev-watch-ignore.test.ts": 145,
|
||||
"server/src/__tests__/docker-entrypoint.test.ts": 276,
|
||||
"server/src/__tests__/document-annotations-service.test.ts": 5650,
|
||||
"server/src/__tests__/access-service.test.ts": 4757,
|
||||
"server/src/__tests__/access-validators.test.ts": 645,
|
||||
"server/src/__tests__/activity-log-responsible-user.test.ts": 4407,
|
||||
"server/src/__tests__/activity-service.test.ts": 4708,
|
||||
"server/src/__tests__/adapter-models.test.ts": 1173,
|
||||
"server/src/__tests__/adapter-registry.test.ts": 1032,
|
||||
"server/src/__tests__/adapter-session-codecs.test.ts": 791,
|
||||
"server/src/__tests__/agent-auth-jwt.test.ts": 648,
|
||||
"server/src/__tests__/agent-auth-middleware.test.ts": 1228,
|
||||
"server/src/__tests__/agent-instructions-service.test.ts": 248,
|
||||
"server/src/__tests__/agent-invokability.test.ts": 1113,
|
||||
"server/src/__tests__/agent-permissions-service.test.ts": 640,
|
||||
"server/src/__tests__/agent-shortname-collision.test.ts": 1735,
|
||||
"server/src/__tests__/agent-skill-contract.test.ts": 242,
|
||||
"server/src/__tests__/agents-adapter-config-user-secret.test.ts": 5407,
|
||||
"server/src/__tests__/agents-claude-oauth-binding.test.ts": 6610,
|
||||
"server/src/__tests__/agents-pending-approval-config.test.ts": 4533,
|
||||
"server/src/__tests__/agents-service-clear-error.test.ts": 5193,
|
||||
"server/src/__tests__/agents-service-secret-bindings.test.ts": 4658,
|
||||
"server/src/__tests__/api-compression.test.ts": 341,
|
||||
"server/src/__tests__/app-hmr-port.test.ts": 3779,
|
||||
"server/src/__tests__/app-private-hostname-gate.test.ts": 4033,
|
||||
"server/src/__tests__/app-vite-dev-routing.test.ts": 2993,
|
||||
"server/src/__tests__/approvals-service.test.ts": 1207,
|
||||
"server/src/__tests__/artifact-review-documents-service.test.ts": 4200,
|
||||
"server/src/__tests__/attachment-types.test.ts": 579,
|
||||
"server/src/__tests__/attention-service.test.ts": 6910,
|
||||
"server/src/__tests__/authorization-service.test.ts": 6083,
|
||||
"server/src/__tests__/aws-secrets-manager-provider.test.ts": 285,
|
||||
"server/src/__tests__/better-auth.test.ts": 1103,
|
||||
"server/src/__tests__/board-claim.test.ts": 3975,
|
||||
"server/src/__tests__/board-mutation-guard.test.ts": 293,
|
||||
"server/src/__tests__/body-limits.test.ts": 203,
|
||||
"server/src/__tests__/budgets-service.test.ts": 4238,
|
||||
"server/src/__tests__/build-commit.test.ts": 195,
|
||||
"server/src/__tests__/build-version.test.ts": 211,
|
||||
"server/src/__tests__/built-in-agents.test.ts": 10282,
|
||||
"server/src/__tests__/bundled-plugins.test.ts": 235,
|
||||
"server/src/__tests__/change-consent-gate.test.ts": 4215,
|
||||
"server/src/__tests__/claude-local-adapter-environment.test.ts": 1105,
|
||||
"server/src/__tests__/claude-local-adapter.test.ts": 751,
|
||||
"server/src/__tests__/claude-local-execute.test.ts": 3248,
|
||||
"server/src/__tests__/claude-local-skill-sync.test.ts": 706,
|
||||
"server/src/__tests__/cleanup-removal-service.test.ts": 5454,
|
||||
"server/src/__tests__/cli-invocation-safety.test.ts": 1244,
|
||||
"server/src/__tests__/cloud-image-bundled-plugins.test.ts": 211,
|
||||
"server/src/__tests__/cloud-instance.test.ts": 227,
|
||||
"server/src/__tests__/codex-auth-reconciliation.test.ts": 1256,
|
||||
"server/src/__tests__/codex-device-login-credential-read.test.ts": 605,
|
||||
"server/src/__tests__/codex-device-login-reaper.test.ts": 1310,
|
||||
"server/src/__tests__/codex-device-login-service.test.ts": 4054,
|
||||
"server/src/__tests__/codex-local-adapter-environment.test.ts": 722,
|
||||
"server/src/__tests__/codex-local-adapter.test.ts": 739,
|
||||
"server/src/__tests__/codex-local-execute.test.ts": 2000,
|
||||
"server/src/__tests__/codex-local-skill-injection.test.ts": 674,
|
||||
"server/src/__tests__/codex-local-skill-sync.test.ts": 673,
|
||||
"server/src/__tests__/codex-login-session-runtime.test.ts": 1272,
|
||||
"server/src/__tests__/companies-service.test.ts": 6166,
|
||||
"server/src/__tests__/company-artifacts-service.test.ts": 6065,
|
||||
"server/src/__tests__/company-cloud-floor.test.ts": 1279,
|
||||
"server/src/__tests__/company-portability-import-batching.test.ts": 5771,
|
||||
"server/src/__tests__/company-search-extract-service.test.ts": 4422,
|
||||
"server/src/__tests__/company-search-service.test.ts": 5513,
|
||||
"server/src/__tests__/company-skill-import-boundary.test.ts": 5493,
|
||||
"server/src/__tests__/company-skill-policy-service.test.ts": 4498,
|
||||
"server/src/__tests__/company-skill-test-runs-service.test.ts": 7873,
|
||||
"server/src/__tests__/company-skills-catalog-service.test.ts": 6859,
|
||||
"server/src/__tests__/company-skills-detail.test.ts": 5366,
|
||||
"server/src/__tests__/company-skills-service.test.ts": 17568,
|
||||
"server/src/__tests__/company-skills.test.ts": 1829,
|
||||
"server/src/__tests__/company-transfer-runs.test.ts": 3984,
|
||||
"server/src/__tests__/config-file.test.ts": 653,
|
||||
"server/src/__tests__/cross-issue-influence-limit-postgres.test.ts": 4526,
|
||||
"server/src/__tests__/cross-issue-influence-limit.test.ts": 1106,
|
||||
"server/src/__tests__/cursor-local-adapter-environment.test.ts": 464,
|
||||
"server/src/__tests__/cursor-local-adapter.test.ts": 320,
|
||||
"server/src/__tests__/cursor-local-execute.test.ts": 1165,
|
||||
"server/src/__tests__/cursor-local-skill-injection.test.ts": 278,
|
||||
"server/src/__tests__/cursor-local-skill-sync.test.ts": 289,
|
||||
"server/src/__tests__/dashboard-service.test.ts": 3824,
|
||||
"server/src/__tests__/db-errors.test.ts": 202,
|
||||
"server/src/__tests__/decision-retention-service.test.ts": 5463,
|
||||
"server/src/__tests__/decision-training.test.ts": 6158,
|
||||
"server/src/__tests__/decision-wakeup.test.ts": 204,
|
||||
"server/src/__tests__/decisions-service.test.ts": 7258,
|
||||
"server/src/__tests__/dev-runner-output.test.ts": 220,
|
||||
"server/src/__tests__/dev-runner-paths.test.ts": 197,
|
||||
"server/src/__tests__/dev-runner-snapshot.test.ts": 199,
|
||||
"server/src/__tests__/dev-runner-worktree.test.ts": 217,
|
||||
"server/src/__tests__/dev-server-status.test.ts": 206,
|
||||
"server/src/__tests__/dev-watch-ignore.test.ts": 206,
|
||||
"server/src/__tests__/disposition-repair.test.ts": 1780,
|
||||
"server/src/__tests__/docker-build-stamp.test.ts": 199,
|
||||
"server/src/__tests__/docker-entrypoint.test.ts": 265,
|
||||
"server/src/__tests__/document-annotations-service.test.ts": 5743,
|
||||
"server/src/__tests__/documents-service.test.ts": 4497,
|
||||
"server/src/__tests__/documents.test.ts": 611,
|
||||
"server/src/__tests__/effective-run-config-fingerprints.test.ts": 253,
|
||||
"server/src/__tests__/environment-config.test.ts": 1745,
|
||||
"server/src/__tests__/environment-custom-image-terminal-ws.test.ts": 3025,
|
||||
"server/src/__tests__/environment-custom-images-service.test.ts": 7289,
|
||||
"server/src/__tests__/environment-execution-target.test.ts": 513,
|
||||
"server/src/__tests__/environment-live-ssh.test.ts": 943,
|
||||
"server/src/__tests__/environment-probe.test.ts": 1489,
|
||||
"server/src/__tests__/environment-run-orchestrator.test.ts": 1013,
|
||||
"server/src/__tests__/environment-runtime-driver-contract.test.ts": 5388,
|
||||
"server/src/__tests__/environment-runtime.test.ts": 5862,
|
||||
"server/src/__tests__/environment-service.test.ts": 4714,
|
||||
"server/src/__tests__/environment-test-harness.test.ts": 460,
|
||||
"server/src/__tests__/error-handler.test.ts": 442,
|
||||
"server/src/__tests__/execution-lock-orphan-cleanup.test.ts": 5168,
|
||||
"server/src/__tests__/execution-workspace-policy.test.ts": 484,
|
||||
"server/src/__tests__/execution-workspaces-service.test.ts": 11057,
|
||||
"server/src/__tests__/export-fidelity.test.ts": 4157,
|
||||
"server/src/__tests__/external-objects-service.test.ts": 5386,
|
||||
"server/src/__tests__/feedback-flush-controller.test.ts": 3756,
|
||||
"server/src/__tests__/feedback-service.test.ts": 4651,
|
||||
"server/src/__tests__/feedback-share-client.test.ts": 146,
|
||||
"server/src/__tests__/file-resources.test.ts": 14085,
|
||||
"server/src/__tests__/first-admin-claim.test.ts": 4124,
|
||||
"server/src/__tests__/folders-service.test.ts": 6404,
|
||||
"server/src/__tests__/documents.test.ts": 1104,
|
||||
"server/src/__tests__/duplex-aggregate-ceiling-env.test.ts": 210,
|
||||
"server/src/__tests__/duplex-observability-recorder.test.ts": 207,
|
||||
"server/src/__tests__/effective-run-config-fingerprints.test.ts": 219,
|
||||
"server/src/__tests__/embedded-postgres-supervisor.test.ts": 206,
|
||||
"server/src/__tests__/environment-capability-contract.test.ts": 1735,
|
||||
"server/src/__tests__/environment-config.test.ts": 1712,
|
||||
"server/src/__tests__/environment-custom-image-terminal-ws.test.ts": 2846,
|
||||
"server/src/__tests__/environment-custom-images-service.test.ts": 9820,
|
||||
"server/src/__tests__/environment-driver-traits.test.ts": 202,
|
||||
"server/src/__tests__/environment-execution-target-capabilities.test.ts": 751,
|
||||
"server/src/__tests__/environment-execution-target-duplex-kill-switch.test.ts": 677,
|
||||
"server/src/__tests__/environment-execution-target-duplex.test.ts": 1346,
|
||||
"server/src/__tests__/environment-execution-target.test.ts": 811,
|
||||
"server/src/__tests__/environment-live-ssh.test.ts": 1193,
|
||||
"server/src/__tests__/environment-probe.test.ts": 1730,
|
||||
"server/src/__tests__/environment-run-orchestrator.test.ts": 1692,
|
||||
"server/src/__tests__/environment-runtime-driver-contract.test.ts": 5260,
|
||||
"server/src/__tests__/environment-runtime-duplex-bridge-input.test.ts": 4482,
|
||||
"server/src/__tests__/environment-runtime.test.ts": 11452,
|
||||
"server/src/__tests__/environment-service.test.ts": 4677,
|
||||
"server/src/__tests__/environment-test-harness.test.ts": 572,
|
||||
"server/src/__tests__/error-handler.test.ts": 288,
|
||||
"server/src/__tests__/execution-lock-orphan-cleanup.test.ts": 5533,
|
||||
"server/src/__tests__/execution-workspace-policy.test.ts": 701,
|
||||
"server/src/__tests__/execution-workspace-reopen.test.ts": 5598,
|
||||
"server/src/__tests__/execution-workspace-runtime-control-conflict.test.ts": 2022,
|
||||
"server/src/__tests__/execution-workspaces-service.test.ts": 18767,
|
||||
"server/src/__tests__/export-fidelity.test.ts": 4260,
|
||||
"server/src/__tests__/external-objects-service.test.ts": 5395,
|
||||
"server/src/__tests__/feedback-flush-controller.test.ts": 4136,
|
||||
"server/src/__tests__/feedback-service.test.ts": 5006,
|
||||
"server/src/__tests__/feedback-share-client.test.ts": 208,
|
||||
"server/src/__tests__/file-resources-git-scan-load.test.ts": 2549,
|
||||
"server/src/__tests__/file-resources.test.ts": 9337,
|
||||
"server/src/__tests__/first-admin-claim.test.ts": 3933,
|
||||
"server/src/__tests__/folders-service.test.ts": 5002,
|
||||
"server/src/__tests__/forbidden-tokens.test.ts": 209,
|
||||
"server/src/__tests__/gemini-local-adapter-environment.test.ts": 379,
|
||||
"server/src/__tests__/gemini-local-adapter.test.ts": 330,
|
||||
"server/src/__tests__/gemini-local-execute.test.ts": 472,
|
||||
"server/src/__tests__/gemini-local-skill-sync.test.ts": 285,
|
||||
"server/src/__tests__/git-credentials.test.ts": 1528,
|
||||
"server/src/__tests__/google-sheets-gallery.test.ts": 994,
|
||||
"server/src/__tests__/gemini-local-adapter-environment.test.ts": 329,
|
||||
"server/src/__tests__/gemini-local-adapter.test.ts": 319,
|
||||
"server/src/__tests__/gemini-local-execute.test.ts": 462,
|
||||
"server/src/__tests__/gemini-local-skill-sync.test.ts": 288,
|
||||
"server/src/__tests__/general-capability-classifier.test.ts": 1736,
|
||||
"server/src/__tests__/git-credentials.test.ts": 1726,
|
||||
"server/src/__tests__/google-sheets-gallery.test.ts": 1678,
|
||||
"server/src/__tests__/grok-local-skill-sync.test.ts": 273,
|
||||
"server/src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts": 8428,
|
||||
"server/src/__tests__/heartbeat-active-run-output-watchdog.test.ts": 53902,
|
||||
"server/src/__tests__/heartbeat-agent-session-message.test.ts": 2466,
|
||||
"server/src/__tests__/heartbeat-archived-company-guard.test.ts": 5273,
|
||||
"server/src/__tests__/heartbeat-auto-checkout.test.ts": 1122,
|
||||
"server/src/__tests__/heartbeat-comment-wake-batching.test.ts": 8686,
|
||||
"server/src/__tests__/heartbeat-context-summary.test.ts": 1645,
|
||||
"server/src/__tests__/heartbeat-cost-accounting.test.ts": 1621,
|
||||
"server/src/__tests__/heartbeat-issue-rewake-throttle.test.ts": 6959,
|
||||
"server/src/__tests__/heartbeat-ledger-billing-code.test.ts": 1758,
|
||||
"server/src/__tests__/heartbeat-list.test.ts": 4922,
|
||||
"server/src/__tests__/heartbeat-local-environment.test.ts": 10973,
|
||||
"server/src/__tests__/heartbeat-lock-release-on-reassignment.test.ts": 5081,
|
||||
"server/src/__tests__/heartbeat-managed-clone-credentials.test.ts": 1255,
|
||||
"server/src/__tests__/heartbeat-model-profile.test.ts": 1678,
|
||||
"server/src/__tests__/heartbeat-plugin-environment.test.ts": 5596,
|
||||
"server/src/__tests__/heartbeat-project-env.test.ts": 1685,
|
||||
"server/src/__tests__/heartbeat-referenced-projects.test.ts": 6589,
|
||||
"server/src/__tests__/heartbeat-remote-referenced-projects.test.ts": 1714,
|
||||
"server/src/__tests__/heartbeat-responsible-user-invariant.test.ts": 7223,
|
||||
"server/src/__tests__/heartbeat-retry-scheduling.test.ts": 10283,
|
||||
"server/src/__tests__/heartbeat-run-log.test.ts": 1604,
|
||||
"server/src/__tests__/heartbeat-run-status-payload.test.ts": 1639,
|
||||
"server/src/__tests__/heartbeat-run-summary.test.ts": 435,
|
||||
"server/src/__tests__/heartbeat-runtime-mcp-servers.test.ts": 5094,
|
||||
"server/src/__tests__/heartbeat-runtime-skills.test.ts": 6782,
|
||||
"server/src/__tests__/heartbeat-runtime-state.test.ts": 5485,
|
||||
"server/src/__tests__/heartbeat-scheduling-suppression.test.ts": 1603,
|
||||
"server/src/__tests__/heartbeat-stale-queue-invalidation.test.ts": 18475,
|
||||
"server/src/__tests__/heartbeat-start-lock.test.ts": 437,
|
||||
"server/src/__tests__/heartbeat-timer-wake-session-reset-pf4.test.ts": 1137,
|
||||
"server/src/__tests__/heartbeat-workspace-branch-containment.test.ts": 8615,
|
||||
"server/src/__tests__/heartbeat-workspace-busy.test.ts": 9802,
|
||||
"server/src/__tests__/heartbeat-workspace-finalize-branch.test.ts": 7704,
|
||||
"server/src/__tests__/heartbeat-workspace-ready-comment.test.ts": 1154,
|
||||
"server/src/__tests__/heartbeat-workspace-session.test.ts": 1365,
|
||||
"server/src/__tests__/heartbeat-worktree-suppression.test.ts": 6472,
|
||||
"server/src/__tests__/heartbeat-zombie-guard.test.ts": 1704,
|
||||
"server/src/__tests__/hire-hook.test.ts": 986,
|
||||
"server/src/__tests__/http-log-policy.test.ts": 228,
|
||||
"server/src/__tests__/http-log-redaction.test.ts": 167,
|
||||
"server/src/__tests__/inbox-dismissals.test.ts": 7200,
|
||||
"server/src/__tests__/instance-settings-managed-overlay.test.ts": 909,
|
||||
"server/src/__tests__/instance-settings-service.test.ts": 915,
|
||||
"server/src/__tests__/instrumentation.test.ts": 189,
|
||||
"server/src/__tests__/invite-join-grants.test.ts": 592,
|
||||
"server/src/__tests__/invite-rate-limit.test.ts": 218,
|
||||
"server/src/__tests__/invite-token-entropy.test.ts": 1922,
|
||||
"server/src/__tests__/issue-blocker-attention.test.ts": 6309,
|
||||
"server/src/__tests__/issue-comment-redaction.test.ts": 6354,
|
||||
"server/src/__tests__/issue-continuation-summary.test.ts": 932,
|
||||
"server/src/__tests__/issue-execution-policy.test.ts": 462,
|
||||
"server/src/__tests__/issue-goal-fallback.test.ts": 204,
|
||||
"server/src/__tests__/issue-liveness.test.ts": 444,
|
||||
"server/src/__tests__/issue-monitor-scheduler.test.ts": 10856,
|
||||
"server/src/__tests__/issue-recovery-actions.test.ts": 7768,
|
||||
"server/src/__tests__/issue-references-service.test.ts": 4311,
|
||||
"server/src/__tests__/issue-rewake-throttle.test.ts": 209,
|
||||
"server/src/__tests__/issue-thread-interactions-service.test.ts": 9148,
|
||||
"server/src/__tests__/issue-thread-interactions-telemetry.test.ts": 4652,
|
||||
"server/src/__tests__/issue-tree-control-service-unit.test.ts": 904,
|
||||
"server/src/__tests__/issue-tree-control-service.test.ts": 6218,
|
||||
"server/src/__tests__/issues-list-query-parsing.test.ts": 1797,
|
||||
"server/src/__tests__/issues-user-context.test.ts": 1136,
|
||||
"server/src/__tests__/join-request-dedupe.test.ts": 203,
|
||||
"server/src/__tests__/json-schema-secret-refs.test.ts": 142,
|
||||
"server/src/__tests__/live-events-ws.test.ts": 549,
|
||||
"server/src/__tests__/log-redaction.test.ts": 1177,
|
||||
"server/src/__tests__/logger-tz.test.ts": 158,
|
||||
"server/src/__tests__/managed-config.test.ts": 414,
|
||||
"server/src/__tests__/mcp-http.test.ts": 206,
|
||||
"server/src/__tests__/monthly-spend-service.test.ts": 1193,
|
||||
"server/src/__tests__/openclaw-gateway-adapter.test.ts": 234,
|
||||
"server/src/__tests__/opencode-local-adapter.test.ts": 196,
|
||||
"server/src/__tests__/opencode-local-skill-sync.test.ts": 186,
|
||||
"server/src/__tests__/paperclip-env.test.ts": 302,
|
||||
"server/src/__tests__/health-workspace-readiness.test.ts": 1621,
|
||||
"server/src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts": 8157,
|
||||
"server/src/__tests__/heartbeat-active-run-output-watchdog.test.ts": 53682,
|
||||
"server/src/__tests__/heartbeat-agent-session-message.test.ts": 2803,
|
||||
"server/src/__tests__/heartbeat-archived-company-guard.test.ts": 4562,
|
||||
"server/src/__tests__/heartbeat-auto-checkout.test.ts": 1955,
|
||||
"server/src/__tests__/heartbeat-comment-wake-batching.test.ts": 9076,
|
||||
"server/src/__tests__/heartbeat-context-summary.test.ts": 1952,
|
||||
"server/src/__tests__/heartbeat-cost-accounting.test.ts": 1984,
|
||||
"server/src/__tests__/heartbeat-issue-rewake-throttle.test.ts": 7616,
|
||||
"server/src/__tests__/heartbeat-ledger-billing-code.test.ts": 2053,
|
||||
"server/src/__tests__/heartbeat-list.test.ts": 5326,
|
||||
"server/src/__tests__/heartbeat-local-environment.test.ts": 5312,
|
||||
"server/src/__tests__/heartbeat-lock-release-on-reassignment.test.ts": 5336,
|
||||
"server/src/__tests__/heartbeat-managed-clone-credentials.test.ts": 2164,
|
||||
"server/src/__tests__/heartbeat-model-profile.test.ts": 2000,
|
||||
"server/src/__tests__/heartbeat-pending-cleanup-sweep.test.ts": 5683,
|
||||
"server/src/__tests__/heartbeat-plugin-environment.test.ts": 5602,
|
||||
"server/src/__tests__/heartbeat-project-env.test.ts": 2029,
|
||||
"server/src/__tests__/heartbeat-referenced-projects.test.ts": 5601,
|
||||
"server/src/__tests__/heartbeat-remote-referenced-projects.test.ts": 1865,
|
||||
"server/src/__tests__/heartbeat-responsible-user-invariant.test.ts": 6136,
|
||||
"server/src/__tests__/heartbeat-retry-scheduling.test.ts": 9278,
|
||||
"server/src/__tests__/heartbeat-run-lease-release-terminalization.test.ts": 5519,
|
||||
"server/src/__tests__/heartbeat-run-log.test.ts": 1944,
|
||||
"server/src/__tests__/heartbeat-run-status-payload.test.ts": 1969,
|
||||
"server/src/__tests__/heartbeat-run-summary.test.ts": 210,
|
||||
"server/src/__tests__/heartbeat-run-terminalize-before-release.test.ts": 4525,
|
||||
"server/src/__tests__/heartbeat-runtime-mcp-servers.test.ts": 5513,
|
||||
"server/src/__tests__/heartbeat-runtime-skills.test.ts": 6217,
|
||||
"server/src/__tests__/heartbeat-runtime-state.test.ts": 5495,
|
||||
"server/src/__tests__/heartbeat-scheduling-suppression.test.ts": 1931,
|
||||
"server/src/__tests__/heartbeat-stale-queue-invalidation.test.ts": 18600,
|
||||
"server/src/__tests__/heartbeat-start-lock.test.ts": 231,
|
||||
"server/src/__tests__/heartbeat-timer-wake-session-reset-pf4.test.ts": 1971,
|
||||
"server/src/__tests__/heartbeat-workspace-branch-containment.test.ts": 7407,
|
||||
"server/src/__tests__/heartbeat-workspace-busy.test.ts": 10518,
|
||||
"server/src/__tests__/heartbeat-workspace-finalize-branch.test.ts": 7262,
|
||||
"server/src/__tests__/heartbeat-workspace-ready-comment.test.ts": 1932,
|
||||
"server/src/__tests__/heartbeat-workspace-session.test.ts": 2286,
|
||||
"server/src/__tests__/heartbeat-worktree-suppression.test.ts": 6308,
|
||||
"server/src/__tests__/heartbeat-zombie-guard.test.ts": 1935,
|
||||
"server/src/__tests__/hire-hook.test.ts": 807,
|
||||
"server/src/__tests__/http-log-policy.test.ts": 204,
|
||||
"server/src/__tests__/http-log-redaction.test.ts": 239,
|
||||
"server/src/__tests__/inbox-dismissals.test.ts": 5662,
|
||||
"server/src/__tests__/instance-settings-managed-overlay.test.ts": 1170,
|
||||
"server/src/__tests__/instance-settings-service.test.ts": 1144,
|
||||
"server/src/__tests__/instrumentation.test.ts": 239,
|
||||
"server/src/__tests__/interaction-resolution-cross-issue-cap-postgres.test.ts": 6128,
|
||||
"server/src/__tests__/invite-join-grants.test.ts": 637,
|
||||
"server/src/__tests__/invite-rate-limit.test.ts": 207,
|
||||
"server/src/__tests__/invite-token-entropy.test.ts": 2300,
|
||||
"server/src/__tests__/issue-blocker-attention.test.ts": 6573,
|
||||
"server/src/__tests__/issue-comment-redaction.test.ts": 6119,
|
||||
"server/src/__tests__/issue-continuation-summary.test.ts": 1144,
|
||||
"server/src/__tests__/issue-execution-policy.test.ts": 705,
|
||||
"server/src/__tests__/issue-existing-branch-validation-status.test.ts": 1356,
|
||||
"server/src/__tests__/issue-goal-fallback.test.ts": 198,
|
||||
"server/src/__tests__/issue-interactions-read-only-contract.test.ts": 203,
|
||||
"server/src/__tests__/issue-liveness.test.ts": 652,
|
||||
"server/src/__tests__/issue-monitor-scheduler.test.ts": 11289,
|
||||
"server/src/__tests__/issue-recovery-actions.test.ts": 8471,
|
||||
"server/src/__tests__/issue-references-service.test.ts": 4472,
|
||||
"server/src/__tests__/issue-remove-cascade.test.ts": 5149,
|
||||
"server/src/__tests__/issue-review-attention.test.ts": 4623,
|
||||
"server/src/__tests__/issue-review-policy.test.ts": 4125,
|
||||
"server/src/__tests__/issue-rewake-throttle.test.ts": 213,
|
||||
"server/src/__tests__/issue-thread-interactions-service.test.ts": 9932,
|
||||
"server/src/__tests__/issue-thread-interactions-telemetry.test.ts": 5363,
|
||||
"server/src/__tests__/issue-tree-control-service-unit.test.ts": 1131,
|
||||
"server/src/__tests__/issue-tree-control-service.test.ts": 5585,
|
||||
"server/src/__tests__/issues-list-query-parsing.test.ts": 5695,
|
||||
"server/src/__tests__/issues-parent-id-alias.test.ts": 6098,
|
||||
"server/src/__tests__/issues-user-context.test.ts": 1728,
|
||||
"server/src/__tests__/join-request-dedupe.test.ts": 212,
|
||||
"server/src/__tests__/json-schema-secret-refs.test.ts": 208,
|
||||
"server/src/__tests__/kimi-local-skill-sync.test.ts": 284,
|
||||
"server/src/__tests__/live-events-ws.test.ts": 813,
|
||||
"server/src/__tests__/local-service-supervisor.test.ts": 4367,
|
||||
"server/src/__tests__/log-redaction.test.ts": 201,
|
||||
"server/src/__tests__/logger-tz.test.ts": 220,
|
||||
"server/src/__tests__/managed-config.test.ts": 666,
|
||||
"server/src/__tests__/mcp-http.test.ts": 208,
|
||||
"server/src/__tests__/merged-pr-confirmation-sweep.test.ts": 4305,
|
||||
"server/src/__tests__/monthly-spend-service.test.ts": 1987,
|
||||
"server/src/__tests__/openclaw-gateway-adapter.test.ts": 292,
|
||||
"server/src/__tests__/opencode-local-adapter.test.ts": 297,
|
||||
"server/src/__tests__/opencode-local-skill-sync.test.ts": 285,
|
||||
"server/src/__tests__/paperclip-env.test.ts": 263,
|
||||
"server/src/__tests__/paperclip-issue-update-helper.test.ts": 4333,
|
||||
"server/src/__tests__/paperclip-skill-utils.test.ts": 252,
|
||||
"server/src/__tests__/parse-status-filter.test.ts": 1335,
|
||||
"server/src/__tests__/pi-local-adapter-environment.test.ts": 393,
|
||||
"server/src/__tests__/pi-local-execute.test.ts": 334,
|
||||
"server/src/__tests__/pi-local-skill-sync.test.ts": 1133,
|
||||
"server/src/__tests__/pipelines-service.test.ts": 7263,
|
||||
"server/src/__tests__/plugin-access-authorization-host-services.test.ts": 5438,
|
||||
"server/src/__tests__/plugin-agent-sessions.test.ts": 1682,
|
||||
"server/src/__tests__/plugin-config-startup-delivery.test.ts": 4023,
|
||||
"server/src/__tests__/plugin-database.test.ts": 4601,
|
||||
"server/src/__tests__/plugin-dev-watcher.test.ts": 508,
|
||||
"server/src/__tests__/plugin-environment-driver-ready-recovery.test.ts": 2887,
|
||||
"server/src/__tests__/plugin-environment-driver-seam.test.ts": 541,
|
||||
"server/src/__tests__/plugin-execution-workspace-bridge.test.ts": 229,
|
||||
"server/src/__tests__/plugin-host-services-span.test.ts": 1789,
|
||||
"server/src/__tests__/plugin-install-autobuild.test.ts": 7316,
|
||||
"server/src/__tests__/plugin-install-guard.test.ts": 1163,
|
||||
"server/src/__tests__/plugin-lifecycle-restart.test.ts": 724,
|
||||
"server/src/__tests__/plugin-local-folders.test.ts": 277,
|
||||
"server/src/__tests__/plugin-managed-agents.test.ts": 5174,
|
||||
"server/src/__tests__/plugin-managed-routines.test.ts": 5685,
|
||||
"server/src/__tests__/plugin-managed-skills.test.ts": 6856,
|
||||
"server/src/__tests__/plugin-orchestration-apis.test.ts": 8002,
|
||||
"server/src/__tests__/plugin-sandbox-provider-config-validation.test.ts": 296,
|
||||
"server/src/__tests__/plugin-sdk-orchestration-contract.test.ts": 454,
|
||||
"server/src/__tests__/plugin-sdk-testing.test.ts": 272,
|
||||
"server/src/__tests__/plugin-secrets-handler.test.ts": 4609,
|
||||
"server/src/__tests__/plugin-telemetry-bridge.test.ts": 1224,
|
||||
"server/src/__tests__/plugin-tenant-isolation.test.ts": 5093,
|
||||
"server/src/__tests__/plugin-tool-dispatcher-pluginDbId.test.ts": 960,
|
||||
"server/src/__tests__/plugin-ui-static.test.ts": 1092,
|
||||
"server/src/__tests__/plugin-worker-manager.test.ts": 1327,
|
||||
"server/src/__tests__/private-hostname-guard.test.ts": 301,
|
||||
"server/src/__tests__/productivity-review-service.test.ts": 9612,
|
||||
"server/src/__tests__/project-icon-persistence.test.ts": 4155,
|
||||
"server/src/__tests__/project-list-metrics.test.ts": 950,
|
||||
"server/src/__tests__/project-shortname-resolution.test.ts": 1177,
|
||||
"server/src/__tests__/qa-routine-secrets-e2e.test.ts": 5304,
|
||||
"server/src/__tests__/quota-windows-service.test.ts": 215,
|
||||
"server/src/__tests__/quota-windows.test.ts": 366,
|
||||
"server/src/__tests__/recovery-classifiers.test.ts": 1574,
|
||||
"server/src/__tests__/recovery-observability.test.ts": 4389,
|
||||
"server/src/__tests__/recovery-stale-issue-lock-sweep.test.ts": 9167,
|
||||
"server/src/__tests__/redact-sensitive.test.ts": 144,
|
||||
"server/src/__tests__/remote-http-endpoint-guard.test.ts": 635,
|
||||
"server/src/__tests__/routable-blocked.test.ts": 210,
|
||||
"server/src/__tests__/routine-run-telemetry.test.ts": 5025,
|
||||
"server/src/__tests__/routines-service.test.ts": 13035,
|
||||
"server/src/__tests__/run-continuations.test.ts": 808,
|
||||
"server/src/__tests__/run-liveness.test.ts": 143,
|
||||
"server/src/__tests__/runtime-api.test.ts": 223,
|
||||
"server/src/__tests__/sandbox-provider-runtime.test.ts": 144,
|
||||
"server/src/__tests__/secret-provider-registry.test.ts": 187,
|
||||
"server/src/__tests__/secrets-service-user-secret-owner-scoped.test.ts": 4753,
|
||||
"server/src/__tests__/secrets-service.test.ts": 7274,
|
||||
"server/src/__tests__/server-info.test.ts": 846,
|
||||
"server/src/__tests__/server-package-build-script.test.ts": 427,
|
||||
"server/src/__tests__/server-startup-feedback-export.test.ts": 1249,
|
||||
"server/src/__tests__/shared-telemetry-events.test.ts": 230,
|
||||
"server/src/__tests__/skills-catalog-service.test.ts": 260,
|
||||
"server/src/__tests__/smoke-lab.test.ts": 6063,
|
||||
"server/src/__tests__/source-trust.test.ts": 5476,
|
||||
"server/src/__tests__/static-index-html.test.ts": 294,
|
||||
"server/src/__tests__/status-card-update-engine.test.ts": 385,
|
||||
"server/src/__tests__/status-cards.test.ts": 8233,
|
||||
"server/src/__tests__/storage-local-provider.test.ts": 234,
|
||||
"server/src/__tests__/summary-slots.test.ts": 6587,
|
||||
"server/src/__tests__/task-watchdogs-classifier.test.ts": 762,
|
||||
"server/src/__tests__/task-watchdogs-scheduler.test.ts": 6386,
|
||||
"server/src/__tests__/teams-catalog-install-no-overrides.test.ts": 9170,
|
||||
"server/src/__tests__/teams-catalog-service.test.ts": 461,
|
||||
"server/src/__tests__/telemetry-client-flush.test.ts": 1208,
|
||||
"server/src/__tests__/tool-access-policy-service.test.ts": 6548,
|
||||
"server/src/__tests__/tool-access-service.test.ts": 14498,
|
||||
"server/src/__tests__/tool-content-guards.test.ts": 240,
|
||||
"server/src/__tests__/tool-gateway-service.test.ts": 6241,
|
||||
"server/src/__tests__/tool-gateway.test.ts": 24463,
|
||||
"server/src/__tests__/tool-oauth-legacy-backfill.test.ts": 7051,
|
||||
"server/src/__tests__/trust-preset-resolver.test.ts": 409,
|
||||
"server/src/__tests__/trust-proxy.test.ts": 168,
|
||||
"server/src/__tests__/ui-branding.test.ts": 223,
|
||||
"server/src/__tests__/version.test.ts": 229,
|
||||
"server/src/__tests__/vite-html-renderer.test.ts": 136,
|
||||
"server/src/__tests__/work-products.test.ts": 521,
|
||||
"server/src/__tests__/work-timeline-service.test.ts": 5712,
|
||||
"server/src/__tests__/workspace-instance-cleanup.test.ts": 265,
|
||||
"server/src/__tests__/workspace-runtime.test.ts": 37401,
|
||||
"server/src/__tests__/worktree-config.test.ts": 280,
|
||||
"server/src/__tests__/write-path-membership.test.ts": 736
|
||||
"server/src/__tests__/parse-status-filter.test.ts": 1713,
|
||||
"server/src/__tests__/pi-local-adapter-environment.test.ts": 396,
|
||||
"server/src/__tests__/pi-local-execute.test.ts": 491,
|
||||
"server/src/__tests__/pi-local-skill-sync.test.ts": 288,
|
||||
"server/src/__tests__/pipelines-service.test.ts": 8966,
|
||||
"server/src/__tests__/plugin-access-authorization-host-services.test.ts": 5679,
|
||||
"server/src/__tests__/plugin-agent-sessions.test.ts": 1903,
|
||||
"server/src/__tests__/plugin-config-startup-delivery.test.ts": 3528,
|
||||
"server/src/__tests__/plugin-database.test.ts": 4910,
|
||||
"server/src/__tests__/plugin-dev-watcher.test.ts": 308,
|
||||
"server/src/__tests__/plugin-environment-driver-ready-recovery.test.ts": 4760,
|
||||
"server/src/__tests__/plugin-environment-driver-sandbox-capabilities.test.ts": 269,
|
||||
"server/src/__tests__/plugin-environment-driver-seam.test.ts": 745,
|
||||
"server/src/__tests__/plugin-execution-workspace-bridge.test.ts": 223,
|
||||
"server/src/__tests__/plugin-host-services-span.test.ts": 2220,
|
||||
"server/src/__tests__/plugin-install-autobuild.test.ts": 7492,
|
||||
"server/src/__tests__/plugin-install-guard.test.ts": 1307,
|
||||
"server/src/__tests__/plugin-lifecycle-restart.test.ts": 1304,
|
||||
"server/src/__tests__/plugin-loader-error-retry.test.ts": 1324,
|
||||
"server/src/__tests__/plugin-local-folders.test.ts": 260,
|
||||
"server/src/__tests__/plugin-managed-agents.test.ts": 5957,
|
||||
"server/src/__tests__/plugin-managed-routines.test.ts": 5686,
|
||||
"server/src/__tests__/plugin-managed-skills.test.ts": 6978,
|
||||
"server/src/__tests__/plugin-orchestration-apis.test.ts": 8406,
|
||||
"server/src/__tests__/plugin-sandbox-provider-config-validation.test.ts": 204,
|
||||
"server/src/__tests__/plugin-sdk-orchestration-contract.test.ts": 717,
|
||||
"server/src/__tests__/plugin-sdk-testing.test.ts": 584,
|
||||
"server/src/__tests__/plugin-secrets-handler.test.ts": 5161,
|
||||
"server/src/__tests__/plugin-telemetry-bridge.test.ts": 2066,
|
||||
"server/src/__tests__/plugin-tenant-isolation.test.ts": 4622,
|
||||
"server/src/__tests__/plugin-tool-dispatcher-pluginDbId.test.ts": 795,
|
||||
"server/src/__tests__/plugin-ui-static.test.ts": 1293,
|
||||
"server/src/__tests__/plugin-worker-manager-duplex-byte-ledger.test.ts": 1240,
|
||||
"server/src/__tests__/plugin-worker-manager-duplex-pending-write-ledger.test.ts": 1006,
|
||||
"server/src/__tests__/plugin-worker-manager-duplex-stdin-write-ledger.test.ts": 3918,
|
||||
"server/src/__tests__/plugin-worker-manager-duplex.test.ts": 2233,
|
||||
"server/src/__tests__/plugin-worker-manager.test.ts": 2669,
|
||||
"server/src/__tests__/private-hostname-guard.test.ts": 300,
|
||||
"server/src/__tests__/private-json-etag.test.ts": 271,
|
||||
"server/src/__tests__/productivity-review-service.test.ts": 11098,
|
||||
"server/src/__tests__/project-icon-persistence.test.ts": 3936,
|
||||
"server/src/__tests__/project-list-metrics.test.ts": 1198,
|
||||
"server/src/__tests__/project-shortname-resolution.test.ts": 1196,
|
||||
"server/src/__tests__/qa-routine-secrets-e2e.test.ts": 5522,
|
||||
"server/src/__tests__/quota-windows-service.test.ts": 214,
|
||||
"server/src/__tests__/quota-windows.test.ts": 799,
|
||||
"server/src/__tests__/recovery-classifiers.test.ts": 1822,
|
||||
"server/src/__tests__/recovery-observability.test.ts": 4550,
|
||||
"server/src/__tests__/recovery-stale-issue-lock-sweep.test.ts": 5578,
|
||||
"server/src/__tests__/redact-sensitive.test.ts": 207,
|
||||
"server/src/__tests__/remote-http-endpoint-guard.test.ts": 212,
|
||||
"server/src/__tests__/rerun-survival.integration.test.ts": 623,
|
||||
"server/src/__tests__/reusable-leases-default.test.ts": 623,
|
||||
"server/src/__tests__/routable-blocked.test.ts": 205,
|
||||
"server/src/__tests__/routine-run-telemetry.test.ts": 5399,
|
||||
"server/src/__tests__/routines-service.test.ts": 9870,
|
||||
"server/src/__tests__/run-continuations.test.ts": 771,
|
||||
"server/src/__tests__/run-liveness.test.ts": 210,
|
||||
"server/src/__tests__/run-secret-redaction.test.ts": 817,
|
||||
"server/src/__tests__/runtime-api.test.ts": 204,
|
||||
"server/src/__tests__/sandbox-orphan-cleanup-spool.test.ts": 221,
|
||||
"server/src/__tests__/sandbox-provider-runtime.test.ts": 196,
|
||||
"server/src/__tests__/secret-provider-registry.test.ts": 270,
|
||||
"server/src/__tests__/secrets-service-dangling-user-secret.test.ts": 5159,
|
||||
"server/src/__tests__/secrets-service-user-secret-owner-scoped.test.ts": 5294,
|
||||
"server/src/__tests__/secrets-service.test.ts": 6526,
|
||||
"server/src/__tests__/server-info.test.ts": 648,
|
||||
"server/src/__tests__/server-package-build-script.test.ts": 194,
|
||||
"server/src/__tests__/server-startup-feedback-export.test.ts": 1631,
|
||||
"server/src/__tests__/service-version.test.ts": 200,
|
||||
"server/src/__tests__/shared-telemetry-events.test.ts": 208,
|
||||
"server/src/__tests__/skills-catalog-service.test.ts": 248,
|
||||
"server/src/__tests__/smoke-lab.test.ts": 4920,
|
||||
"server/src/__tests__/source-trust.test.ts": 3784,
|
||||
"server/src/__tests__/static-index-html.test.ts": 276,
|
||||
"server/src/__tests__/status-card-update-engine.test.ts": 639,
|
||||
"server/src/__tests__/status-cards.test.ts": 8423,
|
||||
"server/src/__tests__/storage-local-provider.test.ts": 225,
|
||||
"server/src/__tests__/summary-slots.test.ts": 6669,
|
||||
"server/src/__tests__/task-watchdogs-classifier.test.ts": 1741,
|
||||
"server/src/__tests__/task-watchdogs-incident-fixture.test.ts": 203,
|
||||
"server/src/__tests__/task-watchdogs-scheduler.test.ts": 6504,
|
||||
"server/src/__tests__/teams-catalog-install-no-overrides.test.ts": 7292,
|
||||
"server/src/__tests__/teams-catalog-service.test.ts": 697,
|
||||
"server/src/__tests__/telemetry-client-flush.test.ts": 221,
|
||||
"server/src/__tests__/tool-access-policy-service.test.ts": 6204,
|
||||
"server/src/__tests__/tool-access-service.test.ts": 16382,
|
||||
"server/src/__tests__/tool-content-guards.test.ts": 220,
|
||||
"server/src/__tests__/tool-gateway-service.test.ts": 6570,
|
||||
"server/src/__tests__/tool-gateway.test.ts": 18019,
|
||||
"server/src/__tests__/tool-oauth-legacy-backfill.test.ts": 4994,
|
||||
"server/src/__tests__/tool-review-queue-unsigned-request.test.ts": 5001,
|
||||
"server/src/__tests__/trust-preset-resolver.test.ts": 642,
|
||||
"server/src/__tests__/trust-proxy.test.ts": 249,
|
||||
"server/src/__tests__/ui-branding.test.ts": 200,
|
||||
"server/src/__tests__/version.test.ts": 222,
|
||||
"server/src/__tests__/vite-html-renderer.test.ts": 208,
|
||||
"server/src/__tests__/work-product-runtime-reconciliation.test.ts": 762,
|
||||
"server/src/__tests__/work-products.test.ts": 773,
|
||||
"server/src/__tests__/work-timeline-service.test.ts": 5134,
|
||||
"server/src/__tests__/workspace-instance-cleanup.test.ts": 247,
|
||||
"server/src/__tests__/workspace-login-handoff-endpoint.test.ts": 1280,
|
||||
"server/src/__tests__/workspace-login-handoff-issuer.test.ts": 755,
|
||||
"server/src/__tests__/workspace-login-handoff.test.ts": 241,
|
||||
"server/src/__tests__/workspace-operations-reconciliation.test.ts": 4391,
|
||||
"server/src/__tests__/workspace-readiness.test.ts": 848,
|
||||
"server/src/__tests__/workspace-reaper-cooldown-config.test.ts": 665,
|
||||
"server/src/__tests__/workspace-runtime-control-recovery.test.ts": 4196,
|
||||
"server/src/__tests__/workspace-runtime-exposure-reservation.test.ts": 8194,
|
||||
"server/src/__tests__/workspace-runtime-https-live-exercise.test.ts": 2333,
|
||||
"server/src/__tests__/workspace-runtime-leases.test.ts": 4619,
|
||||
"server/src/__tests__/workspace-runtime-start-terminality.test.ts": 5267,
|
||||
"server/src/__tests__/workspace-runtime.test.ts": 123272,
|
||||
"server/src/__tests__/worktree-config.test.ts": 1126,
|
||||
"server/src/__tests__/worktree-seed-server-spawn.test.ts": 2003,
|
||||
"server/src/__tests__/write-build-stamp.test.ts": 203,
|
||||
"server/src/__tests__/write-path-membership.test.ts": 1215,
|
||||
"server/src/adapters/claude-agent-id-header.test.ts": 203,
|
||||
"server/src/adapters/http/execute.test.ts": 270,
|
||||
"server/src/adapters/plugin-loader.test.ts": 236,
|
||||
"server/src/adapters/registry.test.ts": 1062,
|
||||
"server/src/instrumentation.test.ts": 222,
|
||||
"server/src/lib/request-promise-memo.test.ts": 218,
|
||||
"server/src/middleware/cloud-tenant-actor.test.ts": 1207,
|
||||
"server/src/routes/adapters.test.ts": 1736,
|
||||
"server/src/services/adapter-login-lease.test.ts": 199,
|
||||
"server/src/services/adapter-models-env.test.ts": 202,
|
||||
"server/src/services/adapter-registry-bootstrap.reconcile.test.ts": 1133,
|
||||
"server/src/services/adapter-registry-bootstrap.test.ts": 1116,
|
||||
"server/src/services/attention-resolver-audience.test.ts": 1778,
|
||||
"server/src/services/board-auth.test.ts": 738,
|
||||
"server/src/services/environment-custom-image-terminal-sessions.test.ts": 217,
|
||||
"server/src/services/execution-allowlist.test.ts": 205,
|
||||
"server/src/services/execution-policy-bootstrap.test.ts": 1128,
|
||||
"server/src/services/heartbeat-run-runtime-status.test.ts": 222,
|
||||
"server/src/services/heartbeat-stop-metadata.test.ts": 195,
|
||||
"server/src/services/hot-restart.test.ts": 295,
|
||||
"server/src/services/issue-dependency-wakeups.test.ts": 751,
|
||||
"server/src/services/issue-thread-interaction-resolution.test.ts": 622,
|
||||
"server/src/services/issue-thread-interactions.test.ts": 4650,
|
||||
"server/src/services/login-command.test.ts": 191,
|
||||
"server/src/services/managed-environments.test.ts": 1711,
|
||||
"server/src/services/managed-resource-drift.test.ts": 215,
|
||||
"server/src/services/onboarding-greeting.test.ts": 204,
|
||||
"server/src/services/recovery/model-profile-hint.test.ts": 203,
|
||||
"server/src/services/recovery/provider-failure-classification.test.ts": 1712,
|
||||
"server/src/services/recovery/review-path-recovery.test.ts": 216,
|
||||
"server/src/services/recovery/service.pause-durability.test.ts": 1746,
|
||||
"server/src/services/recovery/stranded-notice.test.ts": 758,
|
||||
"server/src/services/recovery/successful-run-handoff.test.ts": 821,
|
||||
"server/src/services/responsible-user-denial-run-outcomes.test.ts": 1130,
|
||||
"server/src/services/routines-formatter-cache.test.ts": 2942,
|
||||
"server/src/services/run-log-store.test.ts": 629,
|
||||
"server/src/services/run-scratch.test.ts": 214,
|
||||
"server/src/services/runtime-exposure/broker-client.test.ts": 381,
|
||||
"server/src/services/runtime-exposure/exposure-manager.test.ts": 577,
|
||||
"server/src/services/runtime-exposure/loopback-listener.test.ts": 686,
|
||||
"server/src/services/runtime-exposure/port-pair.test.ts": 622,
|
||||
"server/src/services/runtime-exposure/port-reservation.test.ts": 657,
|
||||
"server/src/services/runtime-exposure/tailscale-hostname.test.ts": 214,
|
||||
"server/src/services/session-workspace-cwd.test.ts": 199,
|
||||
"server/src/services/setup-token-reaper.test.ts": 1726,
|
||||
"server/src/services/setup-token-session.test.ts": 4809,
|
||||
"server/src/services/setup-token-transport-binding.test.ts": 1995,
|
||||
"server/src/services/workspace-git-operation-scheduler.test.ts": 1623,
|
||||
"server/src/services/workspace-runtime-exposure-backfill.test.ts": 1618,
|
||||
"server/src/services/workspace-runtime-exposure.test.ts": 13656,
|
||||
"server/src/services/workspace-runtime-read-model.test.ts": 1139,
|
||||
"server/src/services/workspace-runtime-ready-comment.test.ts": 1744,
|
||||
"server/src/shutdown.test.ts": 247,
|
||||
"server/src/url-utils.test.ts": 196
|
||||
}
|
||||
}
|
||||
@@ -102,9 +102,65 @@ if [[ -z "${PAPERCLIP_API_URL:-}" || -z "${PAPERCLIP_API_KEY:-}" || -z "${PAPERC
|
||||
exit 1
|
||||
fi
|
||||
|
||||
curl -sS -X PATCH \
|
||||
"$PAPERCLIP_API_URL/api/issues/$issue_id" \
|
||||
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||
-H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "$payload"
|
||||
# A successful PATCH always returns the updated issue JSON. An empty body or a
|
||||
# connection-level failure means the write did NOT land, even when a pipeline
|
||||
# exit code says otherwise, so verify the response instead of inferring success.
|
||||
# Two attempts total: the shared heartbeat policy stops a control-plane write
|
||||
# after two consecutive failures, so the helper must not send a third.
|
||||
max_attempts=2
|
||||
attempt=1
|
||||
while :; do
|
||||
http_code=""
|
||||
body=""
|
||||
set +e
|
||||
response="$(
|
||||
curl -sS -m 30 -X PATCH \
|
||||
"$PAPERCLIP_API_URL/api/issues/$issue_id" \
|
||||
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||
-H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "$payload" \
|
||||
-w '\n%{http_code}'
|
||||
)"
|
||||
curl_exit=$?
|
||||
set -e
|
||||
|
||||
if [[ "$curl_exit" -eq 0 ]]; then
|
||||
http_code="${response##*$'\n'}"
|
||||
body="${response%$'\n'*}"
|
||||
fi
|
||||
|
||||
if [[ "$curl_exit" -eq 0 && "$http_code" == 2* ]]; then
|
||||
if [[ -z "$body" ]]; then
|
||||
printf 'Issue update FAILED: HTTP %s with an empty response body. A real update echoes the issue JSON; treat this write as not saved.\n' "$http_code" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$status" ]]; then
|
||||
returned_status="$(jq -r '.status // empty' <<<"$body" 2>/dev/null || true)"
|
||||
if [[ "$returned_status" != "$status" ]]; then
|
||||
printf 'Issue update FAILED: server echoed status %s instead of requested %s.\n' "${returned_status:-<none>}" "$status" >&2
|
||||
printf '%s\n' "$body" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
printf '%s\n' "$body"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 4xx (other than 429) is a definitive rejection; retrying cannot change it.
|
||||
if [[ "$curl_exit" -eq 0 && "$http_code" == 4* && "$http_code" != "429" ]]; then
|
||||
printf 'Issue update rejected (HTTP %s).\n' "$http_code" >&2
|
||||
[[ -n "$body" ]] && printf '%s\n' "$body" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( attempt >= max_attempts )); then
|
||||
printf 'Issue update FAILED after %d attempts (curl exit %s, HTTP %s). The status/comment was NOT saved — report this write as failed, do not assume it landed.\n' "$max_attempts" "$curl_exit" "${http_code:-000}" >&2
|
||||
[[ -n "$body" ]] && printf '%s\n' "$body" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'Issue update attempt %d/%d failed (curl exit %s, HTTP %s); retrying...\n' "$attempt" "$max_attempts" "$curl_exit" "${http_code:-000}" >&2
|
||||
sleep $((attempt * 2))
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Prove that `onboard --install-service` on a released artifact leaves a
|
||||
# working background service. The Docker onboard smoke can never cover this
|
||||
# leg: containers have no service manager, so a release whose service install
|
||||
# crash-loops on a missing shim (v2026.824.0) still passes every golden-path
|
||||
# check. This script runs the published npm artifact on a real systemd user
|
||||
# session and fails unless the installed service itself ends up serving
|
||||
# /api/health.
|
||||
#
|
||||
# Requirements: a Linux host with a user systemd session. In CI that means
|
||||
# `loginctl enable-linger` plus XDG_RUNTIME_DIR / DBUS_SESSION_BUS_ADDRESS
|
||||
# pointing at /run/user/<uid>; see the smoke_service job in
|
||||
# .github/workflows/release-smoke.yml.
|
||||
|
||||
PAPERCLIPAI_VERSION="${PAPERCLIPAI_VERSION:-latest}"
|
||||
DATA_DIR="${DATA_DIR:-$(mktemp -d "${TMPDIR:-/tmp}/paperclip-service-smoke.XXXXXX")}"
|
||||
ONBOARD_TIMEOUT_SECONDS="${ONBOARD_TIMEOUT_SECONDS:-600}"
|
||||
SMOKE_READY_TIMEOUT_SECONDS="${SMOKE_READY_TIMEOUT_SECONDS:-420}"
|
||||
HEALTH_URL="${HEALTH_URL:-http://127.0.0.1:3100/api/health}"
|
||||
SERVICE_NAME="paperclipai.service"
|
||||
SHIM_PATH="${PAPERCLIP_SHIM_PATH:-$HOME/.local/bin/paperclipai}"
|
||||
# Cleanup defaults to on so a local run does not leave a service behind; CI
|
||||
# disables it so the diagnostics step can still inspect the unit.
|
||||
SMOKE_CLEANUP="${SMOKE_CLEANUP:-true}"
|
||||
SMOKE_FORCE="${SMOKE_FORCE:-false}"
|
||||
|
||||
fail() {
|
||||
echo "Service smoke failed: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
diagnostics() {
|
||||
echo "--- systemctl --user status $SERVICE_NAME ---" >&2
|
||||
systemctl --user --no-pager status "$SERVICE_NAME" >&2 || true
|
||||
echo "--- journalctl --user -u $SERVICE_NAME (last 100 lines) ---" >&2
|
||||
journalctl --user -u "$SERVICE_NAME" --no-pager -n 100 >&2 || true
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if [[ "$SMOKE_CLEANUP" == "true" ]]; then
|
||||
if [[ -x "$SHIM_PATH" ]]; then
|
||||
"$SHIM_PATH" service uninstall >/dev/null 2>&1 || true
|
||||
fi
|
||||
systemctl --user stop "$SERVICE_NAME" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
command -v systemctl >/dev/null 2>&1 || fail "systemctl is not available on this host"
|
||||
systemctl --user show-environment >/dev/null 2>&1 \
|
||||
|| fail "no user systemd session; enable lingering and export XDG_RUNTIME_DIR first"
|
||||
|
||||
# Refuse to smoke over a host that already has a managed install: the
|
||||
# assertions below would prove nothing, and cleanup would tear down a real
|
||||
# service.
|
||||
if [[ "$SMOKE_FORCE" != "true" ]]; then
|
||||
if [[ -e "$SHIM_PATH" ]]; then
|
||||
fail "$SHIM_PATH already exists; set SMOKE_FORCE=true to smoke over it"
|
||||
fi
|
||||
if systemctl --user cat "$SERVICE_NAME" >/dev/null 2>&1; then
|
||||
fail "$SERVICE_NAME is already installed; set SMOKE_FORCE=true to smoke over it"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "==> Onboarding paperclipai@$PAPERCLIPAI_VERSION with --install-service"
|
||||
echo " Data dir: $DATA_DIR"
|
||||
if ! timeout "$ONBOARD_TIMEOUT_SECONDS" \
|
||||
npx --yes "paperclipai@${PAPERCLIPAI_VERSION}" onboard --yes --install-service --data-dir "$DATA_DIR"; then
|
||||
diagnostics
|
||||
fail "onboard exited non-zero"
|
||||
fi
|
||||
|
||||
echo "==> Verifying the managed shim"
|
||||
if [[ ! -x "$SHIM_PATH" ]]; then
|
||||
diagnostics
|
||||
fail "no executable shim at $SHIM_PATH after onboarding"
|
||||
fi
|
||||
|
||||
echo "==> Waiting for $SERVICE_NAME to serve $HEALTH_URL"
|
||||
for ((i = 1; i <= SMOKE_READY_TIMEOUT_SECONDS; i += 1)); do
|
||||
state="$(systemctl --user is-active "$SERVICE_NAME" 2>/dev/null || true)"
|
||||
if [[ "$state" == "failed" ]]; then
|
||||
diagnostics
|
||||
fail "$SERVICE_NAME entered the failed state"
|
||||
fi
|
||||
if curl -fsS "$HEALTH_URL" >/dev/null 2>&1; then
|
||||
if [[ "$state" != "active" ]]; then
|
||||
diagnostics
|
||||
fail "$HEALTH_URL answers but $SERVICE_NAME is '$state' - something other than the service is serving"
|
||||
fi
|
||||
echo "==> Service smoke passed: $SERVICE_NAME is active and serving $HEALTH_URL"
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
diagnostics
|
||||
fail "$HEALTH_URL not ready after ${SMOKE_READY_TIMEOUT_SECONDS}s (unit state: $(systemctl --user is-active "$SERVICE_NAME" 2>/dev/null || echo unknown))"
|
||||
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { accessSync, constants, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
// Pins the wiring that makes the background-service smoke an effective gate.
|
||||
// The service leg exists because v2026.824.0 shipped a service install that
|
||||
// crash-looped on a missing shim while the Docker smoke stayed green; these
|
||||
// assertions keep the job from being silently disconnected or weakened.
|
||||
|
||||
const repoRoot = new URL("..", import.meta.url).pathname.replace(/\/$/, "");
|
||||
const scriptPath = join(repoRoot, "scripts", "service-onboard-smoke.sh");
|
||||
const script = readFileSync(scriptPath, "utf8");
|
||||
const smokeWorkflow = readFileSync(join(repoRoot, ".github", "workflows", "release-smoke.yml"), "utf8");
|
||||
const releaseWorkflow = readFileSync(join(repoRoot, ".github", "workflows", "release.yml"), "utf8");
|
||||
|
||||
test("smoke script is executable and parses", () => {
|
||||
accessSync(scriptPath, constants.X_OK);
|
||||
execFileSync("bash", ["-n", scriptPath]);
|
||||
});
|
||||
|
||||
test("smoke script keeps its load-bearing assertions", () => {
|
||||
assert.match(script, /^set -euo pipefail$/m);
|
||||
// Onboards the published artifact with the service leg forced on.
|
||||
assert.match(script, /onboard --yes --install-service/);
|
||||
// Fails when the shim never materialized.
|
||||
assert.match(script, /no executable shim at .*after onboarding/);
|
||||
// Fails when the unit dies instead of serving.
|
||||
assert.match(script, /entered the failed state/);
|
||||
// Fails when health answers but the service is not what is serving --
|
||||
// the exact signature of the v2026.824.0 defect.
|
||||
assert.match(script, /something other than the service is serving/);
|
||||
// Refuses to smoke over a real install unless forced.
|
||||
assert.match(script, /SMOKE_FORCE/);
|
||||
});
|
||||
|
||||
test("release-smoke workflow runs the service leg against the input version", () => {
|
||||
assert.match(smokeWorkflow, /^ smoke_service:$/m);
|
||||
assert.match(smokeWorkflow, /scripts\/service-onboard-smoke\.sh/);
|
||||
const serviceJob = smokeWorkflow.split(/^ smoke:$/m)[0];
|
||||
assert.match(serviceJob, /PAPERCLIPAI_VERSION: \$\{\{ inputs\.paperclip_version \}\}/);
|
||||
// Diagnostics must survive the run: cleanup stays off in CI and the
|
||||
// artifact name cannot collide with the Docker job's upload.
|
||||
assert.match(serviceJob, /SMOKE_CLEANUP: "false"/);
|
||||
assert.match(serviceJob, /\$\{\{ inputs\.artifact_name \}\}-service/);
|
||||
});
|
||||
|
||||
test("nightly and beta smokes still route through the reusable workflow", () => {
|
||||
const calls = releaseWorkflow.match(/uses: \.\/\.github\/workflows\/release-smoke\.yml/g) ?? [];
|
||||
assert.ok(calls.length >= 2, "smoke_nightly and smoke_beta must call release-smoke.yml so smoke_service gates them");
|
||||
});
|
||||
Reference in new issue
Block a user