Skip to content

fix(cli): allow remote extraction chosen in setup - #2116

Open
aaf2tbz wants to merge 3 commits into
mainfrom
fix/2015-extraction-privacy-tier
Open

aaf2tbz wants to merge 3 commits into
mainfrom
fix/2015-extraction-privacy-tier

Conversation

@aaf2tbz

@aaf2tbz aaf2tbz commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2015. signet setup gave the memory_extraction task class privacy: restricted_remote for every extraction provider. The router (platform/core/src/routing.ts) infers remote_ok for a remote openrouter or openai-compatible target. remote_ok ranks below restricted_remote, so the router blocked the only candidate. Fresh installs with a remote extraction model could never route memory_extraction, so Dreaming never ran.

The router's behavior is correct; the setup output is not. Per #1258 / #1265, the dashboard records an operator's decision to send memory to a remote provider as privacy: remote_ok on the task class. Dashboard onboarding writes it when a remote provider is picked, and Settings → Inference writes it on "Use remotely". This PR makes CLI setup follow the same contract. Router defaults are unchanged.

Changes

  • surfaces/cli/src/features/setup-pipeline.ts: setup writes privacy: remote_ok on memory_extraction when the operator picks openrouter, or openai-compatible with a non-loopback endpoint. Locality is checked with the router's own isLocalInferenceEndpoint. Neither provider is ever auto-detected, so either one is an explicit choice. Ollama, llama.cpp, loopback openai-compatible, and ACPX keep restricted_remote, so the dashboard still asks before any of them is moved to a remote provider. ACPX can be auto-detected, so setup does not record consent for it; Settings → Inference already treats an ACPX target as remote and asks for it directly. The route resolves either way, because the router infers restricted_remote for ACPX targets. isGeneratedSetupTaskClass also recognizes the remote_ok variant, so switching setup to --extraction-provider none still removes it.
  • surfaces/cli/src/features/health.ts: for existing installs, signet doctor resolves the memory_extraction route from agent.yaml with resolveRoutingDecision, treating every target as healthy. If the route fails on the privacy gate, doctor warns (memory_extraction_privacy_blocked). The warning names the blocked target and gives the fix: "Use remotely" in Settings → Inference, or privacy: remote_ok in agent.yaml.
  • Docs: web/docs/src/content/docs/cli/getting-started.md describes the setup behavior, including the dashboard's ACPX consent prompt. web/docs/src/content/docs/benchmarking.md now says why the bench still sets target privacy (it swaps the executor after setup).

Type

  • feat — new user-facing feature (bumps minor)
  • fix — bug fix
  • refactor — restructure without behavior change
  • chore — build, deps, config, docs
  • perf — performance improvement
  • test — test coverage

Packages affected

  • @signet/core
  • @signet/daemon
  • @signet/cli / dashboard
  • @signet/sdk
  • @signet/connector-*
  • @signet/web
  • predictor
  • Other:

Screenshots

N/A, no UI changes.

Migration Notes (if applicable)

  • Migration is idempotent
  • Rollback / compatibility note included in PR description

No config migration, on purpose. A migration that rewrites existing restricted_remote task classes to remote_ok cannot tell a setup-written route from one where the operator later pointed a local target at a remote endpoint by hand. Rewriting the second kind would grant remote-extraction consent the operator never gave. Existing installs get the doctor warning, and the Settings → Inference consent prompt already appears for them when the dashboard opens.

Testing

  • bun test passes: surfaces/cli/src/features/setup-pipeline.test.ts, health.test.ts, setup.test.ts
  • bun run typecheck passes: @signet/cli has no typecheck script. A scoped tsc --noEmit over the touched files found no errors on changed lines.
  • bun run lint passes: bunx biome check on changed files, bun run comments:check
  • Tested against running daemon
  • N/A

New tests send each setup-generated route (OpenRouter, remote and loopback OpenAI-compatible, Ollama, llama.cpp, ACPX) through parseRoutingConfig and resolveRoutingDecision. The remote cases fail on main with privacy gate (restricted_remote). The doctor test fails without the health.ts change.

Manual reproduction with a temp HOME on main: signet setup --non-interactive --extraction-provider openai-compatible --extraction-model glm-5.3-flash --extraction-endpoint https://open.bigmodel.cn/api/coding/paas/v4 wrote restricted_remote, and resolving the route offline returned blockedBy: ["privacy gate (restricted_remote)"]. On this branch the same command writes remote_ok and the route resolves to background/default. The same holds for openrouter. Loopback openai-compatible and ollama still write restricted_remote and still resolve. Running signet doctor --json on the workspace from main reports memory_extraction_privacy_blocked, and on the new workspace it reports nothing.

Live verification: I ran two isolated daemons from source, one from main and one from this branch, each with its own temp HOME and SIGNET_PATH. A local OpenAI-compatible stub stood in for the provider. It listened on this machine's LAN IP (http://10.0.0.142:<port>/v1), so the router treated the endpoint as remote.

  • Setup. signet setup --non-interactive --extraction-provider openai-compatible --extraction-model glm-test --extraction-endpoint http://10.0.0.142:…/v1. main's CLI wrote privacy: restricted_remote, and this branch's CLI wrote privacy: remote_ok. The rest of the inference block was identical.
  • Matching the issue's setup. Setup writes no account for a remote openai-compatible endpoint. Without one, the router also blocks the target with missing credential: main reported that next to the privacy gate, and this branch reported only missing credential. To match the issue (runtime healthy, account ready), I added an api account with a credentialRef pointing at a dummy env var to both workspaces.
  • main. POST /api/inference/explain {"operation":"memory_extraction"} and POST /api/inference/execute {"workload":"memoryExtraction"} returned blockedBy: ["privacy gate (restricted_remote)"] with runtime healthy, account ready; execute returned HTTP 502. The Dreaming scheduler reported blocked / inference_unavailable, and POST /api/dream/trigger returned 503 "No inference provider is connected". The stub received no completion requests.
  • This branch. The route resolved to background/default (blockedBy: []), and execute returned the stub's reply. The Dreaming scheduler reported idle. After one /api/memory/remember, POST /api/dream/trigger returned 202. The pass completed, and the stub logged a 56 KB streamed /v1/chat/completions request for glm-test.
  • Doctor. This branch's signet doctor --json against the main-created workspace reported memory_extraction_privacy_blocked (warn, exit 0); the human output showed the same text. Against this branch's workspace it reported no such finding.
  • Local providers. Loopback openai-compatible (http://127.0.0.1:…/v1) and ollama setups still wrote restricted_remote. Each route resolved live against a loopback stub, with execute returning 200, and doctor reported no warning for either.
  • Stability. Every daemon booted clean and passed /health. Shutdown logged only the same benign lines as main.

AI disclosure

  • No AI tools were used in this PR
  • AI tools were used (see Assisted-by tags in commits)

Notes

  • scripts/bench-memory.ts still sets privacy: restricted_remote on its target. The bench now needs it only when setup ran against a loopback endpoint and the bench then swaps in a remote executor. I left it unchanged.
  • The doctor finding is warn, not error, so it does not change doctor's exit status.
  • Unchanged: signet status still prints "Memory is paused until you connect a provider" when Dreaming's scheduler reports inference_unavailable, and that is misleading for a privacy block. Fixing it means passing the router's blockedBy through the Dreaming scheduler status, which belongs in a separate change.

Setup wrote the memory_extraction task class with privacy
restricted_remote for every provider. The router infers remote_ok
for a remote openrouter or openai-compatible target and blocks it
because remote_ok ranks below restricted_remote, so a fresh install
with a remote extraction model could never run Dreaming.

Choosing a remote provider in setup is the operator's decision to
send memory to it. Record that the way dashboard onboarding and the
Settings consent prompt already do, with privacy remote_ok on the
task class. Local targets and ACPX keep restricted_remote, so the
dashboard still asks before they are switched to a remote provider.

Assisted-by: Claude-Code:claude-opus-5-5
Installs set up before the previous commit keep a memory_extraction
task class that their remote target can never satisfy. The daemon
reports runtime healthy and account ready, and status only says to
connect a provider, so nothing names the privacy gate.

signet doctor now resolves the memory_extraction route from
agent.yaml with every target treated as healthy. When the route
fails on the privacy gate it warns with the blocked target and the
two ways to fix it. It does not change the config: allowing remote
extraction stays an explicit operator choice.

Assisted-by: Claude-Code:claude-opus-5-5
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 52 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 35f01893-bd2f-480a-b373-7ea0c38d1d32
📥 Commits

Reviewing files that changed from the base of the PR and between ea8e8b5 and 574b650.

📒 Files selected for processing (6)
  • surfaces/cli/src/features/health.test.ts
  • surfaces/cli/src/features/health.ts
  • surfaces/cli/src/features/setup-pipeline.test.ts
  • surfaces/cli/src/features/setup-pipeline.ts
  • web/docs/src/content/docs/benchmarking.md
  • web/docs/src/content/docs/cli/getting-started.md
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Assisted-by: Claude-Code:claude-opus-5-5
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.

Fresh installs with a remote extraction model can never run Dreaming (privacy gate)

1 participant