Skip to content

feat(ai): add gemini-3.7-flash with thinking level mapping and update google defaults - #1452

Closed
Kenmege wants to merge 47 commits into
PrimeIntellect-ai:mainfrom
Kenmege:feat/gemini-3.7-flash
Closed

feat(ai): add gemini-3.7-flash with thinking level mapping and update google defaults#1452
Kenmege wants to merge 47 commits into
PrimeIntellect-ai:mainfrom
Kenmege:feat/gemini-3.7-flash

Conversation

@Kenmege

@Kenmege Kenmege commented Aug 16, 2026

Copy link
Copy Markdown

Summary

Adds full support for gemini-3.7-flash with thinking/reasoning effort mapping across Google Generative AI and Google Vertex AI providers, and sets gemini-3.7-flash as the default model for both providers.

Key Changes

  1. packages/ai/scripts/generate-models.ts:

    • Mapped thinkingLevelMap for Gemini 3.x Flash models (gemini-3.7-flash, gemini-3.6-flash, gemini-3.5-flash, etc.) to include {"off": null, "minimal": "MINIMAL", "low": "LOW", "medium": "MEDIUM", "high": "HIGH"}.
    • Registered gemini-3.7-flash under google-vertex provider and added fallback generator registration for google.
  2. packages/coding-agent/src/core/model-resolver.ts:

    • Updated defaultModelPerProvider for google and google-vertex to gemini-3.7-flash.
  3. packages/ai/test/google-gemini-37-flash.test.ts:

    • Added unit tests verifying gemini-3.7-flash registration, reasoning capabilities, and thinking level clamping on google and google-vertex.
  4. Changelogs:

    • Documented additions in packages/ai/CHANGELOG.md and packages/coding-agent/CHANGELOG.md.

Verification

  • npm run check passes 100% cleanly.
  • packages/ai/test/google-gemini-37-flash.test.ts unit tests pass.
  • Generated models.generated.ts verified for accurate model metadata.

Note

Add gemini-3.7-flash with thinking level mapping and update Google provider defaults

  • Adds gemini-3.7-flash to both google and google-vertex providers in generate-models.ts with reasoning enabled and a full thinkingLevelMap (minimal/low/medium/high); updates defaultModelPerProvider in model-resolver.ts from gemini-3.1-pro-preview to gemini-3.7-flash.
  • Extends applyThinkingLevelMetadata to emit explicit MINIMAL/LOW/MEDIUM/HIGH thinking level constants in the generated catalog.
  • Adds a repetition guard for OpenAI-compatible streaming that aborts degenerate reasoning loops with a classified StreamFailureError of kind degenerate_output.
  • Refreshes the generated model catalog (models.generated.ts) with additions across many providers and removal of older Anthropic entries.
  • Risk: existing sessions targeting Google providers will now default to gemini-3.7-flash instead of gemini-3.1-pro-preview, which may change response quality and cost.

Macroscope summarized 8978a50.

Dr Kennedy Umege and others added 30 commits August 10, 2026 08:32
cleanupResources killed the kernel and removed its temp directory in the same
synchronous pass, so dispose() resolved while the child was still exiting. The
kernel is spawned with cwd set to that directory; Windows keeps it locked until
the process is really gone, so a caller deleting it after an awaited dispose()
got EPERM.

The defect is not Windows-specific. Nothing ever waited for "exit", so the
promise resolved early everywhere; Unix only hides it by unlinking files that
are still open.

dispose() now defers temp-dir removal, waits for the process to actually exit,
then removes the directory. Direct children are awaited on their "exit" event;
a forked kernel is not a direct child and emits no "exit", so its pid is polled
the same way forkedKernelDied checks liveness. Both paths are bounded by
KERNEL_EXIT_TIMEOUT_MS so a wedged kernel cannot hang disposal.

Removal retries explicitly. rmSync's own maxRetries does not cover this case:
the native implementation surfaces the directory-level EPERM without retrying.

disposeSync is unchanged. It runs from process.on("exit") where nothing async
can be awaited, so it keeps the previous best-effort synchronous removal.

fixes PrimeIntellect-ai#1049
…nd keep one failed worker from failing global heartbeats_list

Two defects combined to make a single stale descriptor break every global
heartbeat listing with "Cannot list heartbeats while session worker is failed"
(PrimeIntellect-ai#1045):

- stopWorker trusted kill(pid, 0) (EPERM included) as proof the worker was
  still running and never checked the descriptor's recorded processStartId,
  unlike the recovery path. After a worker exited, a pid-reusing (or
  EPERM-answering) unrelated process made the stop path signal the imposter's
  process group, wait out both deadlines, and persist lifecycle "failed" with
  "did not stop after SIGKILL" -- across supervisor restarts.
- The global heartbeats_list fan-out included failed workers (isVisibleWorker
  only excludes client-owned ones) and returned the first failure snapshot as
  the whole command's result, so one zombie descriptor poisoned the entire
  listing while session-scoped listings kept working.

stopWorker now verifies the pid's process start id against the descriptor
before signalling or waiting on it, treating an identity mismatch as an
already-stopped worker, and heartbeats_list skips failed workers, which
cannot host firing heartbeats.

Closes PrimeIntellect-ai#1045
…ntity at each stop-path signal

Address both review findings on the initial identity fix: the tombstoned
descriptor adoption path in adoptOrRecoverWorker sent an unconditional
SIGKILL to the descriptor's pid before stopWorker ran, so a recycled pid
could still be signalled during supervisor restart -- the exact incident
path. It now checks workerDescriptorProcessIdentityMatches first.

stopWorker also no longer caches the identity verdict in a boolean computed
before the shutdown request: the worker can exit during the graceful wait
and its pid be reassigned, in which case the cached "verified" flag would
have followed the replacement process into SIGKILL. isWorkerProcessAlive now
re-reads the process start id on every liveness check, immediately before
each signal, narrowing the check-to-signal race to the kill(2) call itself.

The stop-identity regression test now also covers the adoption path with a
tombstoned descriptor and asserts the bystander process survives and the
worker does not end up lifecycle "failed".
… to suite/regressions

Move the process identity and heartbeat aggregation regression tests
to the prescribed location under test/suite/regressions/ with the
required <issue-number>-<slug>.test.ts naming convention.

This consolidates all PrimeIntellect-ai#1045 regressions into a single file:
- stopWorker identity verification for recycled pids
- adoptOrRecoverWorker pre-kill identity guard
- heartbeats_list skipping of failed workers
Tests moved to test/suite/regressions/1045-failed-worker-poison.test.ts
Test moved to test/suite/regressions/1045-failed-worker-poison.test.ts
…able

When a descriptor has a recorded processStartId but getProcessStartId()
returns undefined (e.g., /proc unavailable, ps failures), we now refuse
to signal rather than assuming the pid belongs to our worker.

This prevents accidentally signalling an unrelated process when the
identity verification system itself cannot function. Old workers without
processStartId remain trusted for backward compatibility.

The three conditions in workerDescriptorProcessIdentityMatches now:
1. No recorded ID → trust (backward compat with old descriptors)
2. Process dead → harmless to proceed (signal will fail with ESRCH)
3. Have recorded ID but can't observe → REFUSE (can't verify = don't signal)
4. IDs match → signal
5. IDs don't match → don't signal
Split process identity checks into two functions with different semantics:

1. workerDescriptorProcessIdentityMatches() - for signaling decisions
   Returns true only for verified 'match', false for 'mismatch' or
   'unverifiable'. Used before SIGTERM/SIGKILL to avoid signalling
   wrong processes.

2. workerDescriptorProcessMightBeAlive() - for cleanup decisions
   Returns true for 'match' or 'unverifiable', false only for verified
   'mismatch'. Used in wait loops and final liveness check to avoid
   deleting descriptors of possibly-live workers.

This fixes the issue where returning false for unverifiable identity
caused stopWorker to skip the wait loop and delete the worker as though
it had exited, leaving live workers untracked.

The underlying workerDescriptorProcessIdentityCheck() returns a tri-state:
- 'match': verified, process is ours
- 'mismatch': verified, process is NOT ours (recycled pid)
- 'unverifiable': can't check (old descriptor or platform limitation)
…rendering

The portable start-time listing (ps -o lstart=) renders local time, so
the same live worker produced a different identity when the supervisor
restarted under a different TZ or locale - the mismatch was read as
PID reuse, adoption skipped signalling, and the descriptor of a live
worker was deleted, leaving it untracked.

The process query now pins TZ=UTC and LC_ALL=C, and the token format
is versioned (ps2:) so a legacy ps: token recorded by an older build
degrades to the unverifiable tri-state instead of a false mismatch:
the worker stays tracked and unsignalled until same-format evidence
exists. Same-format inequality remains a trusted mismatch. Red-green
verified: without the cross-format degradation, the legacy-token test
observes the live worker's descriptor being reaped.
Expose pause and resume through the goal host bridge and Python skill so
an agent can yield without completing its objective while external input
is pending.

Reuse the persisted paused state, clear queued goal contexts, and teach
the continuation prompt to pause instead of emitting holding turns.

Signed-off-by: Christian Stewart <christian@aperture.us>
A thinking stream settled into emitting "The the the the the the the " back to
back 2,366 times, 79,222 characters, and stopped only when the user aborted by
hand. No layer owned this: provider streamers are faithful assemblers and never
inspect content, request construction attaches no repetition penalties, and the
agent loop treats a completed stream as progress. A runaway response could burn
the whole 32k output cap.

Adds a stream-level guard on the reasoning channel of openai-completions. Two
detectors:

- Periodic tail. The tail is one short unit repeated many times, found with the
  KMP failure function, which gives the smallest period in O(n) with no scan
  over candidate lengths.
- Novelty stall. Distinct word trigrams over total, for loops that drift enough
  that verbatim periodicity misses them.

The novelty floor is calibrated rather than guessed. Measured over the corpus in
the tests:

    loops   verbatim 0.001   drifting 0.136
    legit   enumerated analysis 0.286   markdown table 0.485   JSON 0.513
            source code 0.611   numbered list 0.671   prose 1.000

0.20 sits in that gap. Word-trigram Jaccard between paragraphs was tried first
and rejected: drifting loops scored 0.38-0.58 and structurally similar
legitimate paragraphs scored in the same band, so no threshold separated them.

False positives are the real risk, since a wrong abort destroys real work, so
the tests assert that code, markdown tables, numbered lists, JSON, prose and
enumerated analysis do not trip it. The text channel is deliberately left
unguarded: a long legitimate answer can contain generated tables or code.

On a hit the stream fails with a new degenerate_output failure kind rather than
committing the garbage. Kill switch: PRIME_AGENT_NO_REPETITION_GUARD=1.

Also wires recordStreamFailure into the openai-completions terminal catch.
Every other provider already called it; this one did not, so failures on the
most widely used path (OpenRouter, llama.cpp, any OpenAI-compatible endpoint)
reached the session with no classification at all. The new kind depends on it,
but this fixes classification for every existing kind on that provider too.

fixes PrimeIntellect-ai#1029
…tensions

Completes workstream 8 of the elite reliability plan: phase calibration,
the human-extension lease lane, and their monitor/CLI surface.

- operation-calibration: group terminal operations by kind and timeout class,
  report p50/p95/p99 and an advisory hard cap, and gate hard enforcement on
  minimum canary samples with zero uncertain outcomes or uncertain cleanups.
  The verdict stays telemetry_insufficient until that bar is met, so advisory
  caps never silently become enforcement.
- operation-extension-inbox: append-only, restart-safe request/receipt records
  for capped human deadline extensions.
- daemon sweeps the inbox and applies extensions through the ledger; the
  reliability monitor settles requests whose operation is no longer open.
- pi monitor gains --calibration and --extend <id> --minutes <1-60>.

The inbox creates its directory on first write rather than in its constructor.
Building it eagerly in the AgentDaemon constructor made an unusable reliability
directory fatal to daemon construction, which regressed the snapshot-cache
replacement fallback. Both sweep call sites now degrade instead of throwing, so
a broken extension lane can never stop the deadline watchdog.

Verification: literal root `npm run check` passes; operation-ledger,
operation-calibration, operation-extension-inbox, reliability-monitor and
daemon-mode suites pass 205/205. The full coding-agent suite's only failures
are three model-catalog regressions that also fail on a pristine tree at
059a842 and are unrelated to this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuxixGsgf1bVvxrpWJn7zB
…r saw finish

Remediates defects found by independent adversarial review of the mission branch.
Each fix has a regression test that fails against the previous commit.

- closeAll can no longer promote a still-open operation to `completed`. A tool whose
  end event never arrived was being recorded as a clean success whenever its session
  closed with reason "completed", and those fabricated records then fed calibration as
  evidence of reliability. Survivors now terminalize as `uncertain`; `completed` is
  reachable only through the operation's own end event.

- Calibration eligibility no longer opens by forgetting. Terminal records are trimmed to
  a bounded window, so `uncertainOutcomeCount === 0` returned to true once an uncertain
  record aged out, certifying the class canary-ready on the strength of evidence that had
  been discarded. Eligibility now reads monotonic per-group lifetime counters that
  trimming cannot touch, expressed as an uncertainty rate. Percentiles stay windowed,
  since recent latency is what an advisory cap should track.

- A human deadline extension applies at most once. The sweep applied the extension and
  then wrote the receipt; if the receipt write failed the request stayed pending and
  re-applied on every tick, consuming the whole renewal cap. Requests are now durably
  claimed before they are applied, so an unwritable inbox grants zero extensions.

- The monitor's liveness rule agrees with the ledger's. It compared start ids with `===`,
  so a legacy `ps:` token read against the current `ps2:` rendering counted as a mismatch
  and declared a live daemon missing. It now uses compareProcessStartIds, where an
  unverifiable comparison is not a mismatch, matching operation-ledger.ts. A missing
  process is also reported alongside the snapshot's other alerts rather than replacing
  them, so one liveness misjudgement can no longer discard every real deadline alert.

- The notification outbox survives concurrent writers. It rewrote the whole file from
  constructor-time state, so an alert already on disk could be erased by an `--ack` from
  another process. Writes now re-read and merge per record.

Verification: literal root `npm run check` passes. Focused daemon/reliability suites 6
files, 213 tests, all passing. Full package suite 4091 passed with 3 failures, which are
the model-catalog tests that also fail at the untouched base a18809e.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuxixGsgf1bVvxrpWJn7zB
…ldown

Split out of the elite reliability branch so the lockfile churn can be reviewed on
its own rather than mixed into daemon work.

Adds overrides for three transitive dependencies carrying advisories that reach the
runtime dependency tree, and moves undici to ^7.29.0 in both packages that depend on it.
Production `npm audit --omit=dev` drops from four high plus one moderate to the single
moderate self-package advisory, which is CVE-2026-54325 and is tracked separately.

ip-address is pinned to 10.4.0, not the current 10.5.0. This repository sets
`min-release-age=7` in .npmrc — a deliberate supply-chain cooldown that refuses to
resolve versions published in the last seven days. 10.5.0 was published on 2026-08-10,
hours before this change, and a clean `npm install` against it fails with ETARGET.
10.4.0 was published 2026-07-31 and already carries the fixes for all three ip-address
advisories, so the cooldown costs nothing here.

The lockfile was regenerated with no node_modules present. Regenerating with an
installed tree resolves only the host platform and silently drops 45 cross-platform
optional binaries, which would leave the lock unable to install on Linux or Windows.
The committed lock retains them.

Remaining deltas against the base lock are dependency hoisting plus the removal of the
android-arm64 and wasm32-wasi rolldown bindings and their emnapi/wasm fallbacks. Two
high-severity advisories remain in devDependencies only (nanoid, postcss) and are not
addressed here.

Not verified by an install: node_modules in this worktree still reflects the previous
lock. Run `npm ci` in a clean checkout before relying on this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuxixGsgf1bVvxrpWJn7zB
…oundary

Project-provided instructions and executable resources were loaded from any
working directory without consent. Trust is now resolved for the canonical cwd
before project settings, resource discovery, or daemon-bound runtime services
are created, and re-resolved whenever the cwd changes.

The gate covers project settings, packages, extensions, skills, prompts,
themes, SYSTEM.md/APPEND_SYSTEM.md, ancestor AGENTS.md/CLAUDE.md, and non-user
.agents/skills. Decisions are keyed by canonical path in trust.json with
ancestor inheritance; an unreadable or invalid store fails closed with a
visible diagnostic. The interactive prompt appears only where the directory or
an ancestor actually holds a trust-requiring resource, and --approve/-a and
--no-approve/-na override a single run without persisting.

Also in this change:

- Carry the trust decision across daemon protocol 8 / schema revision 16, with
  create gated on protocol 8 in both directions rather than silently starting
  with mismatched trust semantics.
- Make the operation ledger durable: validated checkpoint journal,
  snapshot-plus-journal recovery, torn-final-line tolerance, corrupt-interior
  warnings, exact-once reconciliation, and monotonic uncertainty counters that
  survive compaction.
- Settle human deadline extensions through an atomic one-winner inbox claim.
- Make the notification outbox restart-safe: reload under lock, atomic delivery
  cycles, acknowledgement precedence, and a durable 1/2/4/8/15-minute retry
  schedule. A corrupt outbox now fails loudly instead of being silently
  replaced with an empty one.
- Add a repository-owned launchd monitor service with install/uninstall/status,
  packaged-runner validation, and 180-second stale detection. Its shell runner
  and the Node writer share one state mutex, and it no longer loses the
  monitor's exit code when that lock is contended.
- Share one synchronous file-lock helper across the trust store, extension
  inbox, notification outbox, and monitor state, waiting on the monotonic
  scheduler rather than spinning on the wall clock.
- Remove degenerate model-test coupling to ambient Google/Groq credentials.
- Update nanoid to 3.3.17, postcss to 8.5.23, and undici to 7.29.0 within the
  supply-chain cooldown, and declare @opentelemetry/api for clean-install
  browser bundling.
- Require every repository file, inherited work included, to enter a commit,
  while never committing local machine state (AGENTS.md). Uncommitted inherited
  work was being left behind as "caution" when it is the only unrecoverable
  state.

Verified: npm run check exit 0; full coding-agent suite 319 files, 4163 tests
passing, 58 skipped, matching the pre-change skip count. Each regression test
added here was proven to fail with its own fix reverted.
# Conflicts:
#	packages/coding-agent/CHANGELOG.md
The blanket build prohibition is unworkable for two cases this repo actually
has. packages/agent resolves through main: ./dist/index.js and the pi-*
packages resolve via node_modules/@earendil-works symlinks into packages/*,
so both --dist and tsx source mode load built artifacts: a locally installed
agent cannot run current code without a build. And the full suite cannot pass
from a fresh npm ci without one, failing extension loading with a missing
pi-agent-core/dist/index.js, which is why every CI workflow runs
npm ci -> npm run build -> npm run check.

Both uses are audited and must be named in the receipt. Routine work still
does not build.
Regenerated by npm run build against live provider data. Drops delisted
entries including claude-opus-4-1, gemini-2.5-pro, gemini-2.0-flash and
nemotron-3-ultra; adds current ones including grok-4.5, kimi-k3,
gemini-3.6-flash, deepseek-v4-flash and qwen3.8-max.

Kept as its own commit so the catalog can be reverted independently of the
upstream reconciliation if a removed model is still referenced somewhere.
--approve/-a and --no-approve/-na were parsed but never shown, so the only
discoverable reference was docs/usage.md.
Dr Kennedy Umege added 17 commits August 10, 2026 21:55
The ai package gained a degenerate-generation abort, a regenerated model
catalog with removals, and dependency changes, all with an empty
[Unreleased]. Each package owns its own changelog, so these belong here
rather than only in the coding-agent one.
The previous bullet read as though claude-opus-4-1, gemini-2.5-pro and
gemini-2.0-flash were removed outright. They were not: the regeneration
refreshes per-provider listings. claude-opus-4-1 dropped from anthropic and
opencode but is still reachable via cloudflare-ai-gateway, gemini-2.5-pro
dropped from github-copilot but remains on google and google-vertex, and
gemini-2.0-flash dropped from google but remains on google-vertex. Only
nemotron-3-ultra left the catalog entirely.

Corrective commit rather than an amend; 114b96f is already published.
The build exception landed without its counterpart. A protected update
reconciling this fork onto upstream can only be cleared against the whole
tree, but the test rule still allowed nothing beyond user-named files, so
the update protocol and this file contradicted each other. Cap the workers
so the real-process daemon tests are not starved into a false failure.
prime-agent.sh exports PRIME_AGENT_BUILD_ID from the worktree's live
git describe, and identity resolution preferred that environment value over
the bundle's embedded __PI_BUILD_ID__. Committing without rebuilding and then
restarting therefore made the daemon report the current checkout while it was
still serving the older bundle, so the mismatch that is supposed to reveal a
stale install became invisible.

The embedded id is the only value that describes the code actually loaded.
The environment now serves as the fallback for unbundled execution, where
__PI_BUILD_ID__ is never substituted.

Verified by reverting the precedence and confirming the new test fails.
packages/ai's build runs generate-models against live provider APIs, so every
build rewrites tracked source with current pricing and leaves the tree dirty.
Committing the drift so the working tree is clean.
packages/ai ran generate-models before every compile, fetching live provider
and pricing data. Every build therefore rewrote tracked source and left the
tree dirty, which made builds non-reproducible and stamped every locally built
identity -dirty. It also broke release integrity: prepublishOnly rebuilds
after the release commit and tag, so the published catalog was not the one in
the tagged tree.

The ordinary build now compiles the checked-in catalog with no network access.
Refreshing it is an explicit step, and release.mjs runs it before the version
bump so the refreshed catalog lands in the release commit itself.

Verified: two consecutive builds leave git status unchanged.
Rebase private-lane opts onto upstream 965941c (v0.7.2 + worker lifecycle
PrimeIntellect-ai#850/PrimeIntellect-ai#851/PrimeIntellect-ai#852, queue edit PrimeIntellect-ai#838, reasoning metadata, deps).

Preserved: project trust, operation ledger, reliability monitor, build-id
authority, repetition guard, AGENTS.md protected-update exceptions.

Conflict policy:
- CHANGELOGs: deduplicated union under [Unreleased]
- typebox: upstream ^1.3.9; keep @opentelemetry/api for Mistral clean-install
- models.generated: upstream catalog
- daemon protocol: v8 + schema 18 (upstream revs 15-16 + local ledger/trust 17-18)
- daemon-supervisor: upstream stop/finalization + local adopt SIGKILL + identity helpers
Conflict resolution left SIGKILL/stopWorker nested inside the identity
backfill branch and dropped the closing brace, leaving the file one brace
deep. Also resync package-lock for the kept @opentelemetry/api dep.
- schema revision 18 with computed SCHEMA_ID covering upstream queue/stop
  revisions plus local ledger/trust
- processIdentity uses compareProcessStartIds so legacy ps: tokens stay
  unverifiable instead of treated as recycled pids
- heartbeats_list skips failed workers (issue PrimeIntellect-ai#1045)
- adopt path relies on upstream identity-aware stopWorker (no pre-SIGKILL)
# Conflicts:
#	packages/coding-agent/src/modes/daemon/daemon-catalog-process.ts
#	packages/coding-agent/src/modes/daemon/daemon-mode.ts
#	packages/coding-agent/test/daemon-catalog-process.test.ts
#	packages/coding-agent/test/daemon-mode.test.ts
Sync the zai section of the model snapshot with the models.dev
catalog: adds glm-5.3, served on the coding plan endpoint since
2026-08-14. Other provider sections are left untouched.
Running the suite from inside a live Prime Agent daemon worker (an agent
asked to run the tests by its own kernel) leaked live-session state into
both in-process main() calls and spawned CLI children, failing 24 tests
across 6 files identically at the merge tip, the pristine pre-merge tip,
and the installed worktree:

- NO_COLOR + FORCE_COLOR both set -> spawned node binaries warn on
  stderr -> 9 empty-stderr assertion failures in 4685-daemon-client-modes
- RLM_MAX_DEPTH from the worker env -> AgentSession max-depth source
  "env" instead of "default" -> agent-session-recursion failure
- PRIME_AGENT_INTERNAL_DAEMON_SUPERVISOR_SOCKET ->
  resolveUpdateDaemonSocketPath() bypassed TMPDIR/agent-dir redirects ->
  self-update probed the developer's real daemon and refused on live
  busy sessions -> 4 package-command-paths failures
- PRIME_AGENT_INTERNAL_* worker identity env inherited by spawned test
  daemons -> slow/failed supervisor handshakes -> 10 timeouts across
  daemon-supervisor-process, 4600-supervisor-singleton,
  4606-update-restart-coordinator

Fix: test/setup-env.ts (vitest setupFiles) deletes the color conflict,
the RLM session/harness vars, and the PRIME_AGENT_INTERNAL_/PI_INTERNAL_
worker identity class before any test module loads. Tests that need
these vars set their own after setup.

Verified: six affected files green with polluted env + resident daemon
(157 passed/8 skipped), then full canonical suite
(--maxWorkers=5) green in the same conditions:
328 files passed / 9 skipped, 4294 tests / 60 skipped / 0 failed, 114s.
@github-actions

Copy link
Copy Markdown

Hi @Kenmege, thanks for your interest in contributing!

This project requires that pull request authors are vouched, and you are not in the list of vouched users.

This PR will be closed automatically. See https://github.com/PrimeIntellect-ai/prime-agent/blob/main/CONTRIBUTING.md for more details.

@github-actions github-actions Bot closed this Aug 16, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8978a50e51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

/** Create a SettingsManager from an arbitrary storage backend */
static fromStorage(storage: SettingsStorage): SettingsManager {
static fromStorage(storage: SettingsStorage, options: SettingsManagerCreateOptions = {}): SettingsManager {
const projectTrusted = options.projectTrusted ?? true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Default project settings to untrusted

When callers omit the new option, this defaults to trusted and immediately reads project settings. The public createAgentSession() SDK path does exactly that in core/sdk.ts:166, then reloads a DefaultResourceLoader, so opening an untrusted checkout through the SDK can still execute extensions and packages configured by that checkout without any trust decision; the early config/package command handlers have the same omission. Default this to false or require callers to pass an explicit resolved decision rather than preserving the old trust behavior.

AGENTS.md reference: AGENTS.md:L18-L19

Useful? React with 👍 / 👎.

Comment on lines +1252 to +1254
const startupSettingsManager = SettingsManager.create(cwd, agentDir, { projectTrusted: false });
reportDiagnostics(collectSettingsDiagnostics(startupSettingsManager, "startup session lookup"));
const projectTrustResolver = createMainProjectTrustResolver({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve trust before running project migrations

When normal startup begins in an untrusted checkout containing .prime/agent/commands, runMigrations(cwd) at line 1248 runs before this trust resolver is created. migrateExtensionSystem() then inspects project resource directories and can rename commands/ to prompts/ before the user sees the trust prompt, so choosing “Do not trust” still allows the checkout to trigger filesystem mutations. Resolve trust first, or defer project-scoped migrations until the project is trusted.

Useful? React with 👍 / 👎.

Comment on lines +280 to +282
...(operationSummary || activeSession.summaryClassifierState
? {
reliability: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Gate reliability metadata on the negotiated capability

When a protocol-7 client without operation_ledger_v1 uses list, attach, or get_state, this code still includes the new reliability shape because summaryForActiveSession() has no client-capability context. The repository-wide search shows isOperationLedgerNegotiated() is used only by protocol tests, so the declared capability never controls the wire payload and strict older clients can reject responses they are still allowed to request. Strip this field unless both sides negotiated the capability, or make every response carrying it protocol-incompatible.

AGENTS.md reference: AGENTS.md:L41-L45

Useful? React with 👍 / 👎.

get(cwd: string): ProjectTrustDecision {
return withTrustFileLock(this.trustPath, () => {
const data = readTrustFile(this.trustPath);
let currentDir = canonicalizeDirectory(cwd);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind saved trust to the lexical resource ancestry

When a previously trusted real directory is opened through a symlink under a different, untrusted ancestor, canonicalizing cwd here returns the saved true before that lexical ancestry is considered. loadProjectContextFiles() deliberately walks the lexical path in resource-loader.ts:98-112, so it then loads AGENTS.md or CLAUDE.md from the symlink's untrusted parent without prompting; for example, /untrusted/repo/link -> /trusted/project inherits /trusted/project's decision but loads /untrusted/repo/AGENTS.md. Canonicalize resource discovery too, or include the lexical ancestry when resolving saved decisions.

Useful? React with 👍 / 👎.

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.

4 participants