* test: run the unit suite without --isolate (TA-001 round 2)
* test: clean up leaks exposed by running without --isolate (TA-001 round 2)
* test: clean up remaining leaks in shared-process runs (TA-001 round 2)
* test: reset query engine trace state before each test (TA-001 round 2)
* test: isolate env, process and global state leaks across randomized seeds (TA-001 round 2 batch 2)
* test: keep batch 2 state isolation from leaking into later files (TA-001 round 2 batch 2)
Drop the standalone processExitCode helper self-test. Adding a discovered test file changed native shard assignments and seeded file order, exposing existing cross-file mock contamination. The existing finalizer and skills integration tests retain exit-code assertions and continue to exercise the helper.
* test: consolidate vendor catalog tests into per-vendor contract tables
* test: assert full descriptor limits and capabilities for nearai, longcat and xai
* fix: synchronize agent completion with output eviction
Agent task completion could become externally observable before the
output eviction and flush sequence completed, resulting in callers
observing empty output files.
Root Cause
----------
completeAgentTask() returned immediately while evictTaskOutput()
continued asynchronously. Callers could observe task completion
before the eviction/flush chain finished.
Fix
---
- Make completeAgentTask() async and await eviction
- Await completeAsyncAgent() at both call sites
- Clarify ORC-1337 vs gh-20236 in comments
Testing
-------
- AgentTool: 59/59 passing
- LocalAgentTask: 6/6 passing
Refs: ORC-1337, gh-20236
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: move output barrier before terminal state transition
Review follow-up for ORC-1337 addressing both P1 findings:
1. Ordering: updateTaskState('completed') ran before the eviction
await, so TaskOutput(block=true) readers released by the terminal
status could still read a flushing file. The durable-output barrier
now precedes the state transition.
2. Sidechain transcript: local-agent output is a symlink to the agent
transcript written by the session-storage queue
(recordSidechainTranscript) — no DiskTaskOutput entry exists, so
evictTaskOutput alone resolved without waiting. completeAgentTask
now awaits flushSessionStorage() (drains the queue and in-flight
tracked chains) before evictTaskOutput and the status flip.
Also per review:
- Remove ORC-1337-FIX.md from the PR (P3)
- Add deterministic regression test gating both barriers
(completionBarrier.test.ts) — verified to fail on the previous
ordering
- Update call-site comments to describe the corrected sequence
Testing: AgentTool + LocalAgentTask 67/67 (incl. 2 new); tsc clean.
Refs: ORC-1337, gh-20236
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix(agent): await scoped output writes before completion
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: cancel agent transcript waits without delaying cleanup
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: preserve agent output ownership across session changes
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: await agent output link replacement after clear
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: preserve agent output destination and finishing input admission
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix(agent): preserve output destinations for background and resumed sessions
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix: preserve agent output ownership across replacement and clear
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* fix(agent): bind retained output links to the recording producer
Record successful sidechain append destinations by agent ID and require
retained output links to match that producer record. Preserve the record
across session clears and project overrides for retained resumes.
Cover swapped agent and project targets for captured and live writes.
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
---------
Co-authored-by: jatmn <jatmn@users.noreply.github.com>
Co-authored-by: Zolow-kuni <285616838+Zolow-kuni@users.noreply.github.com>
* ci: run unit test shards in parallel
* fix(ci): address shard-selection review feedback
* ci: cache package downloads in the shard and dedicated test jobs
* ci: cache package downloads in PR checks
* ci: cache package downloads in the suite job
* ci: fix suite cache key and separate root and web cache prefixes
Resolves CodeQL js/insufficient-password-hash (alert 70):
aimlapiByKeyIdentity fed the API key into a plain SHA-256.
AI/ML API by-key top-ups (src/integrations/aimlapi, ProviderManager)
- The identity is now `key:v2:` + HMAC-SHA256 keyed BY the credential over
a fixed label, so the key is never the hashed input. It stays cheap on
the interactive path (no KDF stalling Ink before the async lock), and a
known-answer test pins the value so the derivation cannot drift silently.
- Receipts written by earlier versions carry `key:<sha256>`. That value is
deliberately never recomputed, so they are handled without hashing:
- one that stores this credential (a settled saved-key top-up waiting on
its profile write, which a claim otherwise refuses to replace even with
abandonExisting) is matched by its stored key and upgraded under the
lock, in both reconcileSettledAimlapiTopupStateAsync and the by-key
claim (new `byKeyApiKey` claim option, passed by ProviderManager);
- one with no stored key (an in-flight by-key checkout, or a settled
env-key top-up) cannot be attributed and holds nothing unrecoverable,
since a by-key payment is credited to its key server-side, so the next
claim may replace it instead of refusing a re-run that can never match.
Both are skipped while a mint/exchange lease on the record is live.
Skills watcher test (src/utils/skills)
- `disabled sibling edits stop triggering hooks…` flaked on loaded CI
runners ("Expected number of calls: 1, Received: 2"). Its edit helper
retries writes every 50ms until a hook fires, and a retry already in
flight could land one more hook after the exact-count assertion or after
the sibling watcher closed. Assert that each phase's edit was observed,
wait until hooks are quiet between phases, and give the real-filesystem
test a 15s budget. Under 12 saturated cores: original 2/15 failures,
fixed 45/45 passes.
Co-authored-by: OpenClaude <openclaude@gitlawb.com>
CodeQL default setup flagged js/insecure-randomness (alert #72, high)
on the custom-pricing budget fixture, which built message uuids from
Math.random(). The values never leave the test process, but the field
is typed as UUID and the same pattern appeared in three places across
two fixtures.
Generate the uuids with crypto.randomUUID() instead. This clears the
alert, matches the Message uuid type, and drops the
`as Message['uuid']` cast in the manual-compact cooldown fixture.
Nothing depended on the old user-/assistant-/test- prefixes.
Co-authored-by: OpenClaude <openclaude@gitlawb.com>