Skip to content

spec: untrusted-content defense, repository map, debugger tool and transcript search - #77

Merged
vanedaltro merged 1 commit into
mainfrom
spec/context-safety-search
Oct 30, 2026
Merged

vanedaltro merged 1 commit into
mainfrom
spec/context-safety-search

Conversation

@leonardoaraujosantos

Copy link
Copy Markdown
Contributor

Four new OpenSpec changes, specification only, plus their ROADMAP entries. Each one closes a gap that is not on the roadmap today.

add-untrusted-content-defense (P1)

New capability untrusted-content, plus additions to permissions-modes and system-context. It implements the existing workspace-trust → "Instruction and data provenance" rule for every tool that returns third-party content. Today only MCP resources are framed; webfetch, websearch, MCP tool results and browser pages reach the model bare.

  • One frame: a single escape-safe <untrusted_content source origin> frame, applied by the tool registry after truncation. It replaces today's <mcp_resource> frames and stays framed when an overflow file is re-read.
  • Hidden characters: zero-width, bidi and tag characters and terminal escapes become visible markers inside frames.
  • Detector: a deterministic, versioned rule table flags instruction-like text with no model call. Hits are recorded on the tool result event and shown in the TUI, exec and the dashboard. Content is never dropped.
  • Taint-aware approvals: after a flagged result, risky actions ask until the next user prompt. Risky means network egress, writes outside the Location, commands the classifier would allow, and secret reads. dont-ask and unattended runs deny instead; bypass shows the notice, or refuses when bypass: "deny" is set. The settings live under permissions.untrusted_content, and project config can only make them stricter.
  • Out of scope: an exfiltration guard for rendered links and images. The TUI, dashboard and HTML export already render images as text with no auto-fetch.

add-repository-map (P1)

Additions to code-intelligence, system-context, provider-catalog and tui; builtin-tools and configuration are modified.

  • Symbols: tree-sitter tag queries for 11 languages, reusing the tree-sitter already linked in cyber-tools. A CI gate fails if the grammars add more than 12 MiB to the binary.
  • Ranking: PageRank over the reference graph, personalised by focus paths and the Session's recent files. The output is deterministic.
  • Budget: a token budget per model profile (repo_map.context_tokens and tool_tokens), capped as a share of the context window.
  • Tool: repo_map is read-only, has the same permission as grep and works in plan mode.
  • Context Source: a new Epoch-pinned Context Source, core/repo-map, appears in trusted checkouts only. It never sends mid-conversation updates, so the cached prompt prefix stays byte-stable.
  • Storage: a local SQLite cache keyed by content hash and shared across worktrees. It refreshes when used; there is no file watcher. It is inspected with cyber lsp map and /map, and the API sits in the existing lsp route group.
  • Deferred: semantic code search, with the reasons recorded in the design.

add-debugger-tool (P2, experimental feature debugger)

New capability debugging; builtin-tools and background-tasks are modified, and tui gets one addition. It debugs through the Debug Adapter Protocol, built like the existing LSP support (trusted launch, bounded framing, checkout pins, owned cancellation).

  • Tool: one debug tool covers launch, breakpoints and logpoints, stepping, waiting for a stop with a timeout, stack frames, bounded variables, evaluate and terminate.
  • Ownership: one debug session per Session, owned by a Job of kind debug, with an idle timeout and cleanup when the Session ends or is cancelled.
  • Permissions: launching checks the bash permission on the program's command line and runs inside the Session's sandbox. evaluate and condition expressions ask by default. Attaching is limited to processes in the same Session's Jobs.
  • First slice: the stdio adapters debugpy and lldb-dap, and .vscode/launch.json read-only in trusted checkouts. Delve and js-debug (socket adapters) follow.

add-session-transcript-search (P1; agent tool P2)

New capability session-search, with additions to server-api, client-sdk, cli-commands and tui.

  • Index: a SQLite FTS5 index (the bundled SQLite already has FTS5) written in the same transaction as the events, with a resumable backfill.
  • Consistency: deleting a Session, reverting and retention cleanup remove its rows. A restore or an index format change triggers a rebuild.
  • What is indexed:
    • Indexed: prompts, assistant text, tool name and argument summaries, and the first and last 2 KiB of tool output, all after secret redaction.
    • Never indexed: reasoning or opaque state.
  • Size bound: a configurable cap; past it, the least recently used Sessions drop out of the index and results say they are partial.
  • Queries: a small safe grammar that cannot produce FTS syntax errors. Ranking is BM25 discounted by age, and snippets carry character ranges rather than markup.
  • Surfaces: cyber sessions search, GET /api/v1/sessions/search, the SDK session.search, and content matches in /resume. Title search is unchanged.
  • Agent tool (P2): session_search is permission-gated, and its results are framed as untrusted data.

Cross-change notes

  • Shared frame: the debugger and session_search results use the untrusted-content frame (source="debug" and source="session_search").
  • Tool catalog: add-repository-map, add-debugger-tool and the existing add-binary-hex-editor each modify the shared "Capability-owned tool catalog" list against main. Whichever is archived later keeps every added line.
  • Model profiles: the repository-map budget extends the model profiles from improve-model-protocol-fidelity, so that change is archived first.
  • Surfaces: there are no new top-level cyber commands, /api/v1 route groups, ID prefixes or top-level config keys. The repository map's repo_map key is the only addition to Top-level keys.
  • No overlap with open work: PR feat(plugins): add confinement foundations and host lifetime safeguards #76 (plugin native confinement) and the other open changes don't touch these topics.

Checks

  • openspec validate --all --strict: 111 passed, 0 failed.
  • python3 scripts/spec_lint.py: 0 errors, 25 warnings, the same as main. It was also run on a scratch copy with the deltas merged in: no new errors, warnings or duplicate requirement names.

… and transcript search

Four OpenSpec changes, specification only:
- add-untrusted-content-defense (P1): one escape-safe frame for webfetch,
  websearch, MCP and browser results, hidden-character markers, a
  deterministic injection detector with notices, and taint-aware approvals
  for risky actions until the next user prompt.
- add-repository-map (P1): tree-sitter symbol map ranked by references,
  fitted to a per-model budget, as a repo_map tool and an Epoch-pinned
  Context Source that keeps the cached prefix stable.
- add-debugger-tool (P2, feature debugger): DAP debugging through one
  debug tool, built like the LSP support, gated like bash and run in the
  Session sandbox; debugpy and lldb-dap first.
- add-session-transcript-search (P1, agent tool P2): SQLite FTS5 index
  over transcripts, kept consistent with deletion, revert and retention;
  reasoning and opaque state are never indexed.

ROADMAP lists each as proposed.
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.

2 participants