CODING AGENT HARNESS · SOURCE AUDITREPORT 13 / 18
13

JCode

恢复、memory 与 swarm 设计非常激进;安全边界偏应用层,默认没有 OS 沙箱。

TypeScript · Recoverable Memory + Swarm AgentMITmaster
SOURCE
VERIFIED
Repository
1jehuang/jcode
Commit
119301ac9d605fc4c50e88dc347a783901e54b73
Commit date
2026-07-27T18:36:20-07:00
Findings
30
Citations
78
Tracked files
1,738
EXECUTIVE READING

先给结论,再进入源码

核心机制

先写盘;断流撤销半截再重播;多类止损上限

上下文

prefix/tail 缓存;cursor compact;三策略压缩;后台 memory

安全边界

session allow/disable + external gate;危险命令拒绝;无 OS sandbox

适用建设

研究型自研 Harness、复杂 swarm、长期记忆

值得借鉴

  • 断流恢复细
  • memory/压缩策略完整
  • swarm DAG 治理先进

需要警惕

  • 无 OS 沙箱
  • 系统复杂度和状态空间大
  • 外部 gate 是部署依赖

直接带走

  • journal 损坏自愈
  • 前缀游标压缩
  • artifact + audit swarm gate
00 · METHOD

研究口径:先锁提交,再沿运行链读代码

README POLICY

README 只作入口;结论来自 Rust 主循环、Provider trait/runtime、compaction/memory、tool registry、bash/MCP、Swarm server、prompt/skill/hook、session journal、telemetry 与对应测试。

FACT POLICY

区分内建策略闸门与 OS 级隔离,区分普通串行工具循环与显式 batch 并发,区分轻量 swarm 与 deep DAG workflow。

INFERENCE POLICY

不推断第三方模型服务内部实现;对后台命令、匿名遥测和赞助商工具发现按代码中的默认值、退出条件与 opt-out 边界陈述。

L1运行实现
L2接口契约
L3测试证明
L4文档佐证
L5明确推断

本页引用 32 个不同源码/测试文件;证据角色分布:实现 55 · 测试 9 · 配置 2 · 契约 8 · 迁移 1 · Prompt 3。代码块是固定提交中的原文截取,长区间仅在中部折叠,首尾行号保持真实。

01 · TECHNICAL MAPS

架构总图与单轮执行链路

两张图均由本页证据账本生成,并通过 Archify showcase 9 项校验(0 error / 0 warning)。图可单独打开、搜索、缩放和追踪关系。

FIGURE 01JCode Harness 架构图全屏打开 ↗
FIGURE 02用户输入到工具回写的技术链路全屏打开 ↗
02 · COVERAGE MAP

审计维度与证据等级

架构与 Agent Loop verified L1 / L2 / L3

持久化入口、流事件状态机、重试回滚、空响应/上下文恢复与 soft interrupt。

Provider、流式与重试 verified L1 / L2 / L3

统一 Provider、MultiProvider 路由、认证/模型切换、provider-native tool/compaction。

上下文、压缩与记忆 verified L1 / L2 / L3

cache-aware prompt、三种压缩策略、紧急恢复、后台跨会话 memory agent。

工具与执行 verified L1 / L2 / L3

typed registry、工具快照、batch、输出预算、前后台命令和 stdin。

安全与沙箱 verified L1 / L2 / L3

allowed/disabled tools、pre_tool hook、危险命令 gate;未发现默认 OS 容器/系统沙箱。

MCP 与连接器 verified L1 / L2 / L3

shared pool/per-session client、stdio JSON-RPC、schema late registration、按需连接。

指令、Skills 与 Hooks verified L1 / L2 / L3

AGENTS.md、overlay、preferred-tools、跨工具 skills、lifecycle hooks、自开发模式。

Swarm 与协作 verified L1 / L2 / L3

轻 fan-out、持久 Swarm、deep DAG/gates/artifacts、消息/频道、崩溃回收。

持久化、观测与成熟度 verified L1 / L2 / L3

snapshot+JSONL、损坏恢复、事件日志/metrics/opt-out telemetry、MIT。

01
DIMENSION · ARCHITECTURE-LOOP

架构与 Agent Loop

本章共 4 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

01
L1事实jcode-loop-001

每个用户 turn 先写盘,再进入可恢复的流式循环

源码事实

run_once/run_once_capture 先把用户消息加入 Session 并 save,再调用 run_turn;远程流入口还先注入跨 Agent 通知、图片和本轮 system reminder,并在 turn 前后触发 observer hooks。

白话解释

模型还没开口,用户输入已经落账;即使后面 API 或工具出错,恢复时也不会连问题本身都丢掉。

对自研 Harness 的含义

耐崩溃性强,但每轮和工具结果频繁保存会增加本地 I/O,需要 journal 快路径配合。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_execution.rs · L4–L35
    4  impl Agent {
    5      /// Run a single turn with the given user message
    6      pub async fn run_once(&mut self, user_message: &str) -> Result<()> {
    7          self.add_message(
    8              Role::User,
    9              vec![ContentBlock::Text {
   10                  text: user_message.to_string(),
   11                  cache_control: None,
   12              }],
   13          );
   14          self.session.save()?;
   15          if trace_enabled() {
   16              eprintln!("[trace] session_id {}", self.session.id);
   17          }
   18          let _ = self.run_turn(true).await?;
   19          Ok(())
   20      }
   21  
   22      pub async fn run_once_capture(&mut self, user_message: &str) -> Result<String> {
   23          self.add_message(
   24              Role::User,
   25              vec![ContentBlock::Text {
   26                  text: user_message.to_string(),
   27                  cache_control: None,
   28              }],
   29          );
   30          self.session.save()?;
   31          if trace_enabled() {
   32              eprintln!("[trace] session_id {}", self.session.id);
   33          }
   34          self.run_turn(false).await
   35      }
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_execution.rs:4–35 run_once/capture 先 append+save。
  • 实现 crates/jcode-app-core/src/agent/turn_execution.rs:37–90 通知、图片、reminder 与 turn hooks。
02
L1事实jcode-loop-002

循环在每次请求前修复工具配对并重建稳定快照

源码事实

run_turn 注册 streaming/cancel guard;每圈先补齐缺失 tool outputs,再取得可能已压缩的 provider messages,锁定 tool definitions,取上一轮准备好的 memory,并构造静态/动态分离的 prompt。

白话解释

每次再问模型前先查账:工具有没有开单不回执、旧历史是否已折叠、这一轮工具箱和提示词是否稳定。

对自研 Harness 的含义

把异常历史修复、缓存稳定和请求生命周期放在一个明确关口。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_loops.rs · L17–L68
   17      pub(super) async fn run_turn(&mut self, print_output: bool) -> Result<String> {
   18          self.set_log_context();
   19          crate::session_metrics::record_turn(&self.session.id);
   20          // Mark this session as actively streaming for presence UIs (e.g. the
   21          // macOS menu bar indicator). Cleared automatically on every exit path.
   22          let _streaming_guard = crate::session::StreamingGuard::new(self.session.id.clone());
   23          // Register this turn's cancel signal so session-level cancels reach
   24          // this in-flight turn even through stale control handles (issue #428).
   25          let _turn_cancel_guard = crate::turn_cancel_registry::register_active_turn(
   26              &self.session.id,
   27              self.graceful_shutdown.clone(),
   28          );
   29          let mut final_text = String::new();
   30          let trace = trace_enabled();
   31          let mut context_limit_retries = 0u32;
   32          let mut incomplete_continuations = 0u32;
   33          let mut empty_post_tool_continuations = 0u32;
   34  
   35          loop {
   36              let repaired = self.repair_missing_tool_outputs();
   37              if repaired > 0 {
   38                  logging::warn(&format!(
   39                      "Recovered {} missing tool output(s) before API call",
   40                      repaired
      … 18 lines omitted; exact range 17–68 …
   59              }
   60  
   61              let tools = self.tool_definitions().await;
   62              let messages: std::sync::Arc<[Message]> = messages.into();
   63              // Non-blocking memory: uses pending result from last turn, spawns check for next turn
   64              let memory_pending =
   65                  self.build_memory_prompt_nonblocking_shared(std::sync::Arc::clone(&messages), None);
   66              // Use split prompt for better caching - static content cached, dynamic not
   67              let split_prompt = self.build_system_prompt_split(None);
   68              self.log_prompt_prefix_accounting(&split_prompt, &tools);
查看全部 1 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:17–68 guard、repair、compaction、tools、memory、split prompt。
03
L1事实jcode-loop-003

中途断流先撤销半截状态再完整重播

源码事实

Provider 发出 RetryRollback 后,Agent 清空该次尝试的文本、tool calls、SDK results、reasoning 与 native compaction;Copilot runtime 仅在已向消费者发过可见输出且错误可重试时发送该事件。

白话解释

网络半路断了,不把前半句和前半个工具调用留在账上;先橡皮擦掉,再从头重放。

对自研 Harness 的含义

显著降低重试导致的重复文本和重复副作用;普通 stdout 无法擦除,只会显示断点标记。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_loops.rs · L455–L484
  455                      StreamEvent::RetryRollback { attempt, max } => {
  456                          // Transient transport fault mid-stream; the provider is
  457                          // replaying the request. Discard this attempt's partial
  458                          // output so the replay doesn't duplicate it in history.
  459                          logging::warn(&format!(
  460                              "Mid-stream retry rollback (attempt {}/{}): discarding partial output ({} text chars, {} tool calls)",
  461                              attempt,
  462                              max,
  463                              text_content.len(),
  464                              tool_calls.len(),
  465                          ));
  466                          if print_output && !text_content.is_empty() {
  467                              // Already-printed text can't be unprinted on a plain
  468                              // stdout stream; mark the discontinuity instead.
  469                              println!("\n[connection interrupted, retrying response from the top]");
  470                              io::stdout().flush()?;
  471                          }
  472                          text_content.clear();
  473                          tool_calls.clear();
  474                          current_tool = None;
  475                          current_tool_input.clear();
  476                          sdk_tool_results.clear();
  477                          generated_image_contexts.clear();
  478                          reasoning_content.clear();
  479                          reasoning_signature.clear();
  480                          openai_reasoning_items.clear();
  481                          openai_native_compaction = None;
  482                          saw_message_end = false;
  483                          stop_reason = None;
  484                      }
查看全部 3 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:455–484 消费者回滚所有 partial state。
  • 实现 crates/jcode-provider-copilot-runtime/src/lib.rs:615–659 provider 追踪是否已输出并条件发 rollback。
  • 测试 crates/jcode-provider-openrouter-runtime/src/openrouter_tests.rs:2629–2718 mid-stream fault 必须先 rollback 再 replay。
04
L1事实jcode-loop-004

上下文、截断回复和工具后空回复各有独立止损上限

源码事实

上下文自动压缩重试最多 5 次,不完整回复 continuation 最多 3 次,工具结果后的空白 final 最多 5 次;工具后空白会写入一条明确要求给 final answer 的 user message。

白话解释

不同故障不共用一个模糊的“最多重试 N 次”:箱子装不下、回答被截断、工具后失语分别计数。

对自研 Harness 的含义

长任务韧性好,也避免无限循环;自动补写的 user message会成为真实历史。

关键源码 · 配置
crates/jcode-app-core/src/agent/turn_loops.rs · L5–L15
    5      /// Run turns until no more tool calls
    6      /// Maximum number of context-limit compaction retries before giving up.
    7      pub(super) const MAX_CONTEXT_LIMIT_RETRIES: u32 = 5;
    8      pub(super) const MAX_INCOMPLETE_CONTINUATION_ATTEMPTS: u32 = 3;
    9      /// Retries allowed when the provider returns an empty response right after
   10      /// tool results. This is a transient provider hiccup, not a signal that the
   11      /// task is finished, so a single retry is too few: one empty response
   12      /// observed once in 43 turns silently ended a 20-hour benchmark run with the
   13      /// task half-done. The counter is per turn-loop, so a genuinely finished
   14      /// agent still exits promptly.
   15      pub(crate) const MAX_EMPTY_POST_TOOL_CONTINUATION_ATTEMPTS: u32 = 5;
查看全部 2 处证据
  • 配置 crates/jcode-app-core/src/agent/turn_loops.rs:5–15 三类 retry budget。
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:798–825 tool-result 后空白 continuation。
02
DIMENSION · PROVIDER-STREAMING

Provider、流式与重试

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

05
L2事实jcode-provider-001

Provider 契约不仅抽象生成,还抽象认证、路由、transport 与原生能力

源码事实

Provider trait 提供 complete/complete_split、模型/route/effort/tier/transport 切换、认证解析、context window、fork、native tool result sender 和 native compaction;fork 明确要求独立可变状态。

白话解释

它不是只把 URL 换掉;连“谁付费、用哪条线路、能不能续上服务端会话、工具由谁执行、压缩由谁做”都在同一接口里。

对自研 Harness 的含义

多后端能力完整,但 trait 面积很大,新 Provider 的一致性测试成本高。

关键源码 · 契约
crates/jcode-provider-core/src/lib.rs · L76–L126
   76  pub trait Provider: Send + Sync {
   77      /// Send messages and get a streaming response.
   78      /// resume_session_id: Optional session ID to resume a previous conversation (provider-specific).
   79      async fn complete(
   80          &self,
   81          messages: &[Message],
   82          tools: &[ToolDefinition],
   83          system: &str,
   84          resume_session_id: Option<&str>,
   85      ) -> Result<EventStream>;
   86  
   87      /// Send messages with split system prompt for better caching.
   88      async fn complete_split(
   89          &self,
   90          messages: &[Message],
   91          tools: &[ToolDefinition],
   92          system_static: &str,
   93          system_dynamic: &str,
   94          resume_session_id: Option<&str>,
   95      ) -> Result<EventStream> {
   96          let dynamic_messages = messages_with_dynamic_system_context(messages, system_dynamic);
   97          self.complete(&dynamic_messages, tools, system_static, resume_session_id)
   98              .await
   99      }
      … 17 lines omitted; exact range 76–126 …
  117      fn display_name(&self) -> String {
  118          self.name().to_string()
  119      }
  120  
  121      /// Get the model identifier being used.
  122      fn model(&self) -> String {
  123          "unknown".to_string()
  124      }
  125  
  126      /// Human-readable description of the auth method the active provider will
查看全部 2 处证据
  • 契约 crates/jcode-provider-core/src/lib.rs:76–126 生成、split prompt、身份和 auth 契约。
  • 契约 crates/jcode-provider-core/src/lib.rs:293–436 transport、tools、compaction、context、fork 与 native result。
06
L1事实jcode-provider-002

MultiProvider 同时容纳九类 runtime 与兼容端点 profile

源码事实

MultiProvider 持有 Claude CLI、Anthropic API、OpenAI、Copilot、Antigravity、Gemini、Cursor、Bedrock、OpenRouter,以及独立 keyed OpenAI-compatible profiles;active provider 可热切换。

白话解释

像一个总机:同一 Agent 可以接订阅 CLI、官方 API、Copilot、Gemini、Bedrock 或自定义兼容网关,并保留各自认证身份。

对自研 Harness 的含义

模型路由覆盖面极广;OpenRouter 槽位兼容多 profile,代码中有大量防止 profile 身份丢失的分支。

关键源码 · 实现
crates/jcode-base/src/provider/mod.rs · L328–L374
  328  /// MultiProvider wraps multiple providers and allows seamless model switching
  329  pub struct MultiProvider {
  330      /// Claude Code CLI provider
  331      claude: RwLock<Option<Arc<dyn Provider>>>,
  332      /// Direct Anthropic API provider (no Python dependency)
  333      anthropic: RwLock<Option<Arc<dyn Provider>>>,
  334      openai: RwLock<Option<Arc<dyn Provider>>>,
  335      /// GitHub Copilot API provider (direct API, hot-swappable after login).
  336      /// Held as `dyn Provider`: the concrete runtime lives downstream in
  337      /// `jcode-provider-copilot-runtime` and is instantiated through
  338      /// `external::instantiate_external_provider`.
  339      copilot_api: RwLock<Option<Arc<dyn Provider>>>,
  340      /// Antigravity provider (direct HTTPS, hot-swappable after login). Held as
  341      /// `dyn Provider`: the concrete runtime lives downstream in
  342      /// `jcode-provider-antigravity-runtime` and is instantiated through
  343      /// `external::instantiate_external_provider`.
  344      antigravity: RwLock<Option<Arc<dyn Provider>>>,
  345      /// Gemini provider (hot-swappable after login). Held as `dyn Provider`:
  346      /// the concrete runtime lives downstream in `jcode-provider-gemini-runtime`
  347      /// and is instantiated through `external::instantiate_external_provider`.
  348      gemini: RwLock<Option<Arc<dyn Provider>>>,
  349      /// Cursor provider (native/direct API, hot-swappable after login). Held as
  350      /// `dyn Provider`: the concrete runtime lives downstream in
  351      /// `jcode-provider-cursor-runtime` and is instantiated through
      … 13 lines omitted; exact range 328–374 …
  365      active_openai_compatible_profile: RwLock<Option<String>>,
  366      active: RwLock<ActiveProvider>,
  367      /// Use Claude CLI instead of direct API (legacy mode)
  368      use_claude_cli: bool,
  369      /// Notifications generated during provider/account auto-selection.
  370      /// The TUI should drain and display these on session start.
  371      startup_notices: RwLock<Vec<String>>,
  372      /// CLI/environment selection to use when creating fresh sessions. This is
  373      /// only an initial preference and never restricts later model switches.
  374      initial_provider: Option<ActiveProvider>,
查看全部 1 处证据
  • 实现 crates/jcode-base/src/provider/mod.rs:328–374 MultiProvider runtime slots 与 active state。
07
L1事实jcode-provider-003

服务端会话、原生工具和原生压缩都能穿过统一事件流

源码事实

StreamEvent::SessionId 会保存 provider resumable session;Compaction 可保存 OpenAI encrypted content;NativeToolCall 经本地 registry 执行后通过 provider native_result_sender 回传 SDK bridge。

白话解释

底层 Provider 可以说“以后用这个会话号续聊”“我已经压缩过了”或“替我本地跑这个工具”,上层都能接住。

对自研 Harness 的含义

兼容 provider-native agent runtime,而非强迫所有后端退化成纯文本 function calling。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_loops.rs · L485–L547
  485                      StreamEvent::MessageEnd {
  486                          stop_reason: reason,
  487                      } => {
  488                          saw_message_end = true;
  489                          if reason.is_some() {
  490                              stop_reason = reason;
  491                          }
  492                          // Don't break yet - wait for SessionId which comes after MessageEnd
  493                          // (but stream close will also end the loop for providers without SessionId)
  494                      }
  495                      StreamEvent::SessionId(sid) => {
  496                          if trace {
  497                              eprintln!("[trace] session_id {}", sid);
  498                          }
  499                          self.provider_session_id = Some(sid.clone());
  500                          self.session.provider_session_id = Some(sid);
  501                          // We've received session_id, can exit the loop now
  502                          if saw_message_end {
  503                              break;
  504                          }
  505                      }
  506                      StreamEvent::UpstreamProvider { provider } => {
  507                          // Log upstream provider for local trace output
  508                          if trace {
      … 29 lines omitted; exact range 485–547 …
  538                              let tokens_str = pre_tokens
  539                                  .map(|t| format!(" ({} tokens)", t))
  540                                  .unwrap_or_default();
  541                              crate::terminal_println!(
  542                                  "📦 Context compacted ({}){}",
  543                                  trigger,
  544                                  tokens_str
  545                              );
  546                          }
  547                      }
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:485–547 session id、reasoning 与 compaction event。
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:548–585 native tool 本地执行与回传。
03
DIMENSION · CONTEXT-COMPACTION-MEMORY

上下文、压缩与记忆

本章共 6 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

08
L1事实jcode-context-001

静态前缀与每轮动态上下文分离,memory 放尾部保缓存

源码事实

system prompt 把 base prompt、AGENTS、overlay、preferred-tools、skills 放 static_part;memory、active skill、reminder 与 swarm effort 放 dynamic_part。run_turn 在 client cache 检查后把 memory 作为末尾 user message注入。

白话解释

不常变的说明书放书脊,记忆和本轮提醒贴在最后一页;这样改便签不会让整本书的缓存失效。

对自研 Harness 的含义

明显以 prompt-cache economics 为一等设计目标。

关键源码 · 实现
crates/jcode-base/src/prompt.rs · L451–L557
  451  /// Build system prompt split into static (cacheable) and dynamic parts
  452  /// This improves cache hit rate by keeping frequently-changing content separate
  453  pub fn build_system_prompt_split(
  454      skill_prompt: Option<&str>,
  455      available_skills: &[SkillInfo],
  456      is_selfdev: bool,
  457      memory_prompt: Option<&str>,
  458      working_dir: Option<&Path>,
  459  ) -> (SplitSystemPrompt, ContextInfo) {
  460      build_system_prompt_split_with_capabilities(
  461          skill_prompt,
  462          available_skills,
  463          is_selfdev,
  464          memory_prompt,
  465          working_dir,
  466          PromptCapabilities::current(),
  467      )
  468  }
  469  
  470  pub fn build_system_prompt_split_with_capabilities(
  471      skill_prompt: Option<&str>,
  472      available_skills: &[SkillInfo],
  473      is_selfdev: bool,
  474      memory_prompt: Option<&str>,
      … 73 lines omitted; exact range 451–557 …
  548      info.total_chars = static_part.len() + dynamic_part.len();
  549  
  550      (
  551          SplitSystemPrompt {
  552              static_part,
  553              dynamic_part,
  554          },
  555          info,
  556      )
  557  }
查看全部 2 处证据
  • 实现 crates/jcode-base/src/prompt.rs:451–557 static/dynamic prompt 组成。
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:63–92 cache 检查后 suffix memory。
09
L1事实jcode-context-002

压缩器不复制历史,只记录被摘要的前缀游标

源码事实

CompactionManager 不拥有 messages,只存 compacted_count、active_summary、active suffix char estimate 与 pending background task;恢复旧会话时先抑制压缩,直到真正的新消息加入。

白话解释

原始账本仍归 Session 管,压缩器只记“前 N 条已折叠成摘要”,不会偷偷维护第二份容易漂移的历史。

对自研 Harness 的含义

所有权清楚且便于 rewind;游标、摘要和 session persistence 必须原子同步。

关键源码 · 实现
crates/jcode-base/src/compaction.rs · L128–L205
  128  /// Manages background compaction of conversation context.
  129  ///
  130  /// Does NOT own message data. The caller owns the messages and passes
  131  /// references into methods that need them. After compaction, the manager
  132  /// records `compacted_count` — the number of leading messages that have
  133  /// been summarized and should be skipped when building API payloads.
  134  pub struct CompactionManager {
  135      /// Number of leading messages that have been compacted into the summary.
  136      /// When building API messages, skip the first `compacted_count` messages.
  137      compacted_count: usize,
  138  
  139      /// Active summary (if we've compacted before)
  140      active_summary: Option<Summary>,
  141  
  142      /// Rolling char estimate for the active (non-compacted) message suffix.
  143      ///
  144      /// In the common append-only case this is maintained incrementally, so token
  145      /// estimation does not need to rescan the entire active history every time.
  146      /// Bundled with its own dirty flag so the value and staleness can never
  147      /// drift apart (see [`ActiveCharEstimate`]).
  148      active_chars: ActiveCharEstimate,
  149  
  150      /// Background compaction task handle
  151      pending_task: Option<JoinHandle<Result<CompactionResult>>>,
      … 44 lines omitted; exact range 128–205 …
  196      embedding_history: VecDeque<Vec<f32>>,
  197  
  198      /// Local cache for semantic compaction embeddings keyed by truncated-text hash.
  199      /// Stores both successful embeddings and failed lookups (`None`) so repeated
  200      /// semantic scans do not redo the same work.
  201      semantic_embed_cache: HashMap<u64, (Option<Vec<f32>>, u64)>,
  202  
  203      /// Monotonic recency counter for the semantic embedding cache LRU.
  204      semantic_embed_cache_counter: u64,
  205  }
查看全部 3 处证据
  • 实现 crates/jcode-base/src/compaction.rs:128–205 manager state 与 ownership。
  • 实现 crates/jcode-base/src/compaction.rs:283–345 restore suppression 与 persisted compaction。
  • 测试 crates/jcode-base/src/compaction_tests.rs:61–95 restore 不立即 compact,新消息才重新启用。
10
L1事实jcode-context-003

压缩支持 reactive、趋势预测和语义换题三种策略

源码事实

reactive 在固定阈值触发;proactive 用 token history 的 EWMA 增长投影;semantic 用 turn embeddings 检测 topic shift,无 embedding 时回退 proactive。统一 anti-signals 防止重复、过早、停滞期和 cooldown 内压缩。

白话解释

可以等箱子快满再整理,也可以看增长速度提前整理,还可以在话题换挡时整理;但都会先检查“现在整理是否值得”。

对自研 Harness 的含义

上下文策略比多数单摘要 Agent 丰富,语义模式依赖本地 embedding 可用性和阈值调优。

关键源码 · 实现
crates/jcode-base/src/compaction.rs · L456–L543
  456      // ── Anti-signal guard (shared by proactive + semantic) ──────────────────
  457  
  458      /// Returns `true` when any anti-signal fires and we should NOT compact
  459      /// proactively right now.
  460      ///
  461      /// Anti-signals are universal guards applied before the mode-specific
  462      /// trigger logic. They prevent wasted work and respect user intent.
  463      fn anti_signals_block(&self, all_messages: &[Message]) -> bool {
  464          let cfg = &self.compaction_config;
  465  
  466          // 1. Already compacting — never double-trigger.
  467          if self.pending_task.is_some() {
  468              return true;
  469          }
  470  
  471          // 2. Context below the proactive floor — too early regardless of trend.
  472          let usage = self.context_usage_with(all_messages);
  473          if usage < cfg.proactive_floor {
  474              return true;
  475          }
  476  
  477          // 3. Not enough token history to project from.
  478          if self.token_history.len() < cfg.min_samples {
  479              return true;
      … 54 lines omitted; exact range 456–543 …
  534              let delta = ((snapshots[i] as f64) - (snapshots[i - 1] as f64)).max(0.0);
  535              ewma_delta = alpha * delta + (1.0 - alpha) * ewma_delta;
  536          }
  537          let Some(current) = snapshots.last().copied().map(|value| value as f64) else {
  538              return false;
  539          };
  540          let projected = current + ewma_delta * cfg.lookahead_turns as f64;
  541  
  542          crate::logging::info(&format!(
  543              "[compaction/proactive] current={:.0} ewma_delta={:.1}/turn projected@{}turns={:.0} threshold={:.0}",
查看全部 2 处证据
  • 实现 crates/jcode-base/src/compaction.rs:456–543 anti-signals 与 EWMA proactive trigger。
  • 实现 crates/jcode-base/src/compaction.rs:552–605 semantic topic shift 与 fallback。
11
L1事实jcode-context-004

上下文溢出与请求体过大走不同紧急恢复路径

源码事实

context-limit error 触发同步 hard compact 并重置 cache/tool/provider session;HTTP 413 类 byte-size 错误先从持久历史剥离超大 inline images;超长 OpenAI encrypted compaction 则丢 native state 改文本 fallback。

白话解释

“字太多”“图片字节太大”“服务端压缩包本身太大”不是同一种病,分别治疗。

对自研 Harness 的含义

避免对 413 做无效 token 摘要;紧急路径会改写持久 transcript,报告需明确这是有损恢复。

关键源码 · 实现
crates/jcode-app-core/src/agent/compaction.rs · L90–L182
   90      fn is_context_limit_error(error: &str) -> bool {
   91          let lower = error.to_lowercase();
   92          lower.contains("context length")
   93              || lower.contains("context window")
   94              || lower.contains("maximum context")
   95              || lower.contains("max context")
   96              || lower.contains("token limit")
   97              || lower.contains("too many tokens")
   98              || lower.contains("prompt is too long")
   99              || lower.contains("input is too long")
  100              || lower.contains("request too large")
  101              || lower.contains("length limit")
  102              || lower.contains("maximum tokens")
  103              || (lower.contains("exceeded") && lower.contains("tokens"))
  104      }
  105  
  106      /// Best-effort emergency recovery after a context-limit error.
  107      ///
  108      /// Performs a synchronous hard compaction and resets provider session state,
  109      /// allowing the caller to retry the same turn immediately.
  110      pub(super) fn try_auto_compact_after_context_limit(&mut self, error: &str) -> bool {
  111          if crate::provider::openai_request::is_openai_encrypted_content_too_large_error(error)
  112              && self.try_recover_oversized_openai_native_compaction()
  113          {
      … 59 lines omitted; exact range 90–182 …
  173                  "context_limit_auto_compaction",
  174              )
  175              .with_session_id(self.session.id.clone())
  176              .with_detail(format!(
  177                  "dropped_messages={dropped},usage_pct={usage_pct:.1}"
  178              ))
  179              .force_attribution(),
  180          );
  181  
  182          true
查看全部 3 处证据
  • 实现 crates/jcode-app-core/src/agent/compaction.rs:90–182 context-limit hard compaction。
  • 实现 crates/jcode-app-core/src/agent/compaction.rs:185–241 413 image stripping。
  • 实现 crates/jcode-app-core/src/agent/compaction.rs:244–283 oversized native compaction fallback。
12
L1事实jcode-memory-001

跨会话 memory 是独立后台 Agent,不阻塞主 turn

源码事实

MemoryAgent 通过容量 16 的 channel 接收主 Agent context,使用 embedding 检索、Haiku/sidecar relevance judge 和 memory-only tools;结果放入 pending memory,下一次新 user turn 才消费。

白话解释

主 Agent 回答时,旁边有个只管记忆的小秘书;它来不及的结果不会卡住当前回答,而是下一轮再递纸条。

对自研 Harness 的含义

延迟低且职责隔离,但 memory freshness 天生滞后一轮,channel 满时 try_send 可能丢更新。

关键源码 · 实现
crates/jcode-base/src/memory_agent.rs · L1–L45
    1  //! Persistent Memory Agent
    2  //!
    3  //! A dedicated Haiku-powered agent for memory management that runs alongside
    4  //! the main agent. It has access to memory-specific tools only (no code execution).
    5  //!
    6  //! Architecture:
    7  //! - Receives context updates from main agent via channel
    8  //! - Uses embeddings for fast similarity search
    9  //! - Uses Haiku LLM to decide what's relevant and dig deeper
   10  //! - Surfaces relevant memories to main agent via PENDING_MEMORY
   11  
   12  use anyhow::Result;
   13  use chrono::Utc;
   14  use std::collections::{HashMap, HashSet};
   15  use std::sync::Arc;
   16  use std::sync::Mutex;
   17  use std::sync::atomic::{AtomicU64, Ordering};
   18  use std::time::Instant;
   19  use tokio::sync::mpsc;
   20  
   21  use crate::embedding;
   22  use crate::memory::{self, MemoryEntry, MemoryManager};
   23  use crate::memory_graph::{ClusterEntry, EdgeKind, MemoryGraph};
   24  use crate::memory_types::{MemoryEventKind, MemoryState, StepResult, StepStatus};
      … 11 lines omitted; exact range 1–45 …
   36  }
   37  
   38  /// Channel capacity for context updates
   39  const CONTEXT_CHANNEL_CAPACITY: usize = 16;
   40  
   41  /// Similarity threshold for topic change detection (lower = more different)
   42  const TOPIC_CHANGE_THRESHOLD: f32 = 0.3;
   43  
   44  /// Maximum memories to surface per turn
   45  const MAX_MEMORIES_PER_TURN: usize = 5;
查看全部 3 处证据
  • 实现 crates/jcode-base/src/memory_agent.rs:1–45 后台 memory agent 架构与 channel。
  • 实现 crates/jcode-base/src/memory_agent.rs:234–275 nonblocking handle 与 try_send。
  • 实现 crates/jcode-app-core/src/agent/prompting.rs:20–55 只在 fresh user turn 消费/更新。
13
L1事实jcode-memory-002

memory 分 project/global,带向量空间标识与重复抑制

源码事实

MemoryManager 按 working directory hash 存 project graph,也支持 global;embedding 写入 model id,避免跨向量空间比较。pending 注入按 prompt signature、memory set overlap 和 TTL 抑制重复,并把已从本会话抽取的 memory 标为 known。

白话解释

不同项目各有笔记本;换了 embedding 模型不会把两种坐标硬比。刚提过的记忆也不会每轮重复唠叨。

对自研 Harness 的含义

比单纯向量 top-k 多了去重与 provenance;路径 hash 迁移/重命名会形成新的 project memory scope。

关键源码 · 实现
crates/jcode-base/src/memory.rs · L159–L185
  159  trait MemoryEntryEmbeddingExt {
  160      fn ensure_embedding(&mut self) -> bool;
  161  }
  162  
  163  impl MemoryEntryEmbeddingExt for MemoryEntry {
  164      /// Generate and set embedding if not already present.
  165      /// Returns true if embedding was generated, false if already exists or failed.
  166      fn ensure_embedding(&mut self) -> bool {
  167          if self.embedding.is_some() {
  168              return false;
  169          }
  170  
  171          match crate::embedding_backend::embed_passage_active(&self.content) {
  172              Ok((embedding, model_id)) => {
  173                  // Tag with the ACTIVE backend's model id so dense search only
  174                  // compares vectors from the same model/vector space. Untagged
  175                  // legacy memories are treated as local MiniLM via
  176                  // effective_embedding_model().
  177                  self.set_embedding(Some(embedding), Some(model_id));
  178                  true
  179              }
  180              Err(err) => {
  181                  crate::logging::info(&format!("Failed to generate embedding: {err}"));
  182                  false
  183              }
  184          }
  185      }
查看全部 3 处证据
  • 实现 crates/jcode-base/src/memory.rs:159–185 embedding model id。
  • 实现 crates/jcode-base/src/memory.rs:248–275 working-dir hashed project storage。
  • 实现 crates/jcode-base/src/memory/pending.rs:129–174 prompt/set duplicate suppression。
04
DIMENSION · TOOLS-EXECUTION

工具与执行

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

14
L1事实jcode-tools-001

工具是 typed registry,定义顺序与 intent 字段集中标准化

源码事实

Tool trait 统一 name/description/JSON Schema/async execute;to_definition 集中给所有 object schema(含 MCP proxy)加入必填 intent。Registry 内建读写编辑、shell、浏览器、web、swarm、memory、goal、gmail、schedule、自开发等工具,并按名称排序 definitions。

白话解释

每件工具都交同一种说明书和回执;“为什么调用”不是每个工具自己记得就写,而是总装配线强制补上。

对自研 Harness 的含义

便于 UI 显示与审计,稳定排序提高 prompt cache hit。

关键源码 · 契约
crates/jcode-tool-core/src/lib.rs · L9–L65
    9  pub const TOOL_INTENT_DESCRIPTION: &str = concat!(
   10      "Short natural-language label explaining why this tool call is being made. ",
   11      "Used for compact UI display only. Required on every call; do not use this instead of required tool parameters."
   12  );
   13  
   14  pub fn intent_schema_property() -> Value {
   15      serde_json::json!({
   16          "type": "string",
   17          "description": TOOL_INTENT_DESCRIPTION,
   18      })
   19  }
   20  
   21  /// Ensure a tool parameter schema declares the shared `intent` property and
   22  /// marks it required. Applied centrally when converting tools to provider
   23  /// definitions so every tool (including MCP proxies) asks the model for an
   24  /// intent without each tool wiring it manually.
   25  pub fn ensure_intent_in_schema(mut schema: Value) -> Value {
   26      let Some(object) = schema.as_object_mut() else {
   27          return schema;
   28      };
   29      // Only touch object-shaped parameter schemas.
   30      let is_object_schema = object
   31          .get("type")
   32          .and_then(|t| t.as_str())
      … 23 lines omitted; exact range 9–65 …
   56          _ => {
   57              object.insert(
   58                  "required".to_string(),
   59                  Value::Array(vec![Value::String("intent".to_string())]),
   60              );
   61          }
   62      }
   63  
   64      schema
   65  }
查看全部 4 处证据
  • 契约 crates/jcode-tool-core/src/lib.rs:9–65 intent schema normalization。
  • 契约 crates/jcode-tool-core/src/lib.rs:75–139 ToolContext 与 Tool trait。
  • 实现 crates/jcode-app-core/src/tool/mod.rs:150–255 内建工具表。
  • 实现 crates/jcode-app-core/src/tool/mod.rs:318–341 allow filter、MCP key 与 deterministic sort。
15
L1事实jcode-tools-002

普通模型工具调用串行,显式 batch 最多并发十个

源码事实

run_turn 对 tool_calls 逐个 await registry.execute 并逐条持久化结果;BatchTool 禁止递归 batch,最多 10 个 subcalls,用 FuturesUnordered 并发执行、实时发布 progress,最终恢复原调用顺序。

白话解释

模型一次开几张普通工单时按顺序做;只有明确使用 batch 托盘,才会同时跑最多十件事。

对自研 Harness 的含义

默认副作用顺序可预测;性能并行需要模型主动选择 batch。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_loops.rs · L878–L917
  878              // Execute tools and add results
  879              let mut tool_results_dirty = false;
  880              for tc in tool_calls {
  881                  let message_id = assistant_message_id
  882                      .clone()
  883                      .unwrap_or_else(|| self.session.id.clone());
  884  
  885                  if let Some(error_msg) = tc.validation_error() {
  886                      logging::warn(&error_msg);
  887                      Bus::global().publish(BusEvent::ToolUpdated(ToolEvent {
  888                          session_id: self.session.id.clone(),
  889                          message_id: message_id.clone(),
  890                          tool_call_id: tc.id.clone(),
  891                          tool_name: tc.name.clone(),
  892                          status: ToolStatus::Error,
  893                          intent: tc.intent.clone(),
  894                          title: None,
  895                      }));
  896                      if print_output {
  897                          println!("\n  → {}", error_msg);
  898                      }
  899                      self.add_message(
  900                          Role::User,
  901                          vec![ContentBlock::ToolResult {
      … 6 lines omitted; exact range 878–917 …
  908                      continue;
  909                  }
  910  
  911                  self.validate_tool_allowed(&tc.name)?;
  912  
  913                  let is_native_tool = JCODE_NATIVE_TOOLS.contains(&tc.name.as_str());
  914  
  915                  // Check if SDK already executed this tool
  916                  if let Some((sdk_content, sdk_is_error)) = sdk_tool_results.remove(&tc.id) {
  917                      // For native tools, ignore SDK errors and execute locally
查看全部 3 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_loops.rs:878–917 普通 tool_calls 串行循环。
  • 实现 crates/jcode-app-core/src/tool/batch.rs:180–202 batch 输入、上限与禁止嵌套。
  • 实现 crates/jcode-app-core/src/tool/batch.rs:202–281 FuturesUnordered、progress 与顺序恢复。
16
L1事实jcode-tools-003

工具输出有双预算闸门,前台命令超时可升级后台

源码事实

Registry 在输出将超过 context 90% 或单个输出超过 budget 30% 时截断。Bash 默认前台 timeout 120s、上限 10 分钟;前台超时不会杀进程,而是把 JoinHandle 交给 background manager。显式后台模式按 timeout 杀整个 Unix process group 并写 output/status file。

白话解释

一份巨型日志不能吃掉整本上下文;长命令如果只是前台等不及,会转到后台继续,而显式后台设置的超时才负责杀进程组。

对自研 Harness 的含义

特别适合长 build/test;用户必须理解前台 timeout 是“停止等待”而不是“停止执行”。

关键源码 · 实现
crates/jcode-app-core/src/tool/mod.rs · L627–L678
  627          // Context overflow guard: check if this output would push us over the limit
  628          output = self.guard_context_overflow(name, output).await;
  629  
  630          let mut fields = Self::tool_lifecycle_fields("done", name, resolved_name, &input, &ctx);
  631          fields.push(("elapsed_ms".to_string(), latency_ms.to_string()));
  632          fields.push(("output_bytes".to_string(), output.output.len().to_string()));
  633          fields.push((
  634              "output_chars".to_string(),
  635              output.output.chars().count().to_string(),
  636          ));
  637          fields.push(("image_count".to_string(), output.images.len().to_string()));
  638          crate::logging::event_info("TOOL_LIFECYCLE", fields);
  639  
  640          Ok(output)
  641      }
  642  
  643      /// Check if a tool output would overflow the context window and truncate if needed.
  644      /// Returns the (possibly truncated) output.
  645      async fn guard_context_overflow(&self, tool_name: &str, output: ToolOutput) -> ToolOutput {
  646          let compaction = self.compaction.read().await;
  647          let budget = compaction.token_budget();
  648          if budget == 0 {
  649              return output;
  650          }
      … 18 lines omitted; exact range 627–678 …
  669          let remaining = if current_tokens < threshold_tokens {
  670              threshold_tokens - current_tokens
  671          } else {
  672              // Already over threshold — allow a small amount for the error message
  673              budget / 50 // ~2% of budget for the truncation notice
  674          };
  675          let max_tokens = remaining.min(single_max_tokens);
  676  
  677          // Convert token limit back to approximate character limit
  678          let max_chars = max_tokens * 4;
查看全部 4 处证据
  • 实现 crates/jcode-app-core/src/tool/mod.rs:627–678 90% context 与 30% single-output guard。
  • 实现 crates/jcode-app-core/src/tool/bash.rs:742–760 foreground timeout/cwd/process。
  • 实现 crates/jcode-app-core/src/tool/bash.rs:884–930 timeout promotion to background。
  • 实现 crates/jcode-app-core/src/tool/bash.rs:1095–1175 explicit background process-group timeout kill。
05
DIMENSION · SECURITY-SANDBOX

安全与沙箱

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

17
L1事实jcode-security-001

工具边界由 session allow/disable 与外部 pre_tool gate 双层控制

源码事实

Registry.execute 先解析 alias,再检查 session allowed_tools/disabled_tools;若配置 pre_tool hook,退出 2 阻止调用并把 stderr 反馈模型,其他非零、超时或启动失败均 fail-open。

白话解释

先看这把工具是否在本会话工具箱里,再给企业自定义门卫一次否决机会;门卫自己坏了时默认放行。

对自研 Harness 的含义

可扩展治理强,但 pre_tool 的 fail-open 语义不适合要求故障关闭的高风险环境。

关键源码 · 实现
crates/jcode-app-core/src/tool/mod.rs · L543–L601
  543      /// Execute a tool by name
  544      pub async fn execute(&self, name: &str, input: Value, ctx: ToolContext) -> Result<ToolOutput> {
  545          let tools = self.tools.read().await;
  546          let resolved_name = Self::resolve_tool_name(name);
  547          if let Some(policy) = session_tool_policy(&ctx.session_id) {
  548              if let Some(allowed) = policy.allowed_tools.as_ref()
  549                  && !allowed.contains(resolved_name)
  550              {
  551                  return Err(anyhow::anyhow!("Tool '{}' is not allowed", resolved_name));
  552              }
  553              if policy.disabled_tools.contains(resolved_name) {
  554                  return Err(anyhow::anyhow!("Tool '{}' is disabled", resolved_name));
  555              }
  556          }
  557          let tool = match tools.get(resolved_name) {
  558              Some(tool) => tool.clone(),
  559              None => {
  560                  // List available tools so the model can recover instead of
  561                  // spiraling through hallucinated names like "ToolSearch" (#104).
  562                  let mut available: Vec<&str> = tools.keys().map(|k| k.as_str()).collect();
  563                  available.sort_unstable();
  564                  let suggestions = Self::closest_tool_names(name, &available);
  565                  let mut msg = format!("Unknown tool: {name}.");
  566                  if !suggestions.is_empty() {
      … 25 lines omitted; exact range 543–601 …
  592              if let crate::hooks::GateDecision::Block { reason } = decision {
  593                  let mut fields =
  594                      Self::tool_lifecycle_fields("blocked", name, resolved_name, &input, &ctx);
  595                  fields.push(("block_reason".to_string(), reason.clone()));
  596                  crate::logging::event_warn("TOOL_LIFECYCLE", fields);
  597                  return Err(anyhow::anyhow!(
  598                      "Tool call blocked by pre_tool hook: {reason}"
  599                  ));
  600              }
  601          }
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/tool/mod.rs:543–601 session policy 与 pre_tool gate。
  • 契约 crates/jcode-base/src/hooks.rs:220–323 0 allow、2 block、其他 fail-open。
18
L1事实jcode-security-002

Bash 有确定性危险命令 gate,灾难目标直接拒绝

源码事实

所有前后台 Bash 在 dispatch 前调用 jcode_command_risk::assess/gate;普通危险命令要求模型带针对已拒绝调用的 justification 反思后再发,根目录、HOME、凭证库、设备节点等 catastrophic targets 直接 deny。

白话解释

不是让模型自己判断 rm 是否危险:命令先过代码规则;有些可解释后重试,有些目标永远不给过。

对自研 Harness 的含义

比纯提示词可靠,但命令解析器仍需要覆盖 shell 展开、别名、子 shell 和平台差异。

关键源码 · 实现
crates/jcode-app-core/src/tool/bash_destructive_gate.rs · L1–L39
    1  //! The destructive-command gate for the `bash` tool (issue #604).
    2  //!
    3  //! Kept in its own file so the policy seam is easy to find and review: this is
    4  //! the only thing standing between a model's `rm -rf` and the user's data.
    5  
    6  /// Apply the deterministic destructive-command gate, returning refusal text
    7  /// when the command must not run as-issued.
    8  ///
    9  /// Stage 1 is a pure blast-radius assessment; stage 2 turns a `Confirm` verdict
   10  /// into a reflection prompt that a blind retry cannot satisfy. Catastrophic
   11  /// targets (`/`, `$HOME`, credential stores, device nodes) are denied outright.
   12  /// See issue #604.
   13  pub(super) fn destructive_command_refusal(
   14      command: &str,
   15      justification: Option<&str>,
   16      working_dir: Option<std::path::PathBuf>,
   17  ) -> Option<String> {
   18      let risk_ctx = jcode_command_risk::RiskContext::from_env(working_dir);
   19      let assessment = jcode_command_risk::assess(command, &risk_ctx);
   20      if assessment.level.runs_immediately() {
   21          return None;
   22      }
   23  
   24      let justification = jcode_command_risk::Justification {
      … 5 lines omitted; exact range 1–39 …
   30              crate::logging::warn(&format!("[bash] denied destructive command: {command}"));
   31              Some(reason)
   32          }
   33          jcode_command_risk::GateOutcome::Reflect { prompt } => {
   34              crate::logging::info(&format!(
   35                  "[bash] destructive command held for justification: {command}"
   36              ));
   37              Some(prompt)
   38          }
   39      }
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/tool/bash_destructive_gate.rs:1–39 deterministic risk assessment、deny/reflect。
  • 实现 crates/jcode-app-core/src/tool/bash.rs:689–704 background dispatch 前必经 gate。
19
L1限制jcode-security-003

默认执行环境不是 OS 级沙箱

源码事实

Bash 直接用 bash/cmd.exe 子进程并继承宿主环境,在 session working_dir 下运行;代码提供 kill_on_drop、process group、timeout、策略 gate 与 hook,但审计范围内未见 bubblewrap、Seatbelt、容器或 restricted token 作为默认执行层。

白话解释

它有门禁和刹车,但不是把命令关进另一个房间;一旦获准,进程仍在你的机器权限下跑。

对自研 Harness 的含义

企业部署应外包给容器/VM/OS sandbox 或增加 capability-based executor,不能把危险命令 gate 等同隔离。

边界
  • 这是对所审提交的内建 Bash 执行路径结论;用户可在 jcode 外层自行运行容器或受限账户。
关键源码 · 实现
crates/jcode-app-core/src/tool/bash.rs · L724–L760
  724          // Foreground execution with stdin detection
  725          self.execute_foreground(&params, &ctx).await
  726      }
  727  }
  728  
  729  impl BashTool {
  730      async fn execute_foreground(
  731          &self,
  732          params: &BashInput,
  733          ctx: &ToolContext,
  734      ) -> Result<ToolOutput> {
  735          #[cfg(unix)]
  736          if self.supports_reload_persistence(ctx) {
  737              return self
  738                  .execute_reload_persistable_foreground(params, ctx)
  739                  .await;
  740          }
  741  
  742          let timeout_ms = params.timeout.unwrap_or(DEFAULT_TIMEOUT_MS).min(600000);
  743          let timeout_duration = Duration::from_millis(timeout_ms);
  744  
  745          let has_stdin_channel = ctx.stdin_request_tx.is_some();
  746  
  747          let mut command = build_shell_command(&params.command);
      … 3 lines omitted; exact range 724–760 …
  751              .stderr(Stdio::piped());
  752  
  753          if has_stdin_channel {
  754              command.stdin(Stdio::piped());
  755          }
  756  
  757          if let Some(ref dir) = ctx.working_dir {
  758              command.current_dir(dir);
  759          }
  760          let mut child = command.spawn()?;
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/tool/bash.rs:724–760 宿主 shell 子进程与 working_dir。
  • 实现 crates/jcode-app-core/src/tool/bash.rs:1095–1134 后台仍是宿主 shell/process group。
06
DIMENSION · MCP-CONNECTORS

MCP 与连接器

本章共 2 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

20
L1事实jcode-mcp-001

MCP 区分共享池与 session-owned client

源码事实

daemon 中 shared:true 默认服务器复用 SharedMcpPool,shared:false 状态型服务器每 session 单独启动;并行 connect_all 不阻塞 agent spawn,第一次真实调用尚未连接的 server 时最多等待 30 秒。

白话解释

无状态工具服务像公共电梯,多会话共用;带浏览器状态的服务像独立房间,每个会话一套。

对自研 Harness 的含义

降低重复进程与连接成本,同时避免 stateful connector 串会话。

关键源码 · 实现
crates/jcode-base/src/mcp/manager.rs · L1–L59
    1  //! MCP Manager - manages MCP server connections for a single session.
    2  //!
    3  //! In daemon mode with a shared pool, servers marked `shared: true` (the default)
    4  //! are managed by the pool and reused across sessions. Servers marked `shared: false`
    5  //! (e.g., Playwright with browser state) are spawned per-session.
    6  
    7  use super::client::{McpClient, McpHandle};
    8  use super::pool::SharedMcpPool;
    9  use super::protocol::{McpConfig, McpServerConfig, McpToolDef, ToolCallResult};
   10  use anyhow::{Context, Result};
   11  use serde::Serialize;
   12  use std::collections::HashMap;
   13  use std::sync::Arc;
   14  use tokio::sync::RwLock;
   15  
   16  /// Bound on how long a tool call will wait for a not-yet-connected MCP server
   17  /// to come up before failing with a clean tool error. Keeps a slow/hanging
   18  /// server from blocking a single tool call forever (and never blocks spawn).
   19  const CONNECT_ON_CALL_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
   20  
   21  /// Meter a completed tool call for partner-discovery provenance. No-op for
   22  /// servers without discovery provenance (the overwhelmingly common case) and
   23  /// whenever `sponsors.enabled` is false. Counts only; never content.
   24  fn meter_provenance_call(server: &str, result: &Result<ToolCallResult>) {
      … 25 lines omitted; exact range 1–59 …
   50      /// Handles from the shared pool (shared servers)
   51      pool_handles: RwLock<HashMap<String, McpHandle>>,
   52      /// Per-session owned clients (non-shared / stateful servers)
   53      owned_clients: RwLock<HashMap<String, McpClient>>,
   54      config: McpConfig,
   55      session_id: String,
   56      /// Project directory used to resolve project-local MCP config. `None`
   57      /// loads only global config and never consults the process working directory.
   58      project_dir: Option<std::path::PathBuf>,
   59  }
查看全部 3 处证据
  • 实现 crates/jcode-base/src/mcp/manager.rs:1–59 shared/owned 架构与 30s bound。
  • 实现 crates/jcode-base/src/mcp/manager.rs:114–199 parallel pool/session connect_all。
  • 实现 crates/jcode-base/src/mcp/manager.rs:318–360 connect-on-first-call。
21
L1事实jcode-mcp-002

MCP schema 晚到只允许一次 cache miss,JSON-RPC 请求按 ID 隔离

源码事实

首轮不等待慢 MCP;tool list 锁定后若发现新 mcp__ tools,仅重建一次 snapshot。McpHandle 用 atomic request id、pending oneshot map 与 30s request timeout,使共享 server 的并发响应互不串线。

白话解释

先让用户马上说话,不为插件启动卡住;插件工具后来到时只付一次缓存失效成本。多会话共用服务时每张工单都有号码。

对自研 Harness 的含义

启动延迟与 prompt cache 之间做了明确折中。

关键源码 · 实现
crates/jcode-app-core/src/agent/turn_execution.rs · L335–L393
  335      pub(super) async fn tool_definitions(&mut self) -> Vec<ToolDefinition> {
  336          if self.session.is_canary {
  337              self.registry.register_selfdev_tools().await;
  338          }
  339  
  340          // Return locked tools if available (prevents cache invalidation from
  341          // tools arriving asynchronously after the first API request).
  342          //
  343          // Exception: MCP servers connect on a background task and register
  344          // `mcp__*` tools seconds after the session starts — typically *after*
  345          // the first turn has already locked the snapshot. We deliberately do
  346          // NOT block the first turn on MCP connection: servers can be slow or
  347          // hang, and we want the user to be able to talk to the agent the moment
  348          // the session spawns. The price is that the first locked snapshot is
  349          // missing MCP tools, and the only other unlock path fires when the model
  350          // calls the `mcp` management tool — which it cannot do without first
  351          // seeing MCP tools (#206).
  352          //
  353          // So, exactly once per locked snapshot, if MCP tools have since appeared
  354          // in the registry, we rebuild. This is a single intentional provider
  355          // prompt-cache miss (the turn MCP tools first appear). The
  356          // `mcp_late_register_resolved` flag makes this a one-shot check so we do
  357          // not rescan the registry on every subsequent turn.
  358          if let Some(ref locked) = self.locked_tools {
      … 25 lines omitted; exact range 335–393 …
  384          let tools = self.build_filtered_tool_definitions().await;
  385  
  386          // Lock the tool list to prevent cache invalidation when more tools
  387          // arrive asynchronously mid-session.
  388          logging::info(&format!(
  389              "Locking tool list at {} tools for cache stability",
  390              tools.len()
  391          ));
  392          self.locked_tools = Some(tools.clone());
  393          tools
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/agent/turn_execution.rs:335–393 locked snapshot 与 MCP late-register one-shot。
  • 实现 crates/jcode-base/src/mcp/client.rs:14–55 request id、pending map、30s timeout。
07
DIMENSION · INSTRUCTIONS-SKILLS-HOOKS

指令、Skills 与 Hooks

本章共 2 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

22
L1事实jcode-instructions-001

指令层有稳定优先级:base、AGENTS、overlay、preferred tools、skills、动态 memory

源码事实

prompt builder 编译内建 base prompt,加载 global/project AGENTS.md,再读 ~/.jcode 与项目 .jcode overlay/preferred-tools,列出可用 skills;memory 和 active skill 进入动态部分。Session context 还冻结日期、OS、架构、版本、cwd 与 git 摘要。

白话解释

通用规则、用户规则、项目规则、工具偏好、技能和临时记忆各有自己的插槽,不是拼成一团不知谁覆盖谁。

对自研 Harness 的含义

可解释性好;用户应能在 UI 查看最终合成与各部分 token 占用。

关键源码 · 实现
crates/jcode-base/src/prompt.rs · L374–L448
  374  pub fn build_system_prompt_full_with_capabilities(
  375      skill_prompt: Option<&str>,
  376      available_skills: &[SkillInfo],
  377      is_selfdev: bool,
  378      memory_prompt: Option<&str>,
  379      working_dir: Option<&Path>,
  380      capabilities: PromptCapabilities,
  381  ) -> (String, ContextInfo) {
  382      let mut parts = base_system_prompt_parts(capabilities);
  383      let mut info = ContextInfo {
  384          system_prompt_chars: parts.join("\n\n").len(),
  385          ..Default::default()
  386      };
  387  
  388      // Add self-dev guidance only in active self-dev sessions. Normal sessions
  389      // learn about the on-ramp from the mode-aware `selfdev` tool schema.
  390      if is_selfdev {
  391          let selfdev_prompt = build_selfdev_prompt_for_working_dir(working_dir);
  392          info.selfdev_chars = selfdev_prompt.len();
  393          parts.push(selfdev_prompt);
  394      }
  395  
  396      // Add AGENTS.md instructions with tracking (from working_dir or cwd)
  397      let (md_content, md_info) = load_agents_md_files_from_dir(working_dir);
      … 41 lines omitted; exact range 374–448 …
  439  
  440      // Add active skill prompt
  441      if let Some(skill) = skill_prompt {
  442          parts.push(format!("# Active Skill\n\n{}", skill));
  443      }
  444  
  445      let prompt = parts.join("\n\n");
  446      info.total_chars = prompt.len();
  447  
  448      (prompt, info)
查看全部 2 处证据
  • 实现 crates/jcode-base/src/prompt.rs:374–448 full prompt 组成顺序。
  • 实现 crates/jcode-base/src/prompt.rs:615–643 immutable session context。
23
L1事实jcode-instructions-002

Skills 跨 Jcode/Agents/Claude/Codex 生态并做 per-workspace overlay

源码事实

SkillRegistry 解析 SKILL.md frontmatter 的 name/description/allowed-tools;global 来源含 Claude plugins、~/.jcode/skills、~/.agents/skills,首跑可导入 Claude/Codex;project overlay 每次从 .jcode/.agents/.claude skills 读取且 project 同名覆盖 global,不进入共享 registry。

白话解释

它会借用其他 Agent 生态的技能包,但项目私有技能只在当前工作区叠加,不会污染另一个项目。

对自研 Harness 的含义

兼容性与热更新强;递归扫描 plugin root 有深度上限 5,复杂布局可能漏检。

关键源码 · 契约
crates/jcode-base/src/skill.rs · L11–L60
   11  /// A skill definition from SKILL.md
   12  #[derive(Debug, Clone)]
   13  pub struct Skill {
   14      pub name: String,
   15      pub description: String,
   16      pub allowed_tools: Option<Vec<String>>,
   17      pub content: String,
   18      pub path: PathBuf,
   19      search_text: String,
   20  }
   21  
   22  #[derive(Debug, Deserialize)]
   23  struct SkillFrontmatter {
   24      name: String,
   25      description: String,
   26      #[serde(rename = "allowed-tools")]
   27      allowed_tools: Option<String>,
   28  }
   29  
   30  /// Registry of available skills
   31  #[derive(Debug, Default, Clone)]
   32  pub struct SkillRegistry {
   33      skills: HashMap<String, Skill>,
   34  }
      … 16 lines omitted; exact range 11–60 …
   51  impl SkillRegistry {
   52      /// Process-wide shared mutable registry used by both `skill_manage` and
   53      /// direct slash invocation paths. Keeping a single registry prevents slash
   54      /// commands from seeing a stale startup-only skill snapshot after reloads.
   55      ///
   56      /// Holds GLOBAL skills only (plugins, `~/.jcode/skills/`,
   57      /// `~/.agents/skills/`). Project-local skills are a per-session overlay
   58      /// composed at read time from the session's workspace root (issue #457);
   59      /// they must never enter this shared registry, and the daemon's startup
   60      /// cwd must never influence its contents.
查看全部 3 处证据
  • 契约 crates/jcode-base/src/skill.rs:11–60 Skill shape、frontmatter 与 global/project 边界。
  • 迁移 crates/jcode-base/src/skill.rs:98–145 首跑导入 Claude/Codex skills。
  • 实现 crates/jcode-base/src/skill.rs:231–303 global sources 与 per-session overlay。
08
DIMENSION · COLLABORATION-SWARM

Swarm 与协作

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

24
L1事实jcode-collab-001

轻量 swarm 先让协调者规划 2–4 个任务,再并发 fork Provider

源码事实

run_swarm_message 用当前 Agent 生成 JSON task plan,对每项创建 child Session、fork provider、继承模型/认证/cwd,移除 subagent/task/todo 等递归工具,并用 try_join_all 并发;最终把所有输出交给协调者综合。

白话解释

先拆成几张独立工单,让多个复制了同一模型线路的工人同时做,最后由原会话汇总。

对自研 Harness 的含义

简单易用;worker 共享 registry 与工作目录,文件级冲突仍需任务切分和外部 git/worktree 纪律。

关键源码 · 实现
crates/jcode-app-core/src/server/swarm.rs · L1528–L1613
 1528  pub(super) async fn run_swarm_task(
 1529      agent: Arc<Mutex<Agent>>,
 1530      description: &str,
 1531      subagent_type: &str,
 1532      prompt: &str,
 1533  ) -> Result<String> {
 1534      let started = Instant::now();
 1535      let (provider, registry, session_id, working_dir, coordinator_model, provider_key, route) = {
 1536          let agent = agent.lock().await;
 1537          (
 1538              agent.provider_fork(),
 1539              agent.registry(),
 1540              agent.session_id().to_string(),
 1541              agent.working_dir().map(PathBuf::from),
 1542              agent.provider_model(),
 1543              agent.session_provider_key(),
 1544              agent.session_route_api_method(),
 1545          )
 1546      };
 1547      let parent_session_id = session_id.clone();
 1548      let mut session = Session::create(
 1549          Some(session_id),
 1550          Some(format!("{} (@{} swarm)", description, subagent_type)),
 1551      );
      … 52 lines omitted; exact range 1528–1613 …
 1604                      ("child_session_id", child_session_id),
 1605                      ("subagent_type", subagent_type.to_string()),
 1606                      ("error", error.to_string()),
 1607                      ("elapsed_ms", started.elapsed().as_millis().to_string()),
 1608                  ],
 1609              );
 1610              Err(error)
 1611          }
 1612      }
 1613  }
查看全部 2 处证据
  • 实现 crates/jcode-app-core/src/server/swarm.rs:1528–1613 child session/provider/tool surface。
  • 实现 crates/jcode-app-core/src/server/swarm.rs:1615–1700 plan、parallel fan-out 与 synthesis。
25
L1事实jcode-collab-002

deep swarm 把协作升级成可增长 DAG、强制 artifact 与审计 gate

源码事实

swarm-deep 动态指令要求 task_graph、depends_on、expand_node、complete_node typed artifact、critique/verify gate 与 inject_gap;worker 未 expand/complete 会重排队,gate 必须按 audited node id 覆盖范围并优先处理低置信 artifact。

白话解释

不是“多叫几个人聊天”,而是把任务画成图:每个节点要交证据包,审计员可以发现缺口后现场加新节点,图没验完就不能宣布完成。

对自研 Harness 的含义

非常接近研究/工程编排 Harness;复杂度、成本和并发写冲突风险也显著提高。

关键源码 · Prompt
crates/jcode-base/src/prompt.rs · L75–L91
   75  /// Reasoning-effort sentinel for the **deep task graph** mode: strongest model
   76  /// reasoning AND the comprehensive DAG-first swarm workflow (decompose into a
   77  /// validated task graph, critique/verify gates, typed artifact handoffs). Sits
   78  /// one rung above [`SWARM_EFFORT`] on the effort ladder: `... xhigh`, `swarm`
   79  /// (light fan-out), `swarm-deep` (deep task graph). Providers translate this to
   80  /// their strongest real effort, while the UI/session keep the literal marker so
   81  /// the agent knows to inject [`SWARM_DEEP_EFFORT_DIRECTIVE`].
   82  pub const SWARM_DEEP_EFFORT: &str = "swarm-deep";
   83  
   84  /// System-prompt directive injected when the active reasoning effort is
   85  /// [`SWARM_EFFORT`]. Instructs the agent to lean on the swarm tooling.
   86  pub const SWARM_EFFORT_DIRECTIVE: &str = "# Swarm Effort\n\nYou are running at the maximum reasoning effort with swarm orchestration enabled. For any non-trivial task, decompose the work and use the `swarm` tool to spawn and coordinate parallel agents (spawn workers with concrete prompts, assign tasks, and collect their reports) instead of doing everything yourself in one thread. Prefer parallelizing independent subtasks across swarm members, and use a coordinator/plan when the work has multiple stages. Only skip the swarm for trivial, single-step requests.";
   87  
   88  /// System-prompt directive injected when the active reasoning effort is
   89  /// [`SWARM_DEEP_EFFORT`]. Instructs the agent to run the comprehensive DAG-first
   90  /// task-graph workflow.
   91  pub const SWARM_DEEP_EFFORT_DIRECTIVE: &str = "# Deep Task Graph\n\nYou are running at maximum reasoning effort with the deep task-graph swarm workflow. Treat the task DAG as the primary object, not ad hoc agent chat. Workflow:\n\n1. Seed a graph with `swarm task_graph` using `mode: \"deep\"`: lay out nodes (kind explore|implement|verify|fix|synthesize) and `depends_on` edges instead of answering directly. (At this effort the server already defaults the plan to deep, but pass `mode: \"deep\"` explicitly anyway.) The engine auto-inserts a plan-wide root gate over your seed: the plan cannot finish until a final adversarial audit passes, and that audit can inject new top-level work.\n2. For any node that is too big, `swarm expand_node` to decompose it into a child sub-DAG (you become its planner/integrator). In deep mode a critique/verify gate is auto-inserted before a composite node can close. The graph is EXPECTED to outgrow its seed, often by several times: growth (expansions and gate-injected gaps) is the system working, not scope creep. plan_status reports seeded-vs-grown counts.\n3. Finish each node with `swarm complete_node` and a typed artifact: `findings`, `evidence` (file:line / commit refs), `validation`, `open_questions`, a required `confidence` (low|medium|high; report low honestly, it routes follow-up work to shore up that scope), and an honest `what_i_did_not_check`. Downstream nodes are hydrated with these artifacts automatically. There is no other way to close a deep node: a turn ending without expand_node/complete_node re-queues the node to a fresh worker and fails it on repeat.\n4. When a critique/verify gate finds gaps or failures, use `swarm inject_gap` to add new nodes; the parent cannot close until they drain. A passing gate artifact must account for EVERY node it audited by id (the server rejects rubber stamps), and cannot pass over a low-confidence sibling without addressing it explicitly, so treat low-confidence siblings as priority probe targets.\n5. Use `swarm run_plan` to drive the graph to completion. It returns immediately and drives the plan as a background task (progress card + wake on completion), so keep working or answer the user while it runs; check `swarm plan_status` or `bg` for progress. Deep mode fans out wide automatically (many workers run in parallel, bounded only by the swarm member cap), so prefer decomposing into MANY independent sibling nodes rather than a few serial ones: keep the ready set wide so run_plan can dispatch lots of agents at once. Only add `depends_on` edges for real data dependencies.\n\nComprehensiveness is structural: prefer decomposition + gates over a single thorough answer, so it is very unlikely any nook or cranny is missed.";
查看全部 4 处证据
  • Prompt crates/jcode-base/src/prompt.rs:75–91 deep DAG workflow 总契约。
  • Prompt crates/jcode-swarm-core/src/lib.rs:377–432 worker expand/complete 与 typed artifact。
  • Prompt crates/jcode-swarm-core/src/lib.rs:435–496 gate audit/inject-gap 契约。
  • 测试 crates/jcode-swarm-core/src/lib.rs:699–740 deep node/gate prompt contract tests。
26
L1事实jcode-collab-003

Swarm 有持久成员树、频道、heartbeat 和死亡任务回收

源码事实

SwarmMemberRecord 保存 parent/report-back、角色、状态、working_dir 和 report;ChannelIndex 双向索引订阅。worker 死亡时非终态任务按 reclaim cap 重新排队,超上限转 failed,并持久化/broadcast/通知协调者。

白话解释

每个工人有户口、上级、频道和心跳;工人挂了,手里的活不会静默卡死,会有限次数重新派发,反复致命才明确失败。

对自研 Harness 的含义

协作是耐久调度系统而非内存 future;需要持续治理 member cap、staleness 和 replay idempotency。

关键源码 · 契约
crates/jcode-swarm-core/src/lib.rs · L213–L253
  213  /// Durable, persistable portion of a swarm member.
  214  #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
  215  pub struct SwarmMemberRecord {
  216      pub session_id: String,
  217      pub working_dir: Option<PathBuf>,
  218      pub swarm_id: Option<String>,
  219      pub swarm_enabled: bool,
  220      pub status: SwarmLifecycleStatus,
  221      pub detail: Option<String>,
  222      /// Stable label of the task/role this member was spawned or assigned for.
  223      #[serde(default, skip_serializing_if = "Option::is_none")]
  224      pub task_label: Option<String>,
  225      pub friendly_name: Option<String>,
  226      pub report_back_to_session_id: Option<String>,
  227      #[serde(default, skip_serializing_if = "Option::is_none")]
  228      pub latest_completion_report: Option<String>,
  229      pub role: SwarmRole,
  230      pub is_headless: bool,
  231  }
  232  
  233  /// Bidirectional index for swarm channel subscriptions.
  234  #[derive(Clone, Debug, Default, PartialEq, Eq)]
  235  pub struct ChannelIndex {
  236      pub by_swarm_channel: HashMap<String, HashMap<String, HashSet<String>>>,
      … 7 lines omitted; exact range 213–253 …
  244              .or_default()
  245              .entry(channel.to_string())
  246              .or_default()
  247              .insert(session_id.to_string());
  248          self.by_session
  249              .entry(session_id.to_string())
  250              .or_default()
  251              .entry(swarm_id.to_string())
  252              .or_default()
  253              .insert(channel.to_string());
查看全部 3 处证据
  • 契约 crates/jcode-swarm-core/src/lib.rs:213–253 durable member 与 channel index。
  • 实现 crates/jcode-app-core/src/server/swarm.rs:333–448 dead member salvage、cap、persist、broadcast。
  • 测试 crates/jcode-app-core/src/server/swarm_mutation_state_tests.rs:39–83 spawn mutation response 可幂等 replay。
09
DIMENSION · PERSISTENCE-OBSERVABILITY-MATURITY

持久化、观测与成熟度

本章共 4 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

27
L1事实jcode-persist-001

Session 用完整 snapshot 加 append-only JSONL journal

源码事实

save 比较 metadata/vector dirty state:需要全量时 checkpoint snapshot 并删 journal,否则只追加 messages/env snapshots/memory injections/replay events delta;journal 超上限或 append 失败再回退 snapshot。

白话解释

平时只往流水账追加新变化,偶尔把整本账重抄成快照;这样频繁保存不会每次重写全部历史。

对自研 Harness 的含义

兼顾耐久与 I/O;多写者必须依靠更上层会话所有权避免交错 append。

关键源码 · 实现
crates/jcode-base/src/session/persistence.rs · L307–L395
  307      pub fn save(&mut self) -> Result<()> {
  308          self.updated_at = Utc::now();
  309          let path = session_path(&self.id)?;
  310          let journal_path = session_journal_path_from_snapshot(&path);
  311          let start = std::time::Instant::now();
  312          let snapshot_bytes_before = file_len_or_zero(&path);
  313          let journal_bytes_before = file_len_or_zero(&journal_path);
  314          let current_meta = self.journal_meta();
  315          let metadata_needs_snapshot = self
  316              .persist_state
  317              .last_meta
  318              .as_ref()
  319              .is_some_and(|prev| metadata_requires_snapshot(prev, &current_meta));
  320          let vectors_need_snapshot = !self.persist_state.snapshot_exists
  321              || self.persist_state.messages_mode == PersistVectorMode::Full
  322              || self.persist_state.env_snapshots_mode == PersistVectorMode::Full
  323              || self.persist_state.memory_injections_mode == PersistVectorMode::Full
  324              || self.persist_state.replay_events_mode == PersistVectorMode::Full
  325              || self.messages.len() < self.persist_state.messages_len
  326              || self.env_snapshots.len() < self.persist_state.env_snapshots_len
  327              || self.memory_injections.len() < self.persist_state.memory_injections_len
  328              || self.replay_events.len() < self.persist_state.replay_events_len;
  329  
  330          let delta_messages = self
      … 55 lines omitted; exact range 307–395 …
  386                  Ok(()) => {
  387                      self.reset_persist_state(true);
  388                      let journal_stat_start = Instant::now();
  389                      let journal_bytes_after = file_len_or_zero(&journal_path);
  390                      let journal_stat_ms = journal_stat_start.elapsed().as_millis();
  391                      if journal_bytes_after > MAX_SESSION_JOURNAL_BYTES {
  392                          let checkpoint_start = Instant::now();
  393                          let result = self.checkpoint_snapshot(&path, &journal_path);
  394                          let checkpoint_ms = checkpoint_start.elapsed().as_millis();
  395                          let journal_bytes_after = file_len_or_zero(&journal_path);
查看全部 2 处证据
  • 实现 crates/jcode-base/src/session/persistence.rs:307–395 dirty 判定、delta journal、checkpoint threshold。
  • 测试 crates/jcode-base/src/session_tests/cases.rs:835–880 journal append/load replay 回归。
28
L1事实jcode-persist-002

损坏 journal 跳过坏行、挽救 glued entries,并在下次保存自愈

源码事实

replay 不在首个 parse error 停止,而是继续后续行;对 torn append 与下一条粘在同一行的情况扫描结构起点并 stream-parse。发现腐坏后备份 corrupt.jsonl,强制下次 checkpoint 把已挽救状态固化。

白话解释

流水账中间坏一行,不会把后面所有对话一起判死;能捞的条目先捞出来,再重写一本干净快照。

对自研 Harness 的含义

长会话恢复质量高,且保留法证副本。

关键源码 · 实现
crates/jcode-base/src/session/persistence.rs · L26–L128
   26  /// Attempt to recover complete entries from a journal line that failed the
   27  /// strict one-entry-per-line parse.
   28  ///
   29  /// If a writer died mid-append (torn line without a trailing newline), the
   30  /// next successful append starts writing on the same line, producing
   31  /// `<torn json><complete entry json>\n` or `<entry json><entry json>\n`.
   32  /// Serialized entries always begin with `{"meta":` (struct field order), so
   33  /// scan for candidate starts and stream-parse consecutive complete entries
   34  /// from the first position that yields any.
   35  fn salvage_glued_journal_entries(line: &str, mut apply: impl FnMut(SessionJournalEntry)) -> usize {
   36      const ENTRY_START: &str = "{\"meta\":";
   37      let mut salvaged = 0usize;
   38      let mut search_from = 0usize;
   39      while let Some(rel) = line
   40          .get(search_from..)
   41          .and_then(|rest| rest.find(ENTRY_START))
   42      {
   43          let candidate_start = search_from + rel;
   44          let mut stream = serde_json::Deserializer::from_str(&line[candidate_start..])
   45              .into_iter::<SessionJournalEntry>();
   46          let mut parsed = Vec::new();
   47          for item in &mut stream {
   48              match item {
   49                  Ok(entry) => parsed.push(entry),
      … 69 lines omitted; exact range 26–128 …
  119                  ("phase", "journal_replay_corruption".to_string()),
  120                  ("path", journal_path.display().to_string()),
  121                  ("entries_replayed", stats.entries.to_string()),
  122                  ("lines_skipped", stats.skipped_lines.to_string()),
  123                  ("entries_salvaged", stats.salvaged_entries.to_string()),
  124              ],
  125          );
  126      }
  127  
  128      Ok(stats)
查看全部 3 处证据
  • 实现 crates/jcode-base/src/session/persistence.rs:26–128 torn/glued salvage 与继续 replay。
  • 实现 crates/jcode-base/src/session/persistence.rs:142–172 backup + next-save healing。
  • 测试 crates/jcode-base/src/session_tests/cases.rs:930–1095 skip tail、glued salvage、自愈回归。
29
L1事实jcode-observe-001

观测覆盖结构化 lifecycle、实时 session metrics 与可选择遥测

源码事实

工具/MCP/Swarm/Session/Provider 路径记录带 session/message/tool id、latency、bytes、状态的结构化事件;独立 lock-free-ish session registry 维护 60 秒 token churn、turns 和 last activity。匿名 telemetry 默认启用,可用 JCODE_NO_TELEMETRY、DO_NOT_TRACK 或 marker 关闭;prompt/transcript 内容分享另行显式 opt-in。

白话解释

本地能看每个工人最近是否真在干活、花了多少 token、工具跑多久;发往服务端的匿名统计能关闭,而对话内容默认不发。

对自研 Harness 的含义

可观测维度很丰富;隐私评审需同时检查 usage telemetry、content-sharing 和 sponsor provenance 三条数据面。

关键源码 · 实现
crates/jcode-app-core/src/tool/mod.rs · L603–L638
  603          crate::logging::event_info(
  604              "TOOL_LIFECYCLE",
  605              Self::tool_lifecycle_fields("start", name, resolved_name, &input, &ctx),
  606          );
  607  
  608          let started_at = std::time::Instant::now();
  609          let result = tool.execute(input.clone(), ctx.clone()).await;
  610          let latency_ms = started_at.elapsed().as_millis().min(u128::from(u64::MAX)) as u64;
  611  
  612          crate::telemetry::record_tool_execution(resolved_name, &input, result.is_ok(), latency_ms);
  613          Self::fire_post_tool_hook(resolved_name, &ctx, &result, latency_ms);
  614  
  615          let mut output = match result {
  616              Ok(output) => output,
  617              Err(error) => {
  618                  let mut fields =
  619                      Self::tool_lifecycle_fields("error", name, resolved_name, &input, &ctx);
  620                  fields.push(("elapsed_ms".to_string(), latency_ms.to_string()));
  621                  fields.push(("error".to_string(), crate::util::format_error_chain(&error)));
  622                  crate::logging::event_warn("TOOL_LIFECYCLE", fields);
  623                  return Err(error);
  624              }
  625          };
  626  
      … 2 lines omitted; exact range 603–638 …
  629  
  630          let mut fields = Self::tool_lifecycle_fields("done", name, resolved_name, &input, &ctx);
  631          fields.push(("elapsed_ms".to_string(), latency_ms.to_string()));
  632          fields.push(("output_bytes".to_string(), output.output.len().to_string()));
  633          fields.push((
  634              "output_chars".to_string(),
  635              output.output.chars().count().to_string(),
  636          ));
  637          fields.push(("image_count".to_string(), output.images.len().to_string()));
  638          crate::logging::event_info("TOOL_LIFECYCLE", fields);
查看全部 4 处证据
  • 实现 crates/jcode-app-core/src/tool/mod.rs:603–638 tool lifecycle 与 telemetry。
  • 实现 crates/jcode-base/src/session_metrics.rs:1–25 独立 live metrics 设计。
  • 实现 crates/jcode-base/src/session_metrics.rs:63–128 token/turn/activity registry。
  • 配置 crates/jcode-telemetry-core/src/lib.rs:312–395 usage opt-out 与 content separate opt-in。
30
L3事实jcode-maturity-001

关键故障边界有源码级回归测试,许可证为 MIT

源码事实

仓库对 compaction restore/hard threshold、mid-stream rollback、session journal corruption、MCP management、hook gate、Swarm prompt/assignment/report-back 和 tool schema 等关键路径有测试;LICENSE 为 MIT。

白话解释

不只是代码注释说“应该安全”:断流、损坏账本、深度协作契约等都有回归用例钉住。

对自研 Harness 的含义

成熟度高,但 1,198 个 Rust 文件的系统仍需 CI 测试矩阵覆盖多 Provider、三平台和远程 daemon。

关键源码 · 测试
crates/jcode-base/src/compaction_tests.rs · L388–L451
  388  async fn test_guard_at_95_triggers_hard_compact() {
  389      let mut manager = CompactionManager::new().with_budget(1_000);
  390      let mut messages = Vec::new();
  391      for i in 0..20 {
  392          messages.push(make_text_message(
  393              Role::User,
  394              &format!("message {} with padding {}", i, "x".repeat(50)),
  395          ));
  396          manager.notify_message_added();
  397      }
  398      // 96% usage — above critical threshold
  399      manager.update_observed_input_tokens(960);
  400  
  401      let provider: Arc<dyn Provider> = Arc::new(MockSummaryProvider);
  402      let action = manager.ensure_context_fits(&messages, provider);
  403      assert!(
  404          matches!(action, CompactionAction::HardCompacted(_)),
  405          "SHOULD hard-compact at 96%"
  406      );
  407      assert!(
  408          manager.compacted_count > 0,
  409          "compacted_count should increase after hard compact"
  410      );
  411      assert!(
      … 30 lines omitted; exact range 388–451 …
  442      );
  443      // First message should be the emergency summary
  444      match &api_messages[0].content[0] {
  445          ContentBlock::Text { text, .. } => {
  446              assert!(text.contains("Previous Conversation Summary"));
  447              assert!(text.contains("Emergency compaction"));
  448          }
  449          _ => panic!("expected text summary block"),
  450      }
  451  }
查看全部 4 处证据
  • 测试 crates/jcode-base/src/compaction_tests.rs:388–451 95% hard-compaction guard。
  • 测试 crates/jcode-app-core/src/tool/communicate_tests/end_to_end.rs:370–442 spawn completion report-back E2E。
  • 测试 crates/jcode-base/src/hooks.rs:325–352 hook payload/truncation tests。
  • 契约 LICENSE:1–21 MIT License。
APPENDIX · SOURCE INDEX

本报告引用过的实现文件

这是一份代码阅读索引,不是仓库文件总表。机器候选扫描覆盖整个仓库;进入结论的文件必须经人工沿调用链复核。

  1. 01crates/jcode-app-core/src/agent/turn_execution.rsL4–35, 37–90, 335–393
  2. 02crates/jcode-app-core/src/agent/turn_loops.rsL17–68, 455–484, 5–15, 798–825, 485–547, 548–585, 63–92, 878–917
  3. 03crates/jcode-provider-copilot-runtime/src/lib.rsL615–659
  4. 04crates/jcode-provider-openrouter-runtime/src/openrouter_tests.rsL2629–2718
  5. 05crates/jcode-provider-core/src/lib.rsL76–126, 293–436
  6. 06crates/jcode-base/src/provider/mod.rsL328–374
  7. 07crates/jcode-base/src/prompt.rsL451–557, 374–448, 615–643, 75–91
  8. 08crates/jcode-base/src/compaction.rsL128–205, 283–345, 456–543, 552–605
  9. 09crates/jcode-base/src/compaction_tests.rsL61–95, 388–451
  10. 10crates/jcode-app-core/src/agent/compaction.rsL90–182, 185–241, 244–283
  11. 11crates/jcode-base/src/memory_agent.rsL1–45, 234–275
  12. 12crates/jcode-app-core/src/agent/prompting.rsL20–55
  13. 13crates/jcode-base/src/memory.rsL159–185, 248–275
  14. 14crates/jcode-base/src/memory/pending.rsL129–174
  15. 15crates/jcode-tool-core/src/lib.rsL9–65, 75–139
  16. 16crates/jcode-app-core/src/tool/mod.rsL150–255, 318–341, 627–678, 543–601, 603–638
  17. 17crates/jcode-app-core/src/tool/batch.rsL180–202, 202–281
  18. 18crates/jcode-app-core/src/tool/bash.rsL742–760, 884–930, 1095–1175, 689–704, 724–760, 1095–1134
  19. 19crates/jcode-base/src/hooks.rsL220–323, 325–352
  20. 20crates/jcode-app-core/src/tool/bash_destructive_gate.rsL1–39
  21. 21crates/jcode-base/src/mcp/manager.rsL1–59, 114–199, 318–360
  22. 22crates/jcode-base/src/mcp/client.rsL14–55
  23. 23crates/jcode-base/src/skill.rsL11–60, 98–145, 231–303
  24. 24crates/jcode-app-core/src/server/swarm.rsL1528–1613, 1615–1700, 333–448
  25. 25crates/jcode-swarm-core/src/lib.rsL377–432, 435–496, 699–740, 213–253
  26. 26crates/jcode-app-core/src/server/swarm_mutation_state_tests.rsL39–83
  27. 27crates/jcode-base/src/session/persistence.rsL307–395, 26–128, 142–172
  28. 28crates/jcode-base/src/session_tests/cases.rsL835–880, 930–1095
  29. 29crates/jcode-base/src/session_metrics.rsL1–25, 63–128
  30. 30crates/jcode-telemetry-core/src/lib.rsL312–395
  31. 31crates/jcode-app-core/src/tool/communicate_tests/end_to_end.rsL370–442
  32. 32LICENSEL1–21