Skip to content

chore: port clean memory-guard successor - #8

Draft
twoimo wants to merge 15 commits into
mainfrom
fix/memory-guard-domain-scheduler
Draft

chore: port clean memory-guard successor#8
twoimo wants to merge 15 commits into
mainfrom
fix/memory-guard-domain-scheduler

Conversation

@twoimo

@twoimo twoimo commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Temporary internal PR used only to apply the Yeachan-Heo#3133 net diff to current dev before the remaining Windows-domain and scheduler repairs. The one-shot trigger file is removed by the port commit.

Yeachan-Heo and others added 2 commits July 25, 2026 04:27
…ispose flake (Yeachan-Heo#3144)

* test(sdk): make teardown ordering witness production-observable

The Phase 2 rewrite of "session teardown drains admitted direct gate
resolution" was accepted with a narrowed claim because a mutation probe
survived: replacing `await rt.waitForGateResolutionQuiescence()` with
`void ...` still passed. The test fully mocked `resolveGate`, so the
delayed operation never touched the real terminal controller, and it
released the resolver after a single setImmediate while `stopSession()`
was independently awaiting the native `pushFrameAndWait(session_closed)`
barrier — resolution therefore completed before teardown reached
detachment even without the quiescence await.

Now the test calls through the original `registerGateTerminalController`
and the original `resolveGate` (wrapping the latter only with a deferred
pre-terminalization gate), makes `pushFrameAndWait(session_closed)` an
explicit test-controlled pre-drain barrier, asserts the controller is
still attached at the quiescence point, then observes real accepted
terminalization and gate continuation before detachment.

Mutation-proved: the void-await mutation now FAILS at the pre-detachment
assertion (controllerAttached false). Passes 10/10 unmutated.

* test(runtime): poll for the TERM marker in the concurrent-dispose redteam

Caught live by the stabilization soak: main-nontag rehearsal run
30149261910 failed on shard 11 with

  (fail) process-lifecycle adversarial owned-process invariants >
         double and concurrent dispose share one settled result and
         issue one terminating signal
  expect(received).toHaveLength(expected)  Expected: 1  Received: 0

The child's TERM trap appends its marker asynchronously
(`trap 'echo term >> $tmp; exit 0' TERM`), so under shard load
`awaitExit` can return before that write lands and the single-sample
read observes an empty file. The file already has a `waitForAsync`
helper for exactly this shape; the marker assertion just wasn't using
it.

Polls for the single terminating signal before asserting, preserving
the original invariant (exactly one `term` line — not "at least one").

Verified: 15/15 reruns, 4x parallel contention clean, whole file 9/9,
typecheck and biome clean.

This test was NOT in the 62-suspect audit shortlist: it did not fail or
retry during the mined two-week window, so it is a genuinely new
observation the soak surfaced.

---------

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
Yeachan-Heo and others added 6 commits July 25, 2026 17:22
`sh` runs a TERM trap only after the current foreground command returns.
With the child looping on `sleep 1` and `gracefulMs: 500`, dispose could
escalate to SIGKILL before the handler wrote its `term` marker, so the
one-terminating-signal assertion saw an empty file (observed in CI run
30149261910, coding-agent shard 11).

Shorten the loop interval to 0.05s and use the module's own
`DEFAULT_GRACEFUL_MS` (2000ms) so the trap has a deterministic window.
Under 18-worker CPU contention the old shape wins the race 8/20; the new
shape wins 20/20. All assertions are unchanged.

Also record the missing `## [Unreleased]` changelog entries for Yeachan-Heo#3109,
Yeachan-Heo#3127, and Yeachan-Heo#3131, found while auditing release scope after v0.11.9.
…turns (Yeachan-Heo#3147)

Lifecycle `session_shutdown` started `controller.stopCurrentSession(ctx)`
but discarded the promise, awaiting only `stopSession(id)`. Once startup
has settled the host is broker-visible and can accept `session.close`
while the startup handler's post-start `reconcileCurrentSession` is still
running. That reconciliation can mint a replacement notification-root
token; `ensureTelegramDaemon` then unregisters it asynchronously. Shutdown
could therefore return — and disposal exit — before that unregister's file
lock and atomic registry write settled, leaving a stale `sessions[id]` row
that the retained older token is correctly fenced from removing
(`unregisterNotificationRoot` rejects token mismatches by design).

Now shutdown snapshots `sessionStartPromises.has(id)` first and awaits the
settled controller stop after `stopSession` whenever startup was NOT
pending, so completed-start reconciliation and its replacement-token
cleanup are joined. The intentional nonblocking path is preserved exactly
where it matters: a genuinely pending startup entry (the `/notify on`
case) still leaves the controller stop fire-and-forget.

Surfaced by the flaky-CI stabilization soak. The regression test
"Telegram root release failure is retained and retried through lifecycle
shutdown" failed deterministically on darwin-arm64 at dev head while
Linux CI stayed green (run 30147146988, 34/34 shards) — a completion-
ordering divergence, not a `/var` canonicalization or native-addon issue:
both registry and notification-root paths are lexical `path.join` with no
realpath or case folding.

Verified on darwin-arm64: the previously-failing test now passes 10/10,
the whole sdk-host-wiring file is 72/72 (first fully green run of this
file on Darwin), and telegram daemon + btw-e2e are 463/463. The assertion
was kept intact rather than replaced with polling, which would have hidden
the lifecycle-return bug.

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…eachan-Heo#3149)

Caught by the stabilization soak: main-nontag rehearsal run 30151115867
failed on shard 8 with

  (fail) session_start swallows startup plus owner-release failure
         without surfacing an extension error
  expect(surfaced).toEqual([])   received 1 surfaced error

The test used `mockRejectedValueOnce` on the SHARED prototypes
`NotificationServer.prototype.start` and `SessionSdkHost.prototype.stop`.
That is a one-shot global: a peer test scheduled concurrently in the same
shard can consume the single rejection first. When that happens this
test's own `start()` resolves, so `startSession` never reaches the
`stopSession` catch that sets `suppressExtensionError`
(src/sdk/bus/index.ts:4407-4420), and the startup error surfaces through
`session_start` instead of being swallowed.

Three separate tests in this file arm one-shot rejections on the same two
prototypes, so the interference is cross-test within a shard rather than
a missing restore — every one of them restores correctly.

Replaces both one-shots with per-test guarded implementations that reject
only on this test's first call and then delegate to the real method,
preserving the existing assertions (including
`expect(hostStop).toHaveBeenCalledTimes(2)`, which is what makes the
"first call rejects" semantics load-bearing).

Verified on darwin-arm64: 10/10 targeted reruns, 6x concurrent whole-file
runs with zero failures, whole file 72/72, typecheck and biome clean.

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
Yeachan-Heo and others added 5 commits July 25, 2026 20:58
…#3139) (Yeachan-Heo#3146)

The release CI default was narrowed to `contents: read` in Yeachan-Heo#3136 with
`publish` retaining the sole job-level `contents: write` override, but no
automated policy test protected that invariant. `dev-ci.yml` also had no
explicit permission block and inherited the repository default.

Add `scripts/check-workflow-permissions.ts`: a deterministic offline
default-deny evaluator plus CLI that parses committed workflow YAML and
requires every workflow to declare a least-privilege `permissions` block.
Write scopes are denied everywhere except one explicit allowlist triple
(ci.yml / publish / contents), and the three known workflows must declare
exactly `contents: read`. Violations name workflow, job, permission path,
actual, and expected.

Codify `contents: read` on `dev-ci.yml` after auditing its jobs: they only
check out, install, test, and exchange artifacts through the Actions
artifact API, with no `git push`, `gh` CLI, `secrets.*`, or release/PR
mutation, so no write-scoped token is required.

Back it with real-YAML mutation proofs that read committed workflows from
disk, mutate the parsed document, and re-evaluate -- covering workflow and
job `write`, `write-all`, extra scopes, deleted permission blocks, and
malformed job shapes. Route the regression through affected-path CI in both
the broad and targeted planners so workflow and CI-harness changes select it
alongside the existing release-policy suite, and pin the invariant in
`release-policy.test.ts` as well.

Refs Yeachan-Heo#3139

Co-authored-by: Yeachan-Heo <yeachan-heo@gajae.dev>
…/ resolver (Yeachan-Heo#3145)

Closes non-blocking follow-up from the Yeachan-Heo#3080 post-merge review: cleanup_pending marker asymmetry between the async gate and the sync resolver.

Reviewed exact head 90aa337 with durable MERGE_READY and green exact-head CI. Merged after post-merge Dev CI 30157160426 on 352a2c1 turned terminal green.
…o what shipped (Yeachan-Heo#3140)

Documentation-only correction of readiness claims from Yeachan-Heo#3080.

Exact-head MERGE_READY at 6cf2764 with green CI. Held during red/nonterminal post-merge gates; merged after Dev CI 30158413804 on 2317939 terminalized success.
…3070)

Exact-head MERGE_READY at 332942d with green CI. Merged after post-merge Dev CI 30158899514 on e108816 terminalized success.
…eachan-Heo#3132)

`retryDelayMs()` honoured the server's `Retry-After` verbatim:

    if (Number.isFinite(seconds)) return Math.max(baseline, Math.max(0, seconds * 1000));

There was no upper bound, so a hostile or misconfigured endpoint could stall
the usage fetch for as long as it liked. Verified: `Retry-After: 86400` made
the provider sleep 86_400_000ms (24 hours), and the HTTP-date form did the
same (86_399_386ms). The sleep is abort-aware, but with no signal — or a
long-lived one — the usage refresh simply hangs, and auth-storage ranks
credentials off this call.

Every sibling path in the repo already bounds this:
  - utils/fetch-retry.ts  DEFAULT_MAX_DELAY_MS = 60_000 (+ fail-fast above cap)
  - providers/openai-bounded-rate-limits.ts  OPENAI_RETRY_DELAY_CAP_MS = 60_000
  - session/agent-session.ts  maxAcceptableDelayMs = 30_000
Only the Claude usage path was missing a ceiling.

Fix: add MAX_RETRY_DELAY_MS = 60_000 and clamp through clampRetryDelay(),
which also drops non-finite/negative hints. 60s matches the existing
convention and preserves both pre-existing assertions exactly
(`Retry-After: 1` → 1000, `Retry-After: 60` → 60_000).

Regression coverage (test/claude-usage-retry.test.ts): absurd numeric
Retry-After, absurd HTTP-date Retry-After, and a negative Retry-After. The
first two fail against the unfixed code (received 86_400_000 / 86_399_386,
expected 60_000).

Gates: claude-usage-retry (11 pass), usage suite (28 pass across 5 files),
tsc --noEmit clean.

Co-authored-by: dmae97 <dmae97@users.noreply.github.com>
@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
Owner-approved MERGE_READY at exact head 4caf43c with green CI (31 checks). Merged after post-Yeachan-Heo#3132 Dev CI 30159910672 on 77c9a60 terminalized success. Yeachan-Heo#3134 became dirty and was skipped under one-at-a-time sequencing.
@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Superseded diagnostic: the initial memory run applied the current-dev patch and failed only because the final repair script expected the pre-fix latch shape.

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Superseded diagnostic: the second memory run confirmed the latch fix was already present. The verifier now uses an idempotent final-repair path.

@twoimo
twoimo force-pushed the fix/memory-guard-domain-scheduler branch from ce4fdb0 to f14e244 Compare July 25, 2026 14:11
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Superseded diagnostic: this run used the pre-idempotence memory repair wrapper and failed before tests. Replaced by the minimal owner-requested regression inserter.

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Superseded diagnostic: this run retried the already-resolved scheduler transformation. The current verifier preserves the reviewed implementation and adds only the two requested direct Windows accounting regressions.

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

Optional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build
      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)
      at /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/index.js:16:24

::error file=work/packages/natives/native/loader-state.js,line=561,col=12,title=error: Failed to load pi_natives native addon for linux-x64 (modern).::Tried:%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A%0AIf installed via npm/bun, try reinstalling: bun install @gajae-code/natives%0AIf developing locally, build with: bun --cwd=packages/natives run build%0AOptional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build%0A      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)%0A      at /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/index.js:16:24
-------------------------------


::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.54ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.07ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.07ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.02ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.02ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.10ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.09ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.10ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.04ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.02ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.06ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.04ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.02ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.14ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.04ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.09ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.08ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.84ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.34ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.05ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.13ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.08ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.21ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.28ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.09ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.05ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.04ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:

# Unhandled error between tests
-------------------------------
556 | 				`Supported platforms: ${SUPPORTED_PLATFORMS.join(", ")}\n` +
557 | 				"If you need support for this platform, please open an issue.",
558 | 		);
559 | 	}
560 | 	const details = errors.map(error => `- ${error}`).join("\n");
561 | 	throw new Error(
                 ^
error: Failed to load pi_natives native addon for linux-x64 (modern).

Tried:
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'

If installed via npm/bun, try reinstalling: bun install @gajae-code/natives
If developing locally, build with: bun --cwd=packages/natives run build
Optional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build
      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)

::error file=work/packages/natives/native/loader-state.js,line=561,col=12,title=error: Failed to load pi_natives native addon for linux-x64 (modern).::Tried:%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A%0AIf installed via npm/bun, try reinstalling: bun install @gajae-code/natives%0AIf developing locally, build with: bun --cwd=packages/natives run build%0AOptional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build%0A      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)
-------------------------------


::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.09ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.04ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.03ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:

# Unhandled error between tests
-------------------------------
556 | 				`Supported platforms: ${SUPPORTED_PLATFORMS.join(", ")}\n` +
557 | 				"If you need support for this platform, please open an issue.",
558 | 		);
559 | 	}
560 | 	const details = errors.map(error => `- ${error}`).join("\n");
561 | 	throw new Error(
                 ^
error: Failed to load pi_natives native addon for linux-x64 (modern).

Tried:
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'

If installed via npm/bun, try reinstalling: bun install @gajae-code/natives
If developing locally, build with: bun --cwd=packages/natives run build
Optional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build
      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)

::error file=work/packages/natives/native/loader-state.js,line=561,col=12,title=error: Failed to load pi_natives native addon for linux-x64 (modern).::Tried:%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A%0AIf installed via npm/bun, try reinstalling: bun install @gajae-code/natives%0AIf developing locally, build with: bun --cwd=packages/natives run build%0AOptional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build%0A      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)
-------------------------------


::group::packages/coding-agent/test/tools/resource-gc.test.ts:

# Unhandled error between tests
-------------------------------
556 | 				`Supported platforms: ${SUPPORTED_PLATFORMS.join(", ")}\n` +
557 | 				"If you need support for this platform, please open an issue.",
558 | 		);
559 | 	}
560 | 	const details = errors.map(error => `- ${error}`).join("\n");
561 | 	throw new Error(
                 ^
error: Failed to load pi_natives native addon for linux-x64 (modern).

Tried:
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'
- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'

If installed via npm/bun, try reinstalling: bun install @gajae-code/natives
If developing locally, build with: bun --cwd=packages/natives run build
Optional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build
      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)

::error file=work/packages/natives/native/loader-state.js,line=561,col=12,title=error: Failed to load pi_natives native addon for linux-x64 (modern).::Tried:%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/work/gajae-code/gajae-code/work/packages/natives-linux-x64/native/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-modern.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-modern.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64-baseline.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64-baseline.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A- /home/runner/.bun/bin/pi_natives.linux-x64.node: ResolveMessage: Cannot find module '/home/runner/.bun/bin/pi_natives.linux-x64.node' from '/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js'%0A%0AIf installed via npm/bun, try reinstalling: bun install @gajae-code/natives%0AIf developing locally, build with: bun --cwd=packages/natives run build%0AOptional x64 variants: TARGET_VARIANT=baseline|modern bun --cwd=packages/natives run build%0A      at loadNative (/home/runner/work/gajae-code/gajae-code/work/packages/natives/native/loader-state.js:561:12)
-------------------------------


5 tests failed:
(fail) probeWindowsJobMemory > loads through the native loader and returns a tagged result [2.45ms]

 35 pass
 5 fail
 4 errors
 68 expect() calls
Ran 40 tests across 9 files. [644.00ms]

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

   Compiling pi-ast v0.11.10 (/home/runner/work/gajae-code/gajae-code/work/crates/pi-ast)
   Compiling icy_sixel v0.5.0
   Compiling grep-regex v0.1.14
    Finished `ci` profile [optimized + debuginfo] target(s) in 4m 34s
Normalizing native addon filename: pi_natives.linux-x64-gnu.node → pi_natives.linux-x64-modern.node
Generated 84 explicit ESM exports in index.js, fixed 9 const enums in index.d.ts
Build complete.
Generated 84 explicit ESM exports in index.js, fixed 0 const enums in index.d.ts
 * macOS computer-use controller.
Checked 21 files in 187ms. No fixes applied.
bun test v1.3.14 (0d9b296a)

::group::packages/natives/test/memory-guard-build-wiring.test.ts:
(pass) memory-guard native build wiring > rejects generated bindings that omit the Windows memory probe [0.17ms]
(pass) memory-guard native build wiring > rejects native addons that omit the Windows memory probe [0.18ms]

::endgroup::

::group::packages/natives/test/memory-guard-native.test.ts:
(pass) probeWindowsJobMemory > loads through the native loader and returns a tagged result [4.37ms]
(pass) probeWindowsJobMemory > rejects stale same-version bindings without the memory probe capability [0.09ms]

::endgroup::

::group::packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:
(pass) memory-guard native smoke fast path > matches only the exact internal argv [0.10ms]
(pass) memory-guard native smoke fast path > emits the tagged native receipt without normal command dispatch [0.26ms]
38 | 		expect(cliSource.indexOf("if (isMemoryGuardNativeSmokeFastPath(argv))")).toBeLessThan(
39 | 			cliSource.indexOf("await installRuntimeGlobals();"),
40 | 		);
41 | 
42 | 		const ciSource = await Bun.file(path.join(import.meta.dir, "../../..", ".github/workflows/ci.yml")).text();
43 | 		expect(ciSource).toContain("bun test packages/natives/test/memory-guard-native.test.ts");
                        ^
error: expect(received).toContain(expected)

Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"
Received: "name: CI\n\non:\n   push:\n      branches: [main]\n      tags: [\"v*\"]\n   pull_request:\n      branches: [main]\n   workflow_dispatch:\n      inputs:\n         rehearsal:\n            description: \"Rehearsal mode: run the exact tag build/verify graph (native -> binaries) with publish excluded, or the non-tag main graph.\"\n            required: true\n            type: choice\n            options: [tag-build-verify, main-nontag]\n\n# Least privilege by default: only `publish` needs write, and it declares its\n# own job-level `contents: write` override. This keeps rehearsal dispatches\n# (and every build/verify job) on a read-scoped GITHUB_TOKEN.\npermissions:\n   contents: read\n\nconcurrency:\n   # Release tags never cancel; ordinary CI is cancellable per ref.\n   group: ci-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.rehearsal || 'event' }}\n   cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }}\n\njobs:\n   # ---------------------------------------------------------------------------\n   # PR + main branch: lint/typecheck (native-free) and the test suite.\n   # These never run on tags — a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"

      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)

::error file=work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts,line=43,col=20,title=error: expect(received).toContain(expected)::Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"%0A a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"%0A%0A      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.76ms]

::endgroup::

::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.73ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.07ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.03ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.02ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.03ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.08ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.09ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.14ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.07ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.06ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.13ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.10ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.07ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.24ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.06ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.13ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.09ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.42ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.11ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.03ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.14ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.14ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.25ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.41ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.07ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.06ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.06ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.07ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.08ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:
(pass) resolveMemoryGuardPolicy > stays disabled by default and converts MB values to bytes [0.95ms]
(pass) resolveMemoryGuardPolicy > rounds fractional megabyte settings to integer bytes [0.36ms]
(pass) memory guard arbitration > does not let an unsupported host candidate mask an executable worker candidate [0.21ms]
(pass) memory guard arbitration > revalidates out when the selected target is no longer over allowance [0.24ms]
(pass) MemoryGuardHost > serializes action execution so only one run is in flight [1.10ms]
(pass) MemoryGuardHost > schedules based on earliest per-registration due time [0.57ms]
(pass) MemoryGuardHost > defers scheduling when a tick is in progress [0.41ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.14ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.05ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.04ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:
(pass) resource GC red-team safety invariants > keeps uncapped Windows Job commit charge separate from physical RAM [0.42ms]
(pass) resource GC red-team safety invariants > does not clamp a Windows commit-domain policy cap to physical RAM [0.24ms]
(pass) resource GC red-team safety invariants > never evicts ownerless tabs under RSS pressure and warns once [1.35ms]
(pass) resource GC red-team safety invariants > does not close a tab that flips in-flight between snapshot and eviction [0.61ms]
(pass) resource GC red-team safety invariants > does not double-release tabs eligible for both idle and RSS pressure [1.87ms]
(pass) resource GC red-team safety invariants > RSS oscillation re-warns exactly once per over-limit episode [0.38ms]
(pass) resource GC red-team safety invariants > disabled browser GC performs no eviction even when idle and over limit [0.38ms]
(pass) resource GC red-team safety invariants > does not evict a tab idle exactly at the configured threshold [0.35ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc.test.ts:
(pass) Linux cgroup memory sampling > fails over from an unreadable containing mount to a later compatible mount [1.94ms]
(pass) Linux cgroup memory sampling > compares pressure across every compatible containing mount [1.09ms]
(pass) Linux cgroup memory sampling > preserves distinct ancestor chains that resolve to the same leaf path [1.09ms]
(pass) Linux cgroup memory sampling > uses the namespace-relative fallback after containment candidates are exhausted [1.60ms]
(pass) Linux cgroup memory sampling > samples the mount root and selects the ancestor nearest to pressure [1.64ms]
(pass) Linux cgroup memory sampling > selects ancestor pressure against the configured policy cap [0.08ms]
(pass) Linux cgroup memory sampling > ignores zero and malformed counters while preserving valid unlimited usage [2.75ms]
(pass) resource GC controller > applies enabled memory policy to GC and sustained restart advisory telemetry [2.07ms]
(pass) resource GC controller > keeps positive fractional sweep intervals schedulable [0.38ms]
(pass) resource GC controller > uses aggregate domain usage and runs process-wide GC once for concurrent sessions [0.47ms]
(pass) resource GC controller > schedules an enabled guard at its configured check interval [58.78ms]
(pass) resource GC controller > idle sweep evicts idle tabs oldest-first and spares recent ones [0.53ms]
(pass) resource GC controller > forwards expired dead managed tabs to the authoritative supervisor recheck [0.31ms]
(pass) resource GC controller > skips tabs owned by no registered session [0.40ms]
(pass) resource GC controller > warns under RSS pressure when only a recovery-held dead tab remains [0.37ms]
(pass) resource GC controller > never evicts non-idle tabs under RSS pressure (IR-1) and warns once instead [0.38ms]
(pass) resource GC controller > evicts idle tabs LRU under pressure, then warns once if still over limit [0.52ms]
(pass) resource GC controller > warns exactly once per continuous no-evictable RSS-pressure episode [0.42ms]
(pass) resource GC controller > reference-counts the shared timer across sessions [0.27ms]
(pass) resource GC controller > does not run overlapping ticks [0.56ms]
(pass) resource GC controller > lazy-arms and throttles stale screenshot cleanup [0.55ms]
(pass) resource GC controller > resolves documented defaults from settings [0.12ms]
(pass) resource GC monotonic scheduler > A: rearms only for an earlier distinct registration [0.75ms]
(pass) resource GC monotonic scheduler > keeps unsupported duplicate session IDs from advancing the pending deadline [0.36ms]
(pass) resource GC monotonic scheduler > B: equal and later registrations preserve the existing timer [0.70ms]
(pass) resource GC monotonic scheduler > reschedules an active session after live memory-guard cadence changes [0.29ms]
(pass) resource GC monotonic scheduler > preserves an earlier shared deadline when another session changes cadence [0.44ms]
(pass) resource GC monotonic scheduler > C: unregistering the shortest session never postpones pending work [0.52ms]
(pass) resource GC monotonic scheduler > D: retains an expired deferred deadline from timer-owned blocked work [0.96ms]
(pass) resource GC monotonic scheduler > E: defers a consumed timer while externally initiated work owns the lock [0.63ms]
(pass) resource GC monotonic scheduler > F: preserves a short registration deadline during external work [0.56ms]
(pass) resource GC monotonic scheduler > G: fences stale completion after stop and re-registration [0.72ms]
(pass) resource GC monotonic scheduler > H: ignores a queued callback from a superseded same-generation timer [0.42ms]
(pass) resource GC monotonic scheduler > keeps scheduler time separate from eligibility time and resets all scheduler state [0.38ms]
(pass) resource GC settings precedence > lets project .gjc/settings.json override the user config.yml [35.70ms]

::endgroup::

1 tests failed:
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.76ms]

 88 pass
 1 fail
 317 expect() calls
Ran 89 tests across 9 files. [902.00ms]

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

   Compiling pi-ast v0.11.10 (/home/runner/work/gajae-code/gajae-code/work/crates/pi-ast)
   Compiling icy_sixel v0.5.0
   Compiling grep-regex v0.1.14
    Finished `ci` profile [optimized + debuginfo] target(s) in 4m 27s
Normalizing native addon filename: pi_natives.linux-x64-gnu.node → pi_natives.linux-x64-modern.node
Generated 84 explicit ESM exports in index.js, fixed 9 const enums in index.d.ts
Build complete.
Generated 84 explicit ESM exports in index.js, fixed 0 const enums in index.d.ts
 * macOS computer-use controller.
Checked 21 files in 183ms. No fixes applied.
bun test v1.3.14 (0d9b296a)

::group::packages/natives/test/memory-guard-build-wiring.test.ts:
(pass) memory-guard native build wiring > rejects generated bindings that omit the Windows memory probe [0.16ms]
(pass) memory-guard native build wiring > rejects native addons that omit the Windows memory probe [0.21ms]

::endgroup::

::group::packages/natives/test/memory-guard-native.test.ts:
(pass) probeWindowsJobMemory > loads through the native loader and returns a tagged result [4.54ms]
(pass) probeWindowsJobMemory > rejects stale same-version bindings without the memory probe capability [0.07ms]

::endgroup::

::group::packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:
(pass) memory-guard native smoke fast path > matches only the exact internal argv [0.11ms]
(pass) memory-guard native smoke fast path > emits the tagged native receipt without normal command dispatch [0.31ms]
38 | 		expect(cliSource.indexOf("if (isMemoryGuardNativeSmokeFastPath(argv))")).toBeLessThan(
39 | 			cliSource.indexOf("await installRuntimeGlobals();"),
40 | 		);
41 | 
42 | 		const ciSource = await Bun.file(path.join(import.meta.dir, "../../..", ".github/workflows/ci.yml")).text();
43 | 		expect(ciSource).toContain("bun test packages/natives/test/memory-guard-native.test.ts");
                        ^
error: expect(received).toContain(expected)

Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"
Received: "name: CI\n\non:\n   push:\n      branches: [main]\n      tags: [\"v*\"]\n   pull_request:\n      branches: [main]\n   workflow_dispatch:\n      inputs:\n         rehearsal:\n            description: \"Rehearsal mode: run the exact tag build/verify graph (native -> binaries) with publish excluded, or the non-tag main graph.\"\n            required: true\n            type: choice\n            options: [tag-build-verify, main-nontag]\n\n# Least privilege by default: only `publish` needs write, and it declares its\n# own job-level `contents: write` override. This keeps rehearsal dispatches\n# (and every build/verify job) on a read-scoped GITHUB_TOKEN.\npermissions:\n   contents: read\n\nconcurrency:\n   # Release tags never cancel; ordinary CI is cancellable per ref.\n   group: ci-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.rehearsal || 'event' }}\n   cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }}\n\njobs:\n   # ---------------------------------------------------------------------------\n   # PR + main branch: lint/typecheck (native-free) and the test suite.\n   # These never run on tags — a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"

      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)

::error file=work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts,line=43,col=20,title=error: expect(received).toContain(expected)::Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"%0A a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"%0A%0A      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.82ms]

::endgroup::

::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.68ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.10ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.05ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.02ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.04ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.12ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.09ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.17ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.07ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.06ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.14ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.09ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.06ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.19ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.05ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.10ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.07ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.42ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.11ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.04ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.12ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.14ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.31ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.33ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.08ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.14ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.07ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.11ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.09ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:
(pass) resolveMemoryGuardPolicy > stays disabled by default and converts MB values to bytes [0.92ms]
(pass) resolveMemoryGuardPolicy > rounds fractional megabyte settings to integer bytes [0.34ms]
(pass) memory guard arbitration > does not let an unsupported host candidate mask an executable worker candidate [0.27ms]
(pass) memory guard arbitration > revalidates out when the selected target is no longer over allowance [0.19ms]
(pass) MemoryGuardHost > serializes action execution so only one run is in flight [1.20ms]
(pass) MemoryGuardHost > schedules based on earliest per-registration due time [0.60ms]
(pass) MemoryGuardHost > defers scheduling when a tick is in progress [0.29ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.12ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.04ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.03ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:
(pass) resource GC red-team safety invariants > keeps uncapped Windows Job commit charge separate from physical RAM [0.40ms]
(pass) resource GC red-team safety invariants > does not clamp a Windows commit-domain policy cap to physical RAM [0.24ms]
(pass) resource GC red-team safety invariants > never evicts ownerless tabs under RSS pressure and warns once [1.57ms]
(pass) resource GC red-team safety invariants > does not close a tab that flips in-flight between snapshot and eviction [0.72ms]
(pass) resource GC red-team safety invariants > does not double-release tabs eligible for both idle and RSS pressure [1.96ms]
(pass) resource GC red-team safety invariants > RSS oscillation re-warns exactly once per over-limit episode [0.44ms]
(pass) resource GC red-team safety invariants > disabled browser GC performs no eviction even when idle and over limit [0.40ms]
(pass) resource GC red-team safety invariants > does not evict a tab idle exactly at the configured threshold [0.33ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc.test.ts:
(pass) Linux cgroup memory sampling > fails over from an unreadable containing mount to a later compatible mount [4.25ms]
(pass) Linux cgroup memory sampling > compares pressure across every compatible containing mount [1.29ms]
(pass) Linux cgroup memory sampling > preserves distinct ancestor chains that resolve to the same leaf path [0.98ms]
(pass) Linux cgroup memory sampling > uses the namespace-relative fallback after containment candidates are exhausted [0.70ms]
(pass) Linux cgroup memory sampling > samples the mount root and selects the ancestor nearest to pressure [1.55ms]
(pass) Linux cgroup memory sampling > selects ancestor pressure against the configured policy cap [0.08ms]
(pass) Linux cgroup memory sampling > ignores zero and malformed counters while preserving valid unlimited usage [2.62ms]
(pass) resource GC controller > applies enabled memory policy to GC and sustained restart advisory telemetry [2.23ms]
(pass) resource GC controller > keeps positive fractional sweep intervals schedulable [0.41ms]
(pass) resource GC controller > uses aggregate domain usage and runs process-wide GC once for concurrent sessions [0.40ms]
(pass) resource GC controller > schedules an enabled guard at its configured check interval [57.49ms]
(pass) resource GC controller > idle sweep evicts idle tabs oldest-first and spares recent ones [0.52ms]
(pass) resource GC controller > forwards expired dead managed tabs to the authoritative supervisor recheck [0.36ms]
(pass) resource GC controller > skips tabs owned by no registered session [0.41ms]
(pass) resource GC controller > warns under RSS pressure when only a recovery-held dead tab remains [0.45ms]
(pass) resource GC controller > never evicts non-idle tabs under RSS pressure (IR-1) and warns once instead [0.40ms]
(pass) resource GC controller > evicts idle tabs LRU under pressure, then warns once if still over limit [0.57ms]
(pass) resource GC controller > warns exactly once per continuous no-evictable RSS-pressure episode [0.43ms]
(pass) resource GC controller > reference-counts the shared timer across sessions [0.25ms]
(pass) resource GC controller > does not run overlapping ticks [0.67ms]
(pass) resource GC controller > lazy-arms and throttles stale screenshot cleanup [0.54ms]
(pass) resource GC controller > resolves documented defaults from settings [0.14ms]
(pass) resource GC monotonic scheduler > A: rearms only for an earlier distinct registration [0.79ms]
(pass) resource GC monotonic scheduler > keeps unsupported duplicate session IDs from advancing the pending deadline [0.36ms]
(pass) resource GC monotonic scheduler > B: equal and later registrations preserve the existing timer [0.76ms]
(pass) resource GC monotonic scheduler > reschedules an active session after live memory-guard cadence changes [0.39ms]
(pass) resource GC monotonic scheduler > preserves an earlier shared deadline when another session changes cadence [0.47ms]
(pass) resource GC monotonic scheduler > C: unregistering the shortest session never postpones pending work [0.76ms]
(pass) resource GC monotonic scheduler > D: retains an expired deferred deadline from timer-owned blocked work [1.05ms]
(pass) resource GC monotonic scheduler > E: defers a consumed timer while externally initiated work owns the lock [0.74ms]
(pass) resource GC monotonic scheduler > F: preserves a short registration deadline during external work [0.62ms]
(pass) resource GC monotonic scheduler > G: fences stale completion after stop and re-registration [0.81ms]
(pass) resource GC monotonic scheduler > H: ignores a queued callback from a superseded same-generation timer [0.48ms]
(pass) resource GC monotonic scheduler > keeps scheduler time separate from eligibility time and resets all scheduler state [0.37ms]
(pass) resource GC settings precedence > lets project .gjc/settings.json override the user config.yml [39.21ms]

::endgroup::

1 tests failed:
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.82ms]

 88 pass
 1 fail
 317 expect() calls
Ran 89 tests across 9 files. [929.00ms]

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

   Compiling pi-ast v0.11.10 (/home/runner/work/gajae-code/gajae-code/work/crates/pi-ast)
   Compiling icy_sixel v0.5.0
   Compiling grep-regex v0.1.14
    Finished `ci` profile [optimized + debuginfo] target(s) in 4m 18s
Normalizing native addon filename: pi_natives.linux-x64-gnu.node → pi_natives.linux-x64-modern.node
Generated 84 explicit ESM exports in index.js, fixed 9 const enums in index.d.ts
Build complete.
Generated 84 explicit ESM exports in index.js, fixed 0 const enums in index.d.ts
 * macOS computer-use controller.
Checked 21 files in 182ms. No fixes applied.
bun test v1.3.14 (0d9b296a)

::group::packages/natives/test/memory-guard-build-wiring.test.ts:
(pass) memory-guard native build wiring > rejects generated bindings that omit the Windows memory probe [0.15ms]
(pass) memory-guard native build wiring > rejects native addons that omit the Windows memory probe [0.19ms]

::endgroup::

::group::packages/natives/test/memory-guard-native.test.ts:
(pass) probeWindowsJobMemory > loads through the native loader and returns a tagged result [4.15ms]
(pass) probeWindowsJobMemory > rejects stale same-version bindings without the memory probe capability [0.08ms]

::endgroup::

::group::packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:
(pass) memory-guard native smoke fast path > matches only the exact internal argv [0.09ms]
(pass) memory-guard native smoke fast path > emits the tagged native receipt without normal command dispatch [1.10ms]
38 | 		expect(cliSource.indexOf("if (isMemoryGuardNativeSmokeFastPath(argv))")).toBeLessThan(
39 | 			cliSource.indexOf("await installRuntimeGlobals();"),
40 | 		);
41 | 
42 | 		const ciSource = await Bun.file(path.join(import.meta.dir, "../../..", ".github/workflows/ci.yml")).text();
43 | 		expect(ciSource).toContain("bun test packages/natives/test/memory-guard-native.test.ts");
                        ^
error: expect(received).toContain(expected)

Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"
Received: "name: CI\n\non:\n   push:\n      branches: [main]\n      tags: [\"v*\"]\n   pull_request:\n      branches: [main]\n   workflow_dispatch:\n      inputs:\n         rehearsal:\n            description: \"Rehearsal mode: run the exact tag build/verify graph (native -> binaries) with publish excluded, or the non-tag main graph.\"\n            required: true\n            type: choice\n            options: [tag-build-verify, main-nontag]\n\n# Least privilege by default: only `publish` needs write, and it declares its\n# own job-level `contents: write` override. This keeps rehearsal dispatches\n# (and every build/verify job) on a read-scoped GITHUB_TOKEN.\npermissions:\n   contents: read\n\nconcurrency:\n   # Release tags never cancel; ordinary CI is cancellable per ref.\n   group: ci-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.rehearsal || 'event' }}\n   cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }}\n\njobs:\n   # ---------------------------------------------------------------------------\n   # PR + main branch: lint/typecheck (native-free) and the test suite.\n   # These never run on tags — a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"

      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)

::error file=work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts,line=43,col=20,title=error: expect(received).toContain(expected)::Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"%0A a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"%0A%0A      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.80ms]

::endgroup::

::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.71ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.07ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.03ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.01ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.02ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.08ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.09ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.13ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.09ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.07ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.12ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.10ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.08ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.20ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.05ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.12ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.08ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.40ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.16ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.04ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.11ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.08ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.34ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.42ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.07ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.07ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.07ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:
(pass) resolveMemoryGuardPolicy > stays disabled by default and converts MB values to bytes [0.85ms]
(pass) resolveMemoryGuardPolicy > rounds fractional megabyte settings to integer bytes [0.33ms]
(pass) memory guard arbitration > does not let an unsupported host candidate mask an executable worker candidate [0.20ms]
(pass) memory guard arbitration > revalidates out when the selected target is no longer over allowance [0.18ms]
(pass) MemoryGuardHost > serializes action execution so only one run is in flight [1.04ms]
(pass) MemoryGuardHost > schedules based on earliest per-registration due time [0.64ms]
(pass) MemoryGuardHost > defers scheduling when a tick is in progress [0.27ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.11ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.04ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.03ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:
(pass) resource GC red-team safety invariants > keeps uncapped Windows Job commit charge separate from physical RAM [0.39ms]
(pass) resource GC red-team safety invariants > does not clamp a Windows commit-domain policy cap to physical RAM [0.21ms]
(pass) resource GC red-team safety invariants > never evicts ownerless tabs under RSS pressure and warns once [1.27ms]
(pass) resource GC red-team safety invariants > does not close a tab that flips in-flight between snapshot and eviction [0.60ms]
(pass) resource GC red-team safety invariants > does not double-release tabs eligible for both idle and RSS pressure [1.84ms]
(pass) resource GC red-team safety invariants > RSS oscillation re-warns exactly once per over-limit episode [0.41ms]
(pass) resource GC red-team safety invariants > disabled browser GC performs no eviction even when idle and over limit [0.36ms]
(pass) resource GC red-team safety invariants > does not evict a tab idle exactly at the configured threshold [0.33ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc.test.ts:
(pass) Linux cgroup memory sampling > fails over from an unreadable containing mount to a later compatible mount [1.91ms]
(pass) Linux cgroup memory sampling > compares pressure across every compatible containing mount [1.15ms]
(pass) Linux cgroup memory sampling > preserves distinct ancestor chains that resolve to the same leaf path [1.07ms]
(pass) Linux cgroup memory sampling > uses the namespace-relative fallback after containment candidates are exhausted [0.76ms]
(pass) Linux cgroup memory sampling > samples the mount root and selects the ancestor nearest to pressure [2.20ms]
(pass) Linux cgroup memory sampling > selects ancestor pressure against the configured policy cap [0.08ms]
(pass) Linux cgroup memory sampling > ignores zero and malformed counters while preserving valid unlimited usage [2.71ms]
(pass) resource GC controller > applies enabled memory policy to GC and sustained restart advisory telemetry [1.87ms]
(pass) resource GC controller > keeps positive fractional sweep intervals schedulable [0.35ms]
(pass) resource GC controller > uses aggregate domain usage and runs process-wide GC once for concurrent sessions [0.49ms]
(pass) resource GC controller > schedules an enabled guard at its configured check interval [55.62ms]
(pass) resource GC controller > idle sweep evicts idle tabs oldest-first and spares recent ones [0.52ms]
(pass) resource GC controller > forwards expired dead managed tabs to the authoritative supervisor recheck [0.32ms]
(pass) resource GC controller > skips tabs owned by no registered session [0.36ms]
(pass) resource GC controller > warns under RSS pressure when only a recovery-held dead tab remains [0.47ms]
(pass) resource GC controller > never evicts non-idle tabs under RSS pressure (IR-1) and warns once instead [0.37ms]
(pass) resource GC controller > evicts idle tabs LRU under pressure, then warns once if still over limit [0.54ms]
(pass) resource GC controller > warns exactly once per continuous no-evictable RSS-pressure episode [0.41ms]
(pass) resource GC controller > reference-counts the shared timer across sessions [0.29ms]
(pass) resource GC controller > does not run overlapping ticks [0.61ms]
(pass) resource GC controller > lazy-arms and throttles stale screenshot cleanup [0.56ms]
(pass) resource GC controller > resolves documented defaults from settings [0.10ms]
(pass) resource GC monotonic scheduler > A: rearms only for an earlier distinct registration [0.55ms]
(pass) resource GC monotonic scheduler > keeps unsupported duplicate session IDs from advancing the pending deadline [0.39ms]
(pass) resource GC monotonic scheduler > B: equal and later registrations preserve the existing timer [0.58ms]
(pass) resource GC monotonic scheduler > reschedules an active session after live memory-guard cadence changes [0.32ms]
(pass) resource GC monotonic scheduler > preserves an earlier shared deadline when another session changes cadence [0.38ms]
(pass) resource GC monotonic scheduler > C: unregistering the shortest session never postpones pending work [0.54ms]
(pass) resource GC monotonic scheduler > D: retains an expired deferred deadline from timer-owned blocked work [0.92ms]
(pass) resource GC monotonic scheduler > E: defers a consumed timer while externally initiated work owns the lock [0.59ms]
(pass) resource GC monotonic scheduler > F: preserves a short registration deadline during external work [0.63ms]
(pass) resource GC monotonic scheduler > G: fences stale completion after stop and re-registration [0.72ms]
(pass) resource GC monotonic scheduler > H: ignores a queued callback from a superseded same-generation timer [0.45ms]
(pass) resource GC monotonic scheduler > keeps scheduler time separate from eligibility time and resets all scheduler state [0.38ms]
(pass) resource GC settings precedence > lets project .gjc/settings.json override the user config.yml [33.54ms]

::endgroup::

1 tests failed:
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.80ms]

 88 pass
 1 fail
 317 expect() calls
Ran 89 tests across 9 files. [860.00ms]

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

   Compiling pi-ast v0.11.10 (/home/runner/work/gajae-code/gajae-code/work/crates/pi-ast)
   Compiling icy_sixel v0.5.0
   Compiling grep-regex v0.1.14
    Finished `ci` profile [optimized + debuginfo] target(s) in 4m 17s
Normalizing native addon filename: pi_natives.linux-x64-gnu.node → pi_natives.linux-x64-modern.node
Generated 84 explicit ESM exports in index.js, fixed 9 const enums in index.d.ts
Build complete.
Generated 84 explicit ESM exports in index.js, fixed 0 const enums in index.d.ts
 * macOS computer-use controller.
Checked 21 files in 182ms. No fixes applied.
bun test v1.3.14 (0d9b296a)

::group::packages/natives/test/memory-guard-build-wiring.test.ts:
(pass) memory-guard native build wiring > rejects generated bindings that omit the Windows memory probe [0.16ms]
(pass) memory-guard native build wiring > rejects native addons that omit the Windows memory probe [0.15ms]

::endgroup::

::group::packages/natives/test/memory-guard-native.test.ts:
(pass) probeWindowsJobMemory > loads through the native loader and returns a tagged result [4.46ms]
(pass) probeWindowsJobMemory > rejects stale same-version bindings without the memory probe capability [0.09ms]

::endgroup::

::group::packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:
(pass) memory-guard native smoke fast path > matches only the exact internal argv [0.12ms]
(pass) memory-guard native smoke fast path > emits the tagged native receipt without normal command dispatch [1.16ms]
38 | 		expect(cliSource.indexOf("if (isMemoryGuardNativeSmokeFastPath(argv))")).toBeLessThan(
39 | 			cliSource.indexOf("await installRuntimeGlobals();"),
40 | 		);
41 | 
42 | 		const ciSource = await Bun.file(path.join(import.meta.dir, "../../..", ".github/workflows/ci.yml")).text();
43 | 		expect(ciSource).toContain("bun test packages/natives/test/memory-guard-native.test.ts");
                        ^
error: expect(received).toContain(expected)

Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"
Received: "name: CI\n\non:\n   push:\n      branches: [main]\n      tags: [\"v*\"]\n   pull_request:\n      branches: [main]\n   workflow_dispatch:\n      inputs:\n         rehearsal:\n            description: \"Rehearsal mode: run the exact tag build/verify graph (native -> binaries) with publish excluded, or the non-tag main graph.\"\n            required: true\n            type: choice\n            options: [tag-build-verify, main-nontag]\n\n# Least privilege by default: only `publish` needs write, and it declares its\n# own job-level `contents: write` override. This keeps rehearsal dispatches\n# (and every build/verify job) on a read-scoped GITHUB_TOKEN.\npermissions:\n   contents: read\n\nconcurrency:\n   # Release tags never cancel; ordinary CI is cancellable per ref.\n   group: ci-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.rehearsal || 'event' }}\n   cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }}\n\njobs:\n   # ---------------------------------------------------------------------------\n   # PR + main branch: lint/typecheck (native-free) and the test suite.\n   # These never run on tags — a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"

      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)

::error file=work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts,line=43,col=20,title=error: expect(received).toContain(expected)::Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"%0A a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"%0A%0A      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.71ms]

::endgroup::

::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.53ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.07ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.03ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.04ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.04ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.09ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.07ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.11ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.05ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.04ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.09ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.09ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.03ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.19ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.06ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.13ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.09ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.38ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.10ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.02ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.10ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.07ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.30ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.27ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.06ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.06ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.06ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:
(pass) resolveMemoryGuardPolicy > stays disabled by default and converts MB values to bytes [0.95ms]
(pass) resolveMemoryGuardPolicy > rounds fractional megabyte settings to integer bytes [0.39ms]
(pass) memory guard arbitration > does not let an unsupported host candidate mask an executable worker candidate [0.24ms]
(pass) memory guard arbitration > revalidates out when the selected target is no longer over allowance [0.20ms]
(pass) MemoryGuardHost > serializes action execution so only one run is in flight [1.26ms]
(pass) MemoryGuardHost > schedules based on earliest per-registration due time [0.68ms]
(pass) MemoryGuardHost > defers scheduling when a tick is in progress [0.36ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.11ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.05ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.05ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:
(pass) resource GC red-team safety invariants > keeps uncapped Windows Job commit charge separate from physical RAM [0.45ms]
(pass) resource GC red-team safety invariants > does not clamp a Windows commit-domain policy cap to physical RAM [0.21ms]
(pass) resource GC red-team safety invariants > never evicts ownerless tabs under RSS pressure and warns once [1.26ms]
(pass) resource GC red-team safety invariants > does not close a tab that flips in-flight between snapshot and eviction [0.66ms]
(pass) resource GC red-team safety invariants > does not double-release tabs eligible for both idle and RSS pressure [1.83ms]
(pass) resource GC red-team safety invariants > RSS oscillation re-warns exactly once per over-limit episode [0.42ms]
(pass) resource GC red-team safety invariants > disabled browser GC performs no eviction even when idle and over limit [0.40ms]
(pass) resource GC red-team safety invariants > does not evict a tab idle exactly at the configured threshold [0.32ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc.test.ts:
(pass) Linux cgroup memory sampling > fails over from an unreadable containing mount to a later compatible mount [1.95ms]
(pass) Linux cgroup memory sampling > compares pressure across every compatible containing mount [1.11ms]
(pass) Linux cgroup memory sampling > preserves distinct ancestor chains that resolve to the same leaf path [0.93ms]
(pass) Linux cgroup memory sampling > uses the namespace-relative fallback after containment candidates are exhausted [1.48ms]
(pass) Linux cgroup memory sampling > samples the mount root and selects the ancestor nearest to pressure [1.43ms]
(pass) Linux cgroup memory sampling > selects ancestor pressure against the configured policy cap [0.08ms]
(pass) Linux cgroup memory sampling > ignores zero and malformed counters while preserving valid unlimited usage [2.50ms]
(pass) resource GC controller > applies enabled memory policy to GC and sustained restart advisory telemetry [2.05ms]
(pass) resource GC controller > keeps positive fractional sweep intervals schedulable [0.39ms]
(pass) resource GC controller > uses aggregate domain usage and runs process-wide GC once for concurrent sessions [0.44ms]
(pass) resource GC controller > schedules an enabled guard at its configured check interval [57.04ms]
(pass) resource GC controller > idle sweep evicts idle tabs oldest-first and spares recent ones [0.49ms]
(pass) resource GC controller > forwards expired dead managed tabs to the authoritative supervisor recheck [0.29ms]
(pass) resource GC controller > skips tabs owned by no registered session [0.28ms]
(pass) resource GC controller > warns under RSS pressure when only a recovery-held dead tab remains [0.41ms]
(pass) resource GC controller > never evicts non-idle tabs under RSS pressure (IR-1) and warns once instead [0.43ms]
(pass) resource GC controller > evicts idle tabs LRU under pressure, then warns once if still over limit [0.54ms]
(pass) resource GC controller > warns exactly once per continuous no-evictable RSS-pressure episode [0.39ms]
(pass) resource GC controller > reference-counts the shared timer across sessions [0.16ms]
(pass) resource GC controller > does not run overlapping ticks [0.62ms]
(pass) resource GC controller > lazy-arms and throttles stale screenshot cleanup [0.52ms]
(pass) resource GC controller > resolves documented defaults from settings [0.13ms]
(pass) resource GC monotonic scheduler > A: rearms only for an earlier distinct registration [0.64ms]
(pass) resource GC monotonic scheduler > keeps unsupported duplicate session IDs from advancing the pending deadline [0.30ms]
(pass) resource GC monotonic scheduler > B: equal and later registrations preserve the existing timer [0.57ms]
(pass) resource GC monotonic scheduler > reschedules an active session after live memory-guard cadence changes [0.26ms]
(pass) resource GC monotonic scheduler > preserves an earlier shared deadline when another session changes cadence [0.38ms]
(pass) resource GC monotonic scheduler > C: unregistering the shortest session never postpones pending work [0.65ms]
(pass) resource GC monotonic scheduler > D: retains an expired deferred deadline from timer-owned blocked work [0.99ms]
(pass) resource GC monotonic scheduler > E: defers a consumed timer while externally initiated work owns the lock [0.64ms]
(pass) resource GC monotonic scheduler > F: preserves a short registration deadline during external work [0.54ms]
(pass) resource GC monotonic scheduler > G: fences stale completion after stop and re-registration [0.57ms]
(pass) resource GC monotonic scheduler > H: ignores a queued callback from a superseded same-generation timer [0.47ms]
(pass) resource GC monotonic scheduler > keeps scheduler time separate from eligibility time and resets all scheduler state [0.38ms]
(pass) resource GC settings precedence > lets project .gjc/settings.json override the user config.yml [37.85ms]

::endgroup::

1 tests failed:
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.71ms]

 88 pass
 1 fail
 317 expect() calls
Ran 89 tests across 9 files. [887.00ms]

@twoimo twoimo closed this Jul 25, 2026
@twoimo twoimo reopened this Jul 25, 2026
@github-actions

Copy link
Copy Markdown

SUCCESSOR_VERIFICATION_FAILED

branch=fix/memory-guard-domain-scheduler
outcome=failure
marker=(none)

   Compiling pi-ast v0.11.10 (/home/runner/work/gajae-code/gajae-code/work/crates/pi-ast)
   Compiling icy_sixel v0.5.0
   Compiling grep-regex v0.1.14
    Finished `ci` profile [optimized + debuginfo] target(s) in 4m 16s
Normalizing native addon filename: pi_natives.linux-x64-gnu.node → pi_natives.linux-x64-modern.node
Generated 84 explicit ESM exports in index.js, fixed 9 const enums in index.d.ts
Build complete.
Generated 84 explicit ESM exports in index.js, fixed 0 const enums in index.d.ts
 * macOS computer-use controller.
Checked 21 files in 180ms. No fixes applied.
bun test v1.3.14 (0d9b296a)

::group::packages/natives/test/memory-guard-build-wiring.test.ts:
(pass) memory-guard native build wiring > rejects generated bindings that omit the Windows memory probe [0.15ms]
(pass) memory-guard native build wiring > rejects native addons that omit the Windows memory probe [0.22ms]

::endgroup::

::group::packages/natives/test/memory-guard-native.test.ts:
(pass) probeWindowsJobMemory > loads through the native loader and returns a tagged result [4.15ms]
(pass) probeWindowsJobMemory > rejects stale same-version bindings without the memory probe capability [0.09ms]

::endgroup::

::group::packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:
(pass) memory-guard native smoke fast path > matches only the exact internal argv [0.09ms]
(pass) memory-guard native smoke fast path > emits the tagged native receipt without normal command dispatch [1.11ms]
38 | 		expect(cliSource.indexOf("if (isMemoryGuardNativeSmokeFastPath(argv))")).toBeLessThan(
39 | 			cliSource.indexOf("await installRuntimeGlobals();"),
40 | 		);
41 | 
42 | 		const ciSource = await Bun.file(path.join(import.meta.dir, "../../..", ".github/workflows/ci.yml")).text();
43 | 		expect(ciSource).toContain("bun test packages/natives/test/memory-guard-native.test.ts");
                        ^
error: expect(received).toContain(expected)

Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"
Received: "name: CI\n\non:\n   push:\n      branches: [main]\n      tags: [\"v*\"]\n   pull_request:\n      branches: [main]\n   workflow_dispatch:\n      inputs:\n         rehearsal:\n            description: \"Rehearsal mode: run the exact tag build/verify graph (native -> binaries) with publish excluded, or the non-tag main graph.\"\n            required: true\n            type: choice\n            options: [tag-build-verify, main-nontag]\n\n# Least privilege by default: only `publish` needs write, and it declares its\n# own job-level `contents: write` override. This keeps rehearsal dispatches\n# (and every build/verify job) on a read-scoped GITHUB_TOKEN.\npermissions:\n   contents: read\n\nconcurrency:\n   # Release tags never cancel; ordinary CI is cancellable per ref.\n   group: ci-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.rehearsal || 'event' }}\n   cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }}\n\njobs:\n   # ---------------------------------------------------------------------------\n   # PR + main branch: lint/typecheck (native-free) and the test suite.\n   # These never run on tags — a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"

      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)

::error file=work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts,line=43,col=20,title=error: expect(received).toContain(expected)::Expected to contain: "bun test packages/natives/test/memory-guard-native.test.ts"%0A a tag is cut from an already-green main.\n   # ---------------------------------------------------------------------------\n   check:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 20\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Lint and type check (native-free)\n           run: bun run ci:check:full\n\n   # ---------------------------------------------------------------------------\n   # PR + main branch: sharded full test suite. Unlike dev CI (changed-path\n   # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail\n   # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest\n   # partitions) so no single shard dominates wall-time. The `test` aggregate job\n   # keeps the stable branch-protection status name.\n   # ---------------------------------------------------------------------------\n   main_plan:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 10\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n      outputs:\n         matrix: ${{ steps.plan.outputs.matrix }}\n         has_tasks: ${{ steps.plan.outputs.has_tasks }}\n         has_native: ${{ steps.plan.outputs.has_native }}\n         has_python: ${{ steps.plan.outputs.has_python }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Compute full Main CI task matrix\n           id: plan\n           run: bun scripts/ci-dev-affected.ts --matrix-json\n\n   main_native:\n      if: ${{ !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_native == 'true' }}\n      needs: [main_plan]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Build native addon (linux-x64 baseline + modern)\n           env:\n              TARGET_PLATFORM: linux\n              TARGET_ARCH: x64\n              TARGET_VARIANTS: baseline modern\n           run: bun run ci:build:native\n         - name: Verify required native addon variants\n           run: |\n              test -f packages/natives/native/pi_natives.linux-x64-baseline.node\n              test -f packages/natives/native/pi_natives.linux-x64-modern.node\n         - name: Upload native addon(s)\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: |\n                 packages/natives/native/pi_natives.linux-x64-baseline.node\n                 packages/natives/native/pi_natives.linux-x64-modern.node\n              if-no-files-found: error\n              retention-days: 1\n              overwrite: true\n\n   main_python_matrix:\n      name: Python SDK / ${{ matrix.python-version }}\n      needs: [main_plan, main_native]\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_python == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      runs-on: ubuntu-22.04\n      timeout-minutes: 30\n      strategy:\n         fail-fast: false\n         matrix:\n            python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n      env:\n         GJC_REAL_SESSION_TESTS: \"1\"\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3\"\n         - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5\n           with:\n              python-version: ${{ matrix.python-version }}\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - run: bun install --frozen-lockfile\n         - run: bun run check:py-sdk\n         - run: bun run test:py-sdk\n         - run: bun run ci:test:py-sdk-build\n           if: ${{ matrix.python-version == '3.12' }}\n\n   main_shards:\n      name: test-shard / ${{ matrix.key }}\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }}\n      needs: [main_plan, main_native]\n      runs-on: ubuntu-22.04\n      timeout-minutes: ${{ matrix.rust && 90 || 60 }}\n      strategy:\n         fail-fast: false\n         max-parallel: 16\n         matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }}\n      env:\n         CI_FORCE_FULL: \"1\"\n         CI_CODING_AGENT_TEST_SHARDS: \"16\"\n         CI_RUST_TEST_PARTITIONS: \"4\"\n         AFFECTED_TASK_KEY: ${{ matrix.key }}\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2  # nightly\n           if: ${{ matrix.rust }}\n           with:\n              toolchain: nightly-2026-04-29\n         - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e  # v2\n           if: ${{ matrix.nextest }}\n           with:\n              tool: nextest@0.9.137\n         - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2\n           if: ${{ matrix.rust }}\n           with:\n              shared-key: main-rust-linux-x64\n              save-if: ${{ github.ref == 'refs/heads/main' }}\n              cache-workspace-crates: true\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           if: ${{ matrix.native }}\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              name: main-native-${{ github.run_id }}\n              path: packages/natives/native\n         - name: Run task shard\n           env:\n              GITHUB_ACTIONS: \"\"\n           run: bun scripts/ci-dev-affected.ts --task=\"$AFFECTED_TASK_KEY\"\n\n   # Branch protection must keep requiring this stable aggregate status.\n   test:\n      if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && (github.event_name != 'workflow_dispatch' || inputs.rehearsal == 'main-nontag') }}\n      needs: [main_plan, main_native, main_python_matrix, main_shards]\n      runs-on: ubuntu-22.04\n      timeout-minutes: 5\n      steps:\n         - name: Fail closed unless every shard succeeded\n           run: |\n              plan='${{ needs.main_plan.result }}'\n              native='${{ needs.main_native.result }}'\n              shards='${{ needs.main_shards.result }}'\n              python='${{ needs.main_python_matrix.result }}'\n              echo \"main_plan=$plan main_native=$native main_python_matrix=$python main_shards=$shards\"\n              test \"$plan\" = success\n              case \"$native\" in success|skipped) ;; *) echo \"native gate failed\"; exit 1;; esac\n              case \"$python\" in success|skipped) ;; *) echo \"Python gate failed\"; exit 1;; esac\n              test \"$shards\" = success\n\n   # ---------------------------------------------------------------------------\n   # Tag (vX.Y.Z) graph: build native addons for every published platform, then\n   # build the standalone binaries. The tag-only publish job then publishes to npm\n   # and cuts the GitHub Release; rehearsals stop after binary verification.\n   # ---------------------------------------------------------------------------\n   native:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      timeout-minutes: 90\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true }\n               - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern }\n               - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu }\n               - { os: macos-14, platform: darwin, arch: arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline }\n               - { os: windows-latest, platform: win32, arch: x64, variant: baseline }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: ./.github/actions/build-native\n           with:\n              hash: ${{ github.sha }}\n              platform: ${{ matrix.platform }}\n              arch: ${{ matrix.arch }}\n              variant: ${{ matrix.variant }}\n              target: ${{ matrix.target }}\n              rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }}\n              save_cache: \"true\"\n\n   binaries:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.rehearsal == 'tag-build-verify') }}\n      needs: [native]\n      timeout-minutes: 60\n      runs-on: ${{ matrix.os }}\n      strategy:\n         fail-fast: false\n         matrix:\n            include:\n               - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 }\n               - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 }\n               - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 }\n               - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 }\n               - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe }\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download native addon(s)\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Build release binary\n           env:\n              RELEASE_TARGETS: ${{ matrix.target_id }}\n           run: bun run ci:release:build-binaries\n         - name: Smoke release binary\n           if: runner.os != 'Windows'\n           run: |\n              runtime_dir=\"$(mktemp -d)\"\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --version\n              HOME=\"$runtime_dir/home\" XDG_DATA_HOME=\"$runtime_dir/xdg\" \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Smoke release binary (Windows)\n           if: runner.os == 'Windows'\n           shell: pwsh\n           run: |\n              $runtimeDir = Join-Path $env:TEMP (\"gjc-runtime-\" + [System.Guid]::NewGuid().ToString(\"N\"))\n              New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null\n              $env:HOME = Join-Path $runtimeDir \"home\"\n              $env:XDG_DATA_HOME = Join-Path $runtimeDir \"xdg\"\n              & \"${{ matrix.binary_path }}\" --version\n              & \"${{ matrix.binary_path }}\" --smoke-test\n         - name: Upload release binary artifact\n           uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4\n           with:\n              name: gjc-binary-${{ matrix.target_id }}\n              path: ${{ matrix.binary_path }}\n\n   publish:\n      if: ${{ startsWith(github.ref, 'refs/tags/v') && github.event_name != 'workflow_dispatch' }}\n      needs: [native, binaries]\n      timeout-minutes: 45\n      runs-on: ubuntu-22.04\n      permissions:\n         contents: write\n      steps:\n         - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4\n         - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v4\n           with:\n              node-version: \"24\"\n         - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6  # v2\n           with:\n              bun-version: \"1.3.14\"\n         - name: Cache bun dependencies\n           uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830  # v4\n           with:\n              path: ~/.bun/install/cache\n              key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}\n         - run: bun install --frozen-lockfile\n         - name: Download all native addons\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: pi-natives-*\n              path: packages/natives/native\n              merge-multiple: true\n         - name: Publish packages to npm\n           env:\n              NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n           shell: bash\n           run: |\n              set -euo pipefail\n              evidence_dir=\"$RUNNER_TEMP/release-evidence\"\n              mkdir -p \"$evidence_dir\"\n              bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir \"$evidence_dir\"\n              npm_config=\"$(mktemp \"$RUNNER_TEMP/npmrc.XXXXXX\")\"\n              trap 'rm -f \"$npm_config\"' EXIT\n              printf \"//registry.npmjs.org/:_authToken=%s\\n\" \"$NPM_TOKEN\" > \"$npm_config\"\n              NPM_CONFIG_USERCONFIG=\"$npm_config\" NODE_AUTH_TOKEN=\"$NPM_TOKEN\" \\\n                 bun scripts/ci-release-publish.ts --publish-from-evidence \\\n                    --evidence-dir \"$evidence_dir\" \\\n                    --release-serialization-key gajae-production-release\n         - name: Download release binaries\n           uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093  # v4\n           with:\n              pattern: gjc-binary-*\n              path: release-binaries\n              merge-multiple: true\n         - name: Create GitHub Release\n           uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65  # v2\n           with:\n              tag_name: ${{ github.ref_name }}\n              draft: false\n              prerelease: false\n              generate_release_notes: true\n              files: release-binaries/gjc-*\n"%0A%0A      at <anonymous> (/home/runner/work/gajae-code/gajae-code/work/packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts:43:20)
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.70ms]

::endgroup::

::group::packages/coding-agent/test/gjc-runtime/linux-proc.test.ts:
(pass) parseLinuxProcStartTime > parses field 22 from a valid stat string [0.69ms]
(pass) parseLinuxProcStartTime > anchors on the last closing paren when comm contains parens and spaces [0.06ms]
(pass) parseLinuxProcStartTime > returns null for null and undefined input [0.03ms]
(pass) parseLinuxProcStartTime > returns null for empty string input [0.02ms]
(pass) parseLinuxProcStartTime > returns null when the closing paren is missing [0.02ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is absent (too few trailing fields) [0.08ms]
(pass) parseLinuxProcStartTime > returns null when field 22 is non-numeric [0.08ms]
(pass) parseLinuxProcStartTime > rejects malformed record boundaries and fields [0.14ms]
(pass) parseLinuxProcStartTime > accepts a single terminal newline and fields after field 22 [0.07ms]
(pass) parseLinuxProcStartTime > parses a large numeric start time [0.07ms]
(pass) parseLinuxProcStartTime > accepts every single-letter Linux process state code [0.12ms]
(pass) parseLinuxProcTtyDevice > parses field 7 from a valid stat string [0.08ms]
(pass) probeLinuxProcPidSync > returns an explicit unsupported result on non-Linux platforms [0.04ms]
(pass) probeLinuxProcPidSync > returns a live identity for the current PID on Linux [0.20ms]
(pass) probeLinuxProcPidSync > returns an explicit invalid-pid result [0.13ms]
(pass) probeLinuxProcPidSync > returns absent for a PID whose /proc entry cannot be read [0.13ms]
(pass) probeLinuxProcPid > returns an explicit unsupported result on non-Linux platforms [0.12ms]
(pass) probeLinuxProcPid > returns a live identity for the current PID on Linux [0.39ms]
(pass) probeLinuxProcPid > returns an explicit invalid-pid result [0.10ms]
(pass) readLinuxProcStartTimeSync > returns null on non-Linux platforms [0.03ms]
(pass) readLinuxProcStartTimeSync > returns a non-null numeric start time for the current PID on Linux [0.11ms]
(pass) readLinuxProcStartTime > returns null on non-Linux platforms [0.08ms]
(pass) readLinuxProcStartTime > returns a non-null numeric start time for the current PID on Linux [0.33ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-domain.test.ts:
(pass) computeMemoryGuardDomain > matches the R=0 fixture [0.36ms]
(pass) computeMemoryGuardDomain > matches the R<P fixture [0.07ms]
(pass) computeMemoryGuardDomain > matches the R>P fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the worker-overage fixture [0.05ms]
(pass) computeMemoryGuardDomain > matches the unmanaged-pressure no-op fixture [0.10ms]
(pass) computeMemoryGuardDomain > counts rejected worker bytes as unmanaged pressure [0.08ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-guard.test.ts:
(pass) resolveMemoryGuardPolicy > stays disabled by default and converts MB values to bytes [0.81ms]
(pass) resolveMemoryGuardPolicy > rounds fractional megabyte settings to integer bytes [0.35ms]
(pass) memory guard arbitration > does not let an unsupported host candidate mask an executable worker candidate [0.19ms]
(pass) memory guard arbitration > revalidates out when the selected target is no longer over allowance [0.17ms]
(pass) MemoryGuardHost > serializes action execution so only one run is in flight [1.07ms]
(pass) MemoryGuardHost > schedules based on earliest per-registration due time [0.70ms]
(pass) MemoryGuardHost > defers scheduling when a tick is in progress [0.29ms]

::endgroup::

::group::packages/coding-agent/test/runtime/memory-limit.test.ts:
(pass) resolveEffectiveMemoryLimit > caps the manual policy limit at the authoritative hard cap [0.10ms]
(pass) resolveEffectiveMemoryLimit > accepts a policy limit when no hard cap is available [0.04ms]
(pass) resolveEffectiveMemoryLimit > drops invalid limits instead of fabricating an effective cap [0.03ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc-redteam.test.ts:
(pass) resource GC red-team safety invariants > keeps uncapped Windows Job commit charge separate from physical RAM [0.45ms]
(pass) resource GC red-team safety invariants > does not clamp a Windows commit-domain policy cap to physical RAM [0.21ms]
(pass) resource GC red-team safety invariants > never evicts ownerless tabs under RSS pressure and warns once [1.24ms]
(pass) resource GC red-team safety invariants > does not close a tab that flips in-flight between snapshot and eviction [0.67ms]
(pass) resource GC red-team safety invariants > does not double-release tabs eligible for both idle and RSS pressure [1.88ms]
(pass) resource GC red-team safety invariants > RSS oscillation re-warns exactly once per over-limit episode [0.42ms]
(pass) resource GC red-team safety invariants > disabled browser GC performs no eviction even when idle and over limit [0.38ms]
(pass) resource GC red-team safety invariants > does not evict a tab idle exactly at the configured threshold [0.33ms]

::endgroup::

::group::packages/coding-agent/test/tools/resource-gc.test.ts:
(pass) Linux cgroup memory sampling > fails over from an unreadable containing mount to a later compatible mount [1.92ms]
(pass) Linux cgroup memory sampling > compares pressure across every compatible containing mount [1.09ms]
(pass) Linux cgroup memory sampling > preserves distinct ancestor chains that resolve to the same leaf path [1.01ms]
(pass) Linux cgroup memory sampling > uses the namespace-relative fallback after containment candidates are exhausted [0.71ms]
(pass) Linux cgroup memory sampling > samples the mount root and selects the ancestor nearest to pressure [2.25ms]
(pass) Linux cgroup memory sampling > selects ancestor pressure against the configured policy cap [0.08ms]
(pass) Linux cgroup memory sampling > ignores zero and malformed counters while preserving valid unlimited usage [2.59ms]
(pass) resource GC controller > applies enabled memory policy to GC and sustained restart advisory telemetry [1.83ms]
(pass) resource GC controller > keeps positive fractional sweep intervals schedulable [0.32ms]
(pass) resource GC controller > uses aggregate domain usage and runs process-wide GC once for concurrent sessions [0.43ms]
(pass) resource GC controller > schedules an enabled guard at its configured check interval [54.77ms]
(pass) resource GC controller > idle sweep evicts idle tabs oldest-first and spares recent ones [0.47ms]
(pass) resource GC controller > forwards expired dead managed tabs to the authoritative supervisor recheck [0.32ms]
(pass) resource GC controller > skips tabs owned by no registered session [0.35ms]
(pass) resource GC controller > warns under RSS pressure when only a recovery-held dead tab remains [0.43ms]
(pass) resource GC controller > never evicts non-idle tabs under RSS pressure (IR-1) and warns once instead [0.36ms]
(pass) resource GC controller > evicts idle tabs LRU under pressure, then warns once if still over limit [0.53ms]
(pass) resource GC controller > warns exactly once per continuous no-evictable RSS-pressure episode [0.37ms]
(pass) resource GC controller > reference-counts the shared timer across sessions [0.26ms]
(pass) resource GC controller > does not run overlapping ticks [0.55ms]
(pass) resource GC controller > lazy-arms and throttles stale screenshot cleanup [0.54ms]
(pass) resource GC controller > resolves documented defaults from settings [0.12ms]
(pass) resource GC monotonic scheduler > A: rearms only for an earlier distinct registration [0.67ms]
(pass) resource GC monotonic scheduler > keeps unsupported duplicate session IDs from advancing the pending deadline [0.31ms]
(pass) resource GC monotonic scheduler > B: equal and later registrations preserve the existing timer [0.54ms]
(pass) resource GC monotonic scheduler > reschedules an active session after live memory-guard cadence changes [0.31ms]
(pass) resource GC monotonic scheduler > preserves an earlier shared deadline when another session changes cadence [0.43ms]
(pass) resource GC monotonic scheduler > C: unregistering the shortest session never postpones pending work [0.60ms]
(pass) resource GC monotonic scheduler > D: retains an expired deferred deadline from timer-owned blocked work [1.10ms]
(pass) resource GC monotonic scheduler > E: defers a consumed timer while externally initiated work owns the lock [0.69ms]
(pass) resource GC monotonic scheduler > F: preserves a short registration deadline during external work [0.58ms]
(pass) resource GC monotonic scheduler > G: fences stale completion after stop and re-registration [0.65ms]
(pass) resource GC monotonic scheduler > H: ignores a queued callback from a superseded same-generation timer [0.38ms]
(pass) resource GC monotonic scheduler > keeps scheduler time separate from eligibility time and resets all scheduler state [0.35ms]
(pass) resource GC settings precedence > lets project .gjc/settings.json override the user config.yml [35.21ms]

::endgroup::

1 tests failed:
(fail) memory-guard native smoke fast path > keeps the fast path ahead of runtime initialization and the Windows CI smoke after release build [0.70ms]

 88 pass
 1 fail
 317 expect() calls
Ran 89 tests across 9 files. [851.00ms]

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants