Skip to content

cli test: package-install-local-jobs-shared-name SIGKILLs its first install at a fixed 120 s under full-suite load — a false red from pnpm test on a 4 vCPU box #25499

Closed

Description

@objectstack-fleet

Filing-gate category: ① — a reproducible defect with a named location (test infrastructure).
reach: the public entry pnpm test (AGENTS.md Post-Task Checklist step 1), measured once on a 4 vCPU / 15 GiB container at f0fdd45bbc: a false red.
Who acts: the seat that owns packages/cli tests (domain:server after #25247). The fix is one test file.
Duplicate search: package-install-local-jobs-shared-name integration test timeout — 3 hits (#24100, #21602, #21489, all closed). None is about this timeout.

What happened

On main f0fdd45bbc, a full pnpm test (turbo, --concurrency=50%, VITEST_MAX_WORKERS=3 from scripts/vitest-worker-cap.mjs) on a 4 vCPU container produced:

@objectstack/cli:test:  ❯  integration  test/package-install-local-jobs-shared-name.integration.test.ts (9 tests | 6 failed) 209590ms
      × all three packages install (exit 0)
      × … and each later package's job runs too
      × the catalogue: the first package keeps the authored name; …
      × … and only its own: ALPHA and GAMMA run on
      × after a restart, both rehydrated packages run
      × uninstalling the holder of the bare name (ALPHA) stops its job, …

Run on its own on the same machine and tree (pnpm --filter @objectstack/cli exec vitest run test/package-install-local-jobs-shared-name.integration.test.ts), it passes 9/9 in 75.9 s. The whole @objectstack/cli suite, run alone with VITEST_MAX_WORKERS=3, also passes: 497 files, 6271 tests. Hourly CI on main is green for this file.

Why (from the source)

packageInstall() (line ~252) gives each os package install child a hard setTimeout(() => child.kill('SIGKILL'), 120_000). The beforeAll runs three installs in sequence against a live os start. In the loaded run the file took 209 s in total, so the first install was SIGKILLed at 120 s. The first assertion (exit 0) failed, and the five assertions that read its results failed after it.

This is the same shape as #25298 / #25319: a wall-clock budget set for an idle machine. It goes red under suite load, while the code is correct.

What done looks like

Session: session_014C7q5Hm34g4EPdirar9SzN


Generated by Claude Code

Activity

  1. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed on Oct 23, 2026
  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: lands in packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts (packageInstall(), the fixed 120 s SIGKILL); rationale: a test-only false red under full-suite load on a 4 vCPU box; CI on main is green. Take the budget from the shared CLI spawner helpers rather than raising the number.
    Path: instrument · pnpm test (AGENTS.md Post-Task Checklist step 1) | none | n/a
    Grade: priority:p3 — costs a local re-run, not a wrong merge; CI is unaffected.
    Type: Bug

    Session: session_01AkmasAfXt3cu83xGzkuKhe (objectstack triage, run on the maintainer's request in the project thread)


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop · domain:cli seat 1 · p3 · 2026-10-23T20:22Z
    Session: session_01CxBKycaiUpA1yGx1XyoGqX
    Account: os-sales (the seat's linked user; always the card's assignee)
    Branch: claude/issue-25499-install-budget
    Worktree: objectstack-issue-25499
    Domain: domain:server (this seat's side of the server lane under the coordinator's split: former cli and engine paths)
    Seat: domain:cli#1 (seat post #6024; 由Sales账户的项目负责)
    File surface (read on origin/main 74496c64b0; stop on a breach): packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts (packageInstall(), the fixed 120 s SIGKILL), the shared CLI spawner helper it should read its budget from (#24396) only if that helper needs no new export, one changeset or skip-changeset.
    Container & model: S, mode:subagent, model: default tier
    Clause-②: no
    Basis for the Clause-② line: test-only; no published surface moves.
    Responsibility: n/a — filed from a local pnpm test false red (session_014C7q5Hm34g4EPdirar9SzN), triaged 6371356580.
    Thread-read: 6371356580
    Serial constraints cleared: none of the 8 open PRs touches this test file or a cli spawner helper (file lists read in this act).


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25499,
      "status": "done",
      "branch": "claude/issue-25499-install-budget",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25547",
      "session": "session_01CxBKycaiUpA1yGx1XyoGqX",
      "premise_still_valid": true,
      "summary": "packageInstall() in package-install-local-jobs-shared-name.integration.test.ts no longer has its own fixed 120 s SIGKILL. beforeAll takes one deadline when it starts (SETUP_BUDGET_MS = the hook's existing 600 s timeout, unchanged, less a 10 s KILL_REPORT_RESERVE_MS), and each install may run until that deadline. The install child now spawns detached, so the SIGKILL reaches the whole group, including the node process tsx starts. A kill rejects with a message naming the install, its wall time and the budget, so a hang shows as that message and not as exit null or 'Hook timed out'. elapsedMs goes into the first it's failure message as evidence only. The shared spawner helpers (test/helpers/serve-process.ts) export no install budget and no load-aware ceiling, so no helper was touched and no new export was added. Six sibling package-install-local-* files still carry the same fixed 120 s ceiling: listed in the PR's Acceptance notes, not changed.",
      "tests": "HEAD 02097ac15b, 4 vCPU, all under os-verify-lock. (1) The file alone, pure tree: Test Files 1 passed, Tests 9 passed, 87.10 s. (2) Per-install wall time alone, using a one-off console.log mutation through scripts/ablation-replace.mjs in WRAP mode (restored): alpha 11105 ms, beta 10159 ms, gamma 11483 ms, all exit 0. (3) The same mutation across the whole cli integration tier at VITEST_MAX_WORKERS=3: alpha 14198, beta 13516, gamma 15747 ms. Tier: Test Files 171 passed, 1 skipped (172); Tests 1469 passed, 9 skipped; 2498.96 s; the lock reported VERDICT command-exit 0. (4) Ablation with a bogus artifact path: red at the install leg, 'alpha (9838 ms): ... Cannot read artifact: ENOENT', expected 1 to be 0; 9/9 failed; no hook timeout. (5) Ablation with the budget spent (deadline = Date.now() + 1): red in 16.96 s, beforeAll rejects 'os package install in .../shared_alpha was SIGKILLed after 7 ms: the setup budget (600000 ms for the whole beforeAll, less a 10000 ms reserve) was spent.'; the file fails and its 9 tests are skipped; no 'Hook timed out'. After the restore, the blob equals HEAD (bc1e7d9b3a) and git diff HEAD is empty. My first logging mutation did nothing: its anchor was a substring of its replacement, the tool refused it (anchor 1 -> 1), and it was re-run with a distinct anchor. (6) cli typecheck exit 0 (check:test-typecheck OK). cli unit tier: Test Files 326 passed, Tests 4808 passed. pnpm lint exit 0. NOT MEASURED: a full turbo-wide pnpm test on this box was not run. The loaded reading is the cli integration tier only, where installs took 14-16 s, far from the old 120 s ceiling. So tolerance of a busier box is argued from the design, not measured.",
      "gates": "dispatch-gates --commands derived 54 families. Run locally with exits captured before any pipe: 52 exit 0. check:dts-closure, check:lean-entry-closure and check:sourcemap-no-sources-content first exited 3 (no build), then exited 0 after the cli closure build (lock VERDICT command-exit 0). NOT MEASURED: check:dual-build-cjs-loads, reason: PREREQUISITE NOT MET, it reads every package's dist and only the cli closure was built. NOT MEASURED: check:type-check-debt, reason: exit 3, its re-measure build got no verify-lock turn; the cli typecheck with check:test-typecheck ran green under the lock. --ran reconciliation: '✓ dispatch-gates --ran: 54 derived famil(ies) accounted for — 52 run, 2 NOT-MEASURED', exit 0. Caveat: derived on a tree 10 commits behind origin/main; the two drifted files are unrelated (an adr-anchor json, i18n baseline). The base was not merged: no conflict, and no overlap with packages/cli/test/package-install-* or serve-process.ts. Lane extra: pnpm lint exit 0 (lock VERDICT command-exit 0). CI on PR #25547 at report time: Check Changeset success, the 'No other open PR may claim the same issue' check success, everything else in_progress.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/25547/assignees + POST /issues/25547/labels [skip-changeset]; (2) comment = POST /repos/objectstack-ai/objectstack/issues/25499/comments (this report). Plus git push (not REST).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · six sibling files keep the same fixed 120 s install SIGKILL (package-install-local-{jobs,jobs-pull,hooks,handlers,boot-steps,uninstall-cleanups}.integration.test.ts); no red on record; noted in the PR's Acceptance notes, not filed",
        "carrier: none · in this file, bootStart's BOOT_TIMEOUT_MS does not read the shared deadline, so a hung second boot after slow installs would show as Hook timed out; not observed; noted only"
      ],
      "deviations": "Three conflicts, followed as the dispatch wrote them. (1) The PR body's first two lines are the dispatch's attribution lines, and the first of them is an HTML comment. The role file says the body's first line is 'Fixes #n' and bans HTML comments in GitHub text. 'Fixes #25499' is line 4, and the read-back is byte-identical (5190/5190). (2) The PR body ends with both the role file's session-URL footer and the dispatch's closing lines. (3) The commit carries the AGENTS.md model-free trailer pair only."
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #25547 comment 6376367074 · domain:cli seat 1 · session session_01CxBKycaiUpA1yGx1XyoGqX · 2026-10-23T22:56Z


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:cli seat 1 · session session_01CxBKycaiUpA1yGx1XyoGqX · 2026-10-23T23:21Z

    reading result
    PR #25547 object merged: true, merge commit ab596f82c, merged 2026-10-23T23:20:41Z through the merge queue
    origin/main ab596f82c is an ancestor of origin/main, single parent (squash)
    queue branch no gh-readonly-queue/main/* head for PR 25547 remains

    State: card closed completed by Fixes #25499; pm:dispatched stripped in this act.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p3tooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions