feat(agent): CMP-1 add sandboxed builder and runner runtimes - #60
Conversation
5aecfef to
142b908
Compare
142b908 to
15b42b7
Compare
There was a problem hiding this comment.
All reported issues were addressed across 82 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
15b42b7 to
8041bc9
Compare
8041bc9 to
85d6f90
Compare
85d6f90 to
8ff7393
Compare
8ff7393 to
a50e53b
Compare
a50e53b to
6f777ef
Compare
There was a problem hiding this comment.
7 issues found across 91 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docs/setup.md">
<violation number="1" location="docs/setup.md:54">
P3: Minor doc accuracy: the interactive flag is set in apps/agent/turbo.json's dev task, not the root Turbo task (root `turbo.json` dev has dependsOn/cache/persistent only). Point the reader at the agent package's task so they know where the flag lives.</violation>
</file>
<file name="packages/db/prisma/migrations/20260806160000_agent_version_model_context_window/migration.sql">
<violation number="1" location="packages/db/prisma/migrations/20260806160000_agent_version_model_context_window/migration.sql:2">
P2: Existing deployed versions created with a model whose context window is not 1,000,000 tokens will run with an incorrect window after this migration, potentially causing oversized provider requests or premature context limits. A migration/backfill should preserve the context window associated with each historical `modelId` before enforcing the non-null default.</violation>
</file>
<file name="apps/agent/agent/hooks/audit.ts">
<violation number="1" location="apps/agent/agent/hooks/audit.ts:160">
P2: Nested `agent_runner` completions can overwrite the durable run summary because every `message.completed` event with the run attributes updates `agentRun.summary`, regardless of session depth. Restrict this summary projection to the root session so late subagent events cannot change the result used by `session.completed`.</violation>
</file>
<file name="apps/agent/agent/lib/run-runtime.ts">
<violation number="1" location="apps/agent/agent/lib/run-runtime.ts:84">
P2: Selected-scope searches can incorrectly report no match for an approved record. Unapproved records can consume the helper's per-kind limit before the scope filter runs, so the search needs to apply approved-record predicates before ranking/truncation.</violation>
<violation number="2" location="apps/agent/agent/lib/run-runtime.ts:118">
P1: A selected-scope run can read CRM records that were never approved for the version. `readRunRecord` authorizes only the root ID but returns helper payloads containing other contacts, deals, colleagues, and whole-account correspondence; applying the manifest resource set to nested records or returning a scope-safe projection would preserve the promised exact-record scope.</violation>
</file>
<file name="apps/agent/scripts/start.ts">
<violation number="1" location="apps/agent/scripts/start.ts:14">
P2: On Windows, the production `start` script cannot launch Eve because `eve.cmd` is spawned without a shell or `cmd.exe /c`; enabling the Windows shell for this validated numeric command would keep the documented cross-platform launcher working.</violation>
</file>
<file name="apps/agent/agent/lib/builder-runtime.ts">
<violation number="1" location="apps/agent/agent/lib/builder-runtime.ts:663">
P2: Builder artifacts can persist common OAuth/JWT credentials even though the builder contract promises that files cannot contain tokens or secret values. Broader secret detection (or a dedicated secret-scanning utility) would prevent `write_agent_file` from accepting these formats.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
| const sources = allowedHistorySources(run.allowedResources); | ||
|
|
||
| if (input.kind === "contact") | ||
| return readCrmHistory(input.id, { |
There was a problem hiding this comment.
P1: A selected-scope run can read CRM records that were never approved for the version. readRunRecord authorizes only the root ID but returns helper payloads containing other contacts, deals, colleagues, and whole-account correspondence; applying the manifest resource set to nested records or returning a scope-safe projection would preserve the promised exact-record scope.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/agent/agent/lib/run-runtime.ts, line 118:
<comment>A selected-scope run can read CRM records that were never approved for the version. `readRunRecord` authorizes only the root ID but returns helper payloads containing other contacts, deals, colleagues, and whole-account correspondence; applying the manifest resource set to nested records or returning a scope-safe projection would preserve the promised exact-record scope.</comment>
<file context>
@@ -0,0 +1,644 @@
+ const sources = allowedHistorySources(run.allowedResources);
+
+ if (input.kind === "contact")
+ return readCrmHistory(input.id, {
+ threads: 10,
+ includeEmail: sources.gmail,
</file context>
| @@ -0,0 +1,2 @@ | |||
| ALTER TABLE "agentVersion" | |||
| ADD COLUMN "modelContextWindowTokens" INTEGER NOT NULL DEFAULT 1000000; | |||
There was a problem hiding this comment.
P2: Existing deployed versions created with a model whose context window is not 1,000,000 tokens will run with an incorrect window after this migration, potentially causing oversized provider requests or premature context limits. A migration/backfill should preserve the context window associated with each historical modelId before enforcing the non-null default.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/db/prisma/migrations/20260806160000_agent_version_model_context_window/migration.sql, line 2:
<comment>Existing deployed versions created with a model whose context window is not 1,000,000 tokens will run with an incorrect window after this migration, potentially causing oversized provider requests or premature context limits. A migration/backfill should preserve the context window associated with each historical `modelId` before enforcing the non-null default.</comment>
<file context>
@@ -0,0 +1,2 @@
+ALTER TABLE "agentVersion"
+ADD COLUMN "modelContextWindowTokens" INTEGER NOT NULL DEFAULT 1000000;
</file context>
| }); | ||
| } | ||
|
|
||
| if (type === "message.completed") { |
There was a problem hiding this comment.
P2: Nested agent_runner completions can overwrite the durable run summary because every message.completed event with the run attributes updates agentRun.summary, regardless of session depth. Restrict this summary projection to the root session so late subagent events cannot change the result used by session.completed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/agent/agent/hooks/audit.ts, line 160:
<comment>Nested `agent_runner` completions can overwrite the durable run summary because every `message.completed` event with the run attributes updates `agentRun.summary`, regardless of session depth. Restrict this summary projection to the root session so late subagent events cannot change the result used by `session.completed`.</comment>
<file context>
@@ -34,3 +48,136 @@ export default defineHook({
+ });
+ }
+
+ if (type === "message.completed") {
+ const message = recordOf(data).message;
+ if (typeof message === "string" && message.trim()) {
</file context>
| const scoped = run.allowedResources.filter( | ||
| (resource) => resource.kind !== "integration", | ||
| ); | ||
| const result = await searchCrm(input.query, input); |
There was a problem hiding this comment.
P2: Selected-scope searches can incorrectly report no match for an approved record. Unapproved records can consume the helper's per-kind limit before the scope filter runs, so the search needs to apply approved-record predicates before ranking/truncation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/agent/agent/lib/run-runtime.ts, line 84:
<comment>Selected-scope searches can incorrectly report no match for an approved record. Unapproved records can consume the helper's per-kind limit before the scope filter runs, so the search needs to apply approved-record predicates before ranking/truncation.</comment>
<file context>
@@ -0,0 +1,644 @@
+ const scoped = run.allowedResources.filter(
+ (resource) => resource.kind !== "integration",
+ );
+ const result = await searchCrm(input.query, input);
+ if (run.recordScope === "WORKSPACE") return result;
+
</file context>
| } | ||
|
|
||
| const cli = process.platform === "win32" ? "eve.cmd" : "eve"; | ||
| const child = spawn(cli, ["start", "--port", String(port)], { |
There was a problem hiding this comment.
P2: On Windows, the production start script cannot launch Eve because eve.cmd is spawned without a shell or cmd.exe /c; enabling the Windows shell for this validated numeric command would keep the documented cross-platform launcher working.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/agent/scripts/start.ts, line 14:
<comment>On Windows, the production `start` script cannot launch Eve because `eve.cmd` is spawned without a shell or `cmd.exe /c`; enabling the Windows shell for this validated numeric command would keep the documented cross-platform launcher working.</comment>
<file context>
@@ -0,0 +1,42 @@
+}
+
+const cli = process.platform === "win32" ? "eve.cmd" : "eve";
+const child = spawn(cli, ["start", "--port", String(port)], {
+ stdio: "inherit",
+ env: process.env,
</file context>
| } | ||
|
|
||
| function assertSafeArtifact(content: string): void { | ||
| const secretPatterns = [ |
There was a problem hiding this comment.
P2: Builder artifacts can persist common OAuth/JWT credentials even though the builder contract promises that files cannot contain tokens or secret values. Broader secret detection (or a dedicated secret-scanning utility) would prevent write_agent_file from accepting these formats.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/agent/agent/lib/builder-runtime.ts, line 663:
<comment>Builder artifacts can persist common OAuth/JWT credentials even though the builder contract promises that files cannot contain tokens or secret values. Broader secret detection (or a dedicated secret-scanning utility) would prevent `write_agent_file` from accepting these formats.</comment>
<file context>
@@ -0,0 +1,683 @@
+}
+
+function assertSafeArtifact(content: string): void {
+ const secretPatterns = [
+ /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/i,
+ /\b(?:api[_-]?key|password|secret|access[_-]?token)\b\s*[:=]\s*["']?[a-z0-9_./+=-]{12,}/i,
</file context>
| interactive TUI and turbo redraw over each other. `dev:tui` keeps the interactive one, | ||
| and only that writes `.eve/logs/` for `eve logs`; under `--no-ui` the turbo pane is | ||
| the record. | ||
| The agent package's default `dev` command is interactive `eve dev`. The root |
There was a problem hiding this comment.
P3: Minor doc accuracy: the interactive flag is set in apps/agent/turbo.json's dev task, not the root Turbo task (root turbo.json dev has dependsOn/cache/persistent only). Point the reader at the agent package's task so they know where the flag lives.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/setup.md, line 54:
<comment>Minor doc accuracy: the interactive flag is set in apps/agent/turbo.json's dev task, not the root Turbo task (root `turbo.json` dev has dependsOn/cache/persistent only). Point the reader at the agent package's task so they know where the flag lives.</comment>
<file context>
@@ -43,10 +51,14 @@ inventory, including a `diagnostics` count that finds files eve silently ignored
-interactive TUI and turbo redraw over each other. `dev:tui` keeps the interactive one,
-and only that writes `.eve/logs/` for `eve logs`; under `--no-ui` the turbo pane is
-the record.
+The agent package's default `dev` command is interactive `eve dev`. The root
+Turbo task marks it interactive, so select the agent pane and press Enter before
+using the eve TUI. Run `turbo run dev:headless --filter=agent` when a terminal
</file context>
…-stack-02-runtime # Conflicts: # docs/environment.md
…-stack-02-runtime
…-stack-02-runtime
Summary
Adds the Eve builder and runner runtimes, purpose-separated sessions, sandboxed subagents, scoped CRM tools, audit hooks, scheduling, evals, and runtime coverage.
Why
The durable domain needs a constrained execution layer that can build drafts and run deployed agents without leaking credentials or overreaching permissions.
Stack
Depends on #67 — durable custom-agent domain.
Verification