Skip to content

feat: consolidated open build — KAIROS, bridge, cleanup, feature flags, security#660

Closed
Flo5k5 wants to merge 16 commits into
Gitlawb:mainfrom
Flo5k5:feat/kairos-assistant-mode
Closed

feat: consolidated open build — KAIROS, bridge, cleanup, feature flags, security#660
Flo5k5 wants to merge 16 commits into
Gitlawb:mainfrom
Flo5k5:feat/kairos-assistant-mode

Conversation

@Flo5k5
Copy link
Copy Markdown
Contributor

@Flo5k5 Flo5k5 commented Apr 13, 2026

Summary

Consolidated PR merging all open work into a single coherent changeset, rebased on latest main. Supersedes PRs #633, #637, #644, #667, #668.

Partially addresses #654 — the bridge server provides HTTP/SSE infrastructure for web-based session interaction.

Changes (4 commits, 62 files, +2171/-942)

1. Security guidance (#668, 2 files)

  • Replace Anthropic-internal refusal language with positive security guidance for red teaming and CTFs
  • Simplify FileReadTool mitigation logic

2. Cleanup + open features (#637 + #644, 35 files, -1200 lines)

  • Remove ~45 dead USER_TYPE=ant guards across 28+ files
  • Open 13 useful features: agent nesting, effort persistence, plan mode interview, sandbox config
  • Key: src/constants/tools.ts — unlock recursive agent spawning

3. Feature flags + runtime defaults (#667 + #633, 3 files)

  • Activate 18 build-time flags: KAIROS, BRIDGE_MODE, AGENT_TRIGGERS, ULTRATHINK, TOKEN_BUDGET, HISTORY_PICKER, EXTRACT_MEMORIES, FORK_SUBAGENT, etc.
  • Add _openBuildDefaults in GrowthBook stub for centralized runtime gate control
  • Bridge flags enabled: tengu_ccr_bridge, tengu_bridge_repl_v2, tengu_kairos_brief
  • Priority chain: ~/.claude/feature-flags.json > _openBuildDefaults > defaultValue

4. KAIROS + local bridge server (22 files, new)

KAIROS assistant mode:

  • src/assistant/: gate, API, session discovery stub
  • src/proactive/: no-op stubs for proactive mode
  • src/tools/SleepTool/: interruptible sleep (0-5min)
  • src/commands/assistant/, src/commands/proactive.ts: /assistant, /proactive

Local bridge server:

  • packages/bridge-server/: standalone Bun server emulating CCR v2 protocol
  • 10+ endpoints: sessions, JWT, SSE streaming, events, file upload
  • --port, --host 0.0.0.0 for Tailscale/WireGuard remote access

BRIDGE_MODE activation:

  • bridgeEnabled.ts: bypass OAuth check, let _openBuildDefaults control gates
  • bridgeConfig.ts: add localhost:4080 fallback + default token
  • initReplBridge.ts: skip org policy check with token override

Tools:

  • SendUserFileTool: file delivery via BriefTool attachment pipeline
  • PushNotificationTool: OS-native notifications (osascript/notify-send)
  • MonitorMcpDetailDialog: detail UI for monitor background tasks

Runtime activation

# Start bridge server:
bun run packages/bridge-server --port 4080

# Connect CLI:
CLAUDE_BRIDGE_BASE_URL=http://localhost:4080 openclaude

# Assistant mode: { "assistant": true } in settings
# Coordinator: CLAUDE_CODE_COORDINATOR_MODE=1
# Override flags: ~/.claude/feature-flags.json

PRs superseded

PR Content
#633 Included in #667 (AGENT_TRIGGERS=true)
#637 Cleanup dead USER_TYPE branches
#644 Open USER_TYPE-gated features
#667 Enable 15+ feature flags + runtime defaults
#668 Positive security guidance

Test plan

  • bun run build — 211 files pre-processed
  • bun run smoke — version OK
  • bun test809 pass, 10 fail (pre-existing)
  • Bridge server: health + full protocol test (session → JWT → events → 409)
  • CLI ↔ bridge server end-to-end connection
  • SendUserFileTool upload to bridge
  • PushNotificationTool OS notification
  • Remote access via --host 0.0.0.0

Copilot AI review requested due to automatic review settings April 13, 2026 09:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Activates the “KAIROS” assistant/daemon mode in the open build by wiring in assistant-mode infrastructure, adding stubs for proactive mode, introducing an interruptible Sleep tool, exposing new /assistant and /proactive commands, and updating the build pipeline to reliably constant-fold feature() flags under Bun v1.3.9+.

Changes:

  • Add assistant-mode modules (src/assistant/*) and assistant/proactive commands (src/commands/*) to enable and inspect KAIROS behavior at runtime.
  • Introduce SleepTool (interruptible, settings-clamped) and proactive-mode stubs to satisfy gated imports without enabling full ticking.
  • Update the build script to pre-process feature('FLAG') calls into boolean literals and flip multiple feature flags on in the open build; enable team memory by default and add a settings knob for bypass-permissions availability.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/build.ts Enables KAIROS-related flags and replaces the broken bun:bundle shim with in-place source pre-processing + restore.
src/assistant/gate.ts Open-build runtime gate for KAIROS via local GrowthBook stub / feature-flags file.
src/assistant/index.ts Assistant-mode detection, team bootstrap for in-process subagents, and system-prompt addendum loading.
src/assistant/sessionDiscovery.ts Open-build stub for remote session discovery (returns none).
src/commands/assistant/index.ts Re-export entrypoint for the /assistant command module.
src/commands/assistant/assistant.ts Implements /assistant command and provides stub wizard exports used by dialog launchers.
src/commands/proactive.ts Adds /proactive toggle command (using the proactive stub module).
src/proactive/index.ts Proactive-mode state stub (activate/deactivate/pause/subscribe) without tick scheduling.
src/proactive/useProactive.ts No-op React hook stub to satisfy gated imports in the REPL UI.
src/tools/SleepTool/SleepTool.ts New interruptible sleep tool, enabled only when KAIROS is active; clamps sleep duration via settings.
src/memdir/teamMemPaths.ts Defaults the team-memory feature gate to enabled when auto-memory is enabled.
src/utils/permissions/permissionSetup.ts Adds support for permissions.allowBypassPermissionsMode when deciding bypass-mode availability.
src/utils/settings/settings.ts Registers permissions.allowBypassPermissionsMode for managed-settings logging key expansion.
src/utils/settings/types.ts Adds permissions.allowBypassPermissionsMode to the settings schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/build.ts
Comment on lines +87 to +90
preProcessFeatureFlags(join(import.meta.dir, '..', 'src'))
const numModified = modifiedFiles.size

try {
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

preProcessFeatureFlags() runs before the try/finally; if it throws (e.g., unreadable file/dir) the process exits without restoring any already-modified source files. Move the pre-processing call inside the try and ensure restoreModifiedFiles() runs in a finally that covers both pre-processing and Bun.build().

Suggested change
preProcessFeatureFlags(join(import.meta.dir, '..', 'src'))
const numModified = modifiedFiles.size
try {
let numModified = 0
try {
preProcessFeatureFlags(join(import.meta.dir, '..', 'src'))
numModified = modifiedFiles.size

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +87
// Clamp to configured bounds — max takes precedence over min
const minSleep = typeof settings.minSleepDurationMs === 'number'
? settings.minSleepDurationMs
: 0
const maxSleep = typeof settings.maxSleepDurationMs === 'number'
? settings.maxSleepDurationMs
: 5 * 60 * 1000 // 5 minutes default cap

duration_ms = Math.max(duration_ms, minSleep)
if (maxSleep >= 0) {
duration_ms = Math.min(duration_ms, maxSleep)
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

settings.maxSleepDurationMs is documented as allowing -1 for “indefinite sleep (waits for user input)”, but the tool never special-cases maxSleep === -1; it just removes the cap and still uses setTimeout(duration_ms). Consider implementing an abort-signal-only wait when maxSleepDurationMs is -1 (and/or guarding against extremely large duration_ms causing setTimeout overflow).

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +113
const timer = setTimeout(resolve, duration_ms)
const abortController = (context as { abortController?: AbortController }).abortController

if (!abortController) return

if (abortController.signal.aborted) {
clearTimeout(timer)
resolve()
return
}

let cleanupTimer: ReturnType<typeof setTimeout> | undefined
const onAbort = () => {
clearTimeout(timer)
if (cleanupTimer !== undefined) clearTimeout(cleanupTimer)
resolve()
}
abortController.signal.addEventListener('abort', onAbort, { once: true })
// Clean up listener on normal completion to avoid leak
cleanupTimer = setTimeout(() => {
abortController.signal.removeEventListener('abort', onAbort)
}, duration_ms + 1)
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

The abort listener cleanup uses a second setTimeout(duration_ms + 1) to removeEventListener, which schedules an extra timer per sleep and can keep the listener around until that timer fires. Prefer removing the listener in the main timer completion path (and in onAbort) instead of creating a cleanupTimer.

Suggested change
const timer = setTimeout(resolve, duration_ms)
const abortController = (context as { abortController?: AbortController }).abortController
if (!abortController) return
if (abortController.signal.aborted) {
clearTimeout(timer)
resolve()
return
}
let cleanupTimer: ReturnType<typeof setTimeout> | undefined
const onAbort = () => {
clearTimeout(timer)
if (cleanupTimer !== undefined) clearTimeout(cleanupTimer)
resolve()
}
abortController.signal.addEventListener('abort', onAbort, { once: true })
// Clean up listener on normal completion to avoid leak
cleanupTimer = setTimeout(() => {
abortController.signal.removeEventListener('abort', onAbort)
}, duration_ms + 1)
const abortController = (context as { abortController?: AbortController }).abortController
let settled = false
let onAbort: (() => void) | undefined
const finish = () => {
if (settled) return
settled = true
if (abortController && onAbort) {
abortController.signal.removeEventListener('abort', onAbort)
}
resolve()
}
const timer = setTimeout(() => {
finish()
}, duration_ms)
if (!abortController) return
if (abortController.signal.aborted) {
clearTimeout(timer)
finish()
return
}
onAbort = () => {
clearTimeout(timer)
finish()
}
abortController.signal.addEventListener('abort', onAbort, { once: true })

Copilot uses AI. Check for mistakes.
Comment thread src/proactive/index.ts
Comment on lines +9 to +11
* returning safe "off" defaults is sufficient. A full implementation would
* fire periodic <tick> prompts; this stub keeps the mode permanently off
* while satisfying the API contract.
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

The header comment says this stub keeps proactive mode “permanently off”, but activateProactive()/deactivateProactive() do flip the _active flag and notify subscribers. Update the comment to match the actual behavior (e.g., “no tick scheduling” rather than “permanently off”).

Suggested change
* returning safe "off" defaults is sufficient. A full implementation would
* fire periodic <tick> prompts; this stub keeps the mode permanently off
* while satisfying the API contract.
* returning safe defaults is sufficient. A full implementation would
* fire periodic <tick> prompts; this stub preserves the API's state-change
* behavior but does not schedule or emit proactive ticks.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +37
const assistant = {
type: 'local-jsx' as const,
name: 'assistant',
description: 'Toggle assistant mode',
isEnabled: () => true,
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

This command is described as “Toggle assistant mode”, but it only reports status and instructs the user to edit settings.json + restart. Update the command description/header to reflect that it’s a status/help command (or implement actual toggling if that’s intended).

Copilot uses AI. Check for mistakes.
@Flo5k5 Flo5k5 marked this pull request as draft April 13, 2026 10:04
@Flo5k5 Flo5k5 force-pushed the feat/kairos-assistant-mode branch from 4f18fd5 to 5a16225 Compare April 13, 2026 14:03
Flo5k5 added 4 commits April 13, 2026 20:13
…wb#668)

Replace Anthropic-internal refusal text in CYBER_RISK_INSTRUCTION with
positive guidance for security testing, red teaming, and CTF. Simplify
FileReadTool mitigation logic (always include, no conditional check).
…awb#637, Gitlawb#644)

Consolidates PRs Gitlawb#637 and Gitlawb#644:
- Remove ~45 dead USER_TYPE=ant guards across 28+ files (-1200 lines)
- Open 13 useful features to all users (agent nesting, effort persistence,
  plan mode interview, sandbox config, tips visibility)
- Key: src/constants/tools.ts — unlocks recursive agent spawning
Consolidates PRs Gitlawb#667 and Gitlawb#633:
- Activate 18 build-time flags: KAIROS, BRIDGE_MODE, AGENT_TRIGGERS,
  ULTRATHINK, TOKEN_BUDGET, HISTORY_PICKER, EXTRACT_MEMORIES, etc.
- Add _openBuildDefaults in GrowthBook stub for runtime gate overrides:
  bridge flags (tengu_ccr_bridge, tengu_bridge_repl_v2),
  KAIROS flags (tengu_kairos, tengu_kairos_brief),
  feature flags (AWAY_SUMMARY, VERIFICATION_AGENT, EXTRACT_MEMORIES)
- Priority: ~/.claude/feature-flags.json > _openBuildDefaults > defaultValue
Minimal changes to 3 bridge files for local bridge server support:
- bridgeEnabled.ts: bypass OAuth subscriber check (local bridge needs
  no subscription), let _openBuildDefaults control runtime gates
- bridgeConfig.ts: add localhost:4080 fallback + default token
- initReplBridge.ts: skip org policy check when using token override
@Flo5k5 Flo5k5 force-pushed the feat/kairos-assistant-mode branch from 5a16225 to 613c752 Compare April 13, 2026 18:14
@Flo5k5 Flo5k5 changed the title feat: KAIROS assistant mode — infrastructure, commands, and tools feat: consolidated open build — KAIROS, bridge, cleanup, feature flags, security Apr 13, 2026
Flo5k5 added 4 commits April 13, 2026 20:18
Replace the proprietary @ant/claude-for-chrome-mcp stub with a local
MCP server package enabling Chrome browser automation via the extension.

Package (packages/openclaude-for-chrome-mcp/):
- 17 browser tool definitions with full MCP schemas
- Unix socket client with lazy connection and backpressure-safe writes
- MCP server factory using @modelcontextprotocol/sdk
- Socket protocol types (4-byte LE + JSON)

Build integration:
- onResolve redirects openclaude-for-chrome-mcp to local package
- Import renames across 4 consumer files
The build system's scanForMissingImports scans for require() calls using
a regex that matches inside comments too. Documented import paths like:

  * const X = require('./commands/proactive.js').default;

were resolved from the WRONG directory (the file containing the comment,
not the actual importer), marked as missing, then the global onResolve
handler intercepted ALL imports of that specifier — including the valid
ones. This caused 6 KAIROS modules to be replaced with truthy noop stubs,
breaking the TUI input.

Also fixes: assistant/index.ts imported from ../utils/state.js (doesn't
exist) instead of ../utils/cwd.js.
The scanForMissingImports regex matched require() and import() patterns
inside JSDoc comments, causing false-positive missing module detection.
A documented path like `require('./commands/proactive.js')` in a comment
was resolved from the wrong directory, marked as missing, then the global
onResolve handler intercepted ALL imports of that specifier — including
valid ones — replacing them with truthy noop stubs that broke runtime.

Strip block (/* */) and line (//) comments from source before scanning.
- promptIdentity.test.ts: define MACRO global (ISSUES_EXPLAINER etc.)
  for test mode where Bun.define build-time replacements aren't active
- context.test.ts: clear OPENAI_MODEL env var in each test — the user's
  environment (e.g. OPENAI_MODEL=github_copilot/gpt-5.4) polluted the
  provider-qualified lookup, returning wrong context windows
- openclaudePaths.test.ts: set CLAUDE_CONFIG_DIR to force .openclaude
  path when ~/.openclaude doesn't exist on the test machine
@Flo5k5 Flo5k5 force-pushed the feat/kairos-assistant-mode branch from 1e05dcc to 2640d88 Compare April 13, 2026 21:40
Flo5k5 added 8 commits April 13, 2026 23:48
The build system's noop stub for missing modules only exports `default`,
not named exports. When KAIROS=true, initBundledSkills() destructures
`{ registerDreamSkill }` from the dream.js stub, getting `undefined`.
Calling `undefined()` throws a silent TypeError that breaks the Ink
render loop, freezing the TUI input.

Fix: add src/skills/bundled/dream.ts with a no-op registerDreamSkill().
Also removes debug breadcrumbs from main.tsx and index.ts.
Implement the missing modules that prevented 3 feature flags from activating:

TRANSCRIPT_CLASSIFIER (auto-approval classifier):
- Add VerifyPlanExecutionTool/constants.ts (tool name string)
- Add open-source classifier prompt templates (auto_mode_system_prompt.txt,
  permissions_external.txt) for the existing yoloClassifier.ts (1600 lines)

FORK_SUBAGENT (implicit context-forking):
- Add /fork command (delegates to existing forkSubagent.ts via Agent tool)
- Add UserForkBoilerplateMessage.tsx (renders fork-boilerplate XML tags)

MCP_SKILLS (skill discovery from MCP resources):
- Add mcpSkills.ts: fetchMcpSkillsForClient() discovers skills from MCP
  server resources (URI scheme skill://, MIME skill, or .skill.md name)
- Converts to Commands via getMCPSkillBuilders() registry

CACHED_MICROCOMPACT remains disabled (requires Anthropic cache editing API).
The TUI displayed `https://claude.ai/code/session_*` when connected to
the local bridge server, instead of the actual `http://localhost:4080`.
Two coupled bugs caused this:

1. `getBridgeBaseUrl()` had a dead localhost fallback — `getOauthConfig()
   .BASE_API_URL` always returns `https://api.anthropic.com`, so the
   `'http://localhost:4080'` fallback was never reached.

2. `CLAUDE_AI_LOCAL_BASE_URL` is hardcoded to `:4000` (the upstream
   Anthropic dev frontend port), but the open-build bridge server runs
   on `:4080`.

Decouple bridge config from the LLM provider — in this fork they are
independent, so a user with Anthropic OAuth tokens (for inference) must
still target the local bridge by default. `getClaudeAiBaseUrl()` now
derives the origin from the actual `ingressUrl` for localhost sessions.

Defense-in-depth: `createSession.ts` (v1 path, currently inactive in the
fork) gets the same fallback fix in case `tengu_bridge_repl_v2` is
flipped off. BLOCKER comments document the remaining `getOrganization
UUID()` blocker for fully unblocking the open-build v1 path.
Make isClaudeAISubscriber() return true when Anthropic auth is not enabled,
so subscription-gated features (Chrome extension, Remote Control, Brief)
work with local providers. The underlying infrastructure is local:
- Bridge runs on localhost:4080 (no OAuth needed)
- Chrome MCP uses packages/openclaude-for-chrome-mcp
- OpenAI-compatible endpoints replace the Anthropic API

Fixes: "Claude in Chrome requires a claude.ai subscription" error when
using the /chrome command or the chrome extension notification popup.
…tension

The MCP server exposes tools as 'tabs_context_mcp' and 'tabs_create_mcp'
(with suffix) to Claude, matching the names in prompts, skills, and tool
rendering throughout the codebase. However, the Chrome extension's native
messaging handler expects bare method names (e.g. 'tabs_context') and
returns "Unknown method" otherwise.

Strip the _mcp suffix at the transport layer so Claude-facing names stay
consistent while extension-facing names match what the extension accepts.
The Anthropic internal build outputs cli.js; our open build uses Bun to
produce cli.mjs (ESM). The wrapper script installed as the Chrome
NativeMessagingHost pointed to cli.js which doesn't exist, causing Chrome
to fall back to the Claude Desktop native host (which doesn't recognize
openclaude's MCP method names) and return "Unknown method: tabs_context".

Users who ran /chrome in a previous session need to re-run setup to
regenerate ~/.claude/chrome/chrome-native-host with the corrected path.
The previous commit (60812d5) defaulted `getBridgeBaseUrl()` to
localhost:4080 unconditionally, which broke /remote-control for users on
the Anthropic provider (OAuth or API key) — they expect to reach the
production bridge at api.anthropic.com, not a local server.

Route by provider instead:
- Anthropic provider (firstParty + api.anthropic.com) → Anthropic bridge
  with the user's OAuth tokens.
- Any other provider (OpenAI, Gemini, Ollama, Bedrock, Vertex…) → local
  bridge at localhost:4080 with the 'openclaude-local-bridge' token.

When the local bridge is targeted but the server is not running, the
user was seeing "Session creation failed — see debug log". Now
createCodeSession / fetchRemoteCredentials throw a typed
BridgeConnectionRefusedError on ECONNREFUSED/ECONNRESET; remoteBridgeCore
catches it and surfaces an actionable message:

  Local bridge server is not running at http://localhost:4080.
  Start it with: bun run packages/bridge-server/index.ts
The Chrome extension service worker (fcoeoabgfenejglbffodgkkbkcdhcgfn v1.0.68)
dispatches tool_request messages based on method name. Reverse-engineering
the service-worker.js shows it only handles method === 'execute_tool':

  switch (message.type) {
    case 'tool_request':
      if (params.method === 'execute_tool') {
        // Dispatch using params.tool, params.args, params.client_id
      } else {
        return { content: `Unknown method: ${method}` }
      }
  }

Our native host was forwarding the raw tool name as the top-level method,
causing "Unknown method: tabs_context_mcp" from the extension.

Fix: native host wraps each tool_request in execute_tool envelope with
the actual tool name in params.tool. Also revert the _mcp suffix stripping
since the extension accepts the full name (with suffix) as a tool name.

Verified against extension service worker at
~/Library/Application Support/Google/Chrome/Default/Extensions/
  fcoeoabgfenejglbffodgkkbkcdhcgfn/1.0.68_0/assets/service-worker.ts-*.js
Copy link
Copy Markdown
Collaborator

@Vasanthdev2004 Vasanthdev2004 left a comment

Choose a reason for hiding this comment

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

Review: PR #660 — Consolidated open build: KAIROS, bridge, cleanup, feature flags, security (head 01e875a)

CI green ✅. 93 files, +3661/-1031.

Assessment

This PR consolidates 5 previously separate PRs (#633, #637, #644, #667, #668) plus new KAIROS/bridge work. I previously approved #637 and #644, and requested changes on #667 and #668.

✅ What's improved from the sub-PRs

Feature flag runtime gates (#667 concern — partially addressed):
The _openBuildDefaults layer in the GrowthBook stub now provides a 3-tier priority: ~/.claude/feature-flags.json > _openBuildDefaults > defaultValue. This means EXTRACT_MEMORIES (via tengu_passport_quail) will be enabled in the open build even if the GrowthBook default is false. Tests cover this. ✅

Bridge server auth:
The bridge server properly authenticates requests with JWT + Bearer token. Worker endpoints have separate auth. This is well-designed. ✅

🔴 Still-blocked concerns from #668

Security guidance still removes authorization/scope gating:

// Before (#668):
"Assist with authorized security testing... Refuse requests for destructive techniques, DoS attacks, mass targeting..."

// After (this PR):
"Assist with security testing... Dual-use security tools can be used in pentesting engagements, red team operations, CTF..."

Two problems remain:

  1. "authorized" was removed — This removes the expectation that the user has clear authorization context. Without it, the guidance provides no basis to distinguish a red team engagement from an unauthenticated attack.
  2. The refusal clause was removed — "Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes" is gone. The replacement text implicitly allows these by omission.

I understand the open-build philosophy of not imposing Anthropic-internal refusal language. But the fix should be to replace the Anthropic-specific refusal with open-build-appropriate safety guidance (e.g., "Exercise caution with techniques that could cause harm without clear authorization context"), not to remove all safety gating.


🟡 Non-blocking (from Copilot review + my observations)

  1. preProcessFeatureFlags() runs before try/finally — if it throws, modified source files aren't restored. Move inside the try block.
  2. SleepTool -1 indefinite sleep — documented but not implemented; maxSleep === -1 just removes the cap instead of waiting for user input.
  3. Abort listener cleanup — extra setTimeout(duration_ms + 1) creates unnecessary timer. Prefer once event or AbortSignal.timeout().
  4. activateProactive() comment mismatch — comment says "permanently off" but code toggles _active.
  5. /assistant command description — says "Toggle" but only reports status + instructs manual edit.

New KAIROS/bridge additions

  • src/assistant/ — Gate, API, session discovery stub. Reasonable skeleton. ✅
  • src/proactive/ — No-op stubs. Clean. ✅
  • src/tools/SleepTool/ — Interruptible sleep. Good concept, minor issues noted above.
  • Bridge server — Auth, SSE, session management. Well-structured. ✅

Verdict: Needs changes 🔧

The _openBuildDefaults fix addresses the #667 runtime gate concern. But the #668 security guidance concern remains: removing both "authorized" and the refusal clause creates a blanket green light for dual-use tools without authorization context. Please restore authorization-aware language appropriate for the open build.

@Darkatek7
Copy link
Copy Markdown

I opened a focused follow-up PR with the review-unblock fixes here:

Scope:

  1. move preProcessFeatureFlags() inside try in scripts/build.ts so restore always runs
  2. restore authorization-aware safety wording in src/constants/cyberRiskInstruction.ts
  3. fix SleepTool so maxSleepDurationMs = -1 behaves as interrupt-only sleep and simplify abort cleanup
  4. update the proactive stub comment to match behavior
  5. change /assistant wording from “toggle” to status/help wording

Verification on the follow-up branch:

  • bun install
  • bun run build
  • bun test still has broader pre-existing failures on the PR branch, so I kept scope to the review fixes only

If it helps, the patch can also be cherry-picked from commit 6ab8b5a (fix: address PR 660 review feedback).

@jatmn
Copy link
Copy Markdown
Collaborator

jatmn commented May 13, 2026

closing as stale, please feel free to re-open later with more focused PR's this one currently spiders out far too broadly

@jatmn jatmn closed this May 13, 2026
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.

5 participants