Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ Installation is quiet: no theme change, no provider or model binding, next-actio

## Capabilities

### Semantic navigation

The bundled `semantic-navigation` Skill can query an existing local language server for definitions, references and single-file diagnostics through Pi's ordinary Bash tool. Diagnostic comparisons retain ambiguous occurrences instead of treating matching messages as proof that nothing changed. No server is installed or started on launch; use requires an explicit server command and Bash permission. See [usage and limits](USAGE.md#semantic-navigation).

### Subagents

```text
Expand Down
4 changes: 4 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ OpenPI 自有偏好通过自然语言配置:

## 能力

### 语义导航

内置 `semantic-navigation` Skill 通过 Pi 的普通 Bash 工具,按需向已有本地语言服务器查询定义、引用和单文件诊断。前后诊断对比保留无法可靠配对的记录,不把相同报错文字抵消成“没有变化”。启动 OpenPI 不会安装或启动服务器;调用需要明确的服务器命令和 Bash 权限。详见[使用方式与边界](USAGE.md#semantic-navigation)。

### Subagent

```text
Expand Down
10 changes: 10 additions & 0 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ Skill 使用 Pi 原生机制:模型根据名称、描述和路径按需用 `re

Skill 正文通过原生用户消息或工具结果进入正常 Session 历史,压缩也交给 Pi。OpenPI 不另存正文快照,不叠加隐藏正文,也不在压缩后自动补回。压缩后不保证全文仍在模型上下文中;需要时可重新读取或显式调用。普通 `read` 的输出限制和模型总上下文限制仍然适用。设计边界见 [Decision 0002](docs/decisions/0002-native-skill-lifecycle.md)。

## Semantic navigation

`semantic-navigation` 随包通过 Pi 原生 Skill 清单加载。模型可按需读取,也可用 `/skill:semantic-navigation` 明确调用;正文和脚本参数见 [Skill](skills/semantic-navigation/SKILL.md)。它复用普通 `bash`,不新增模型工具、模型调用或后台服务,也不会自动安装语言服务器。

调用时明确指定项目目录、已有服务器的可执行文件与参数、文件及位置。支持定义、引用和单文件 pull diagnostics;不支持该能力的服务器会明确返回 unsupported。输入位置使用从 1 开始的 UTF-16 行列,返回位置保留 LSP 从 0 开始的范围。每次调用独立启动、请求和关闭服务,响应结果与进程退出结果分别展示。

前后诊断快照绑定打开文本的 SHA-256、文件 URI 和服务器身份。对比保留每个诊断及其位置;文本变化后,同类报错的对应关系标为 ambiguous,而非直接抵消。新增或消失的诊断只表示两次观察的差异,不证明编辑造成或修复了问题。依赖、配置和其他文件未被冻结;单文件空结果不代表整个项目检查通过,未知或不完整快照也不作此结论。

语言服务器以普通 Bash 权限运行;只读协议请求不构成服务器沙箱。需要当前会话具有 Bash 能力,Plan Mode 的命令限制仍然适用。原生包清单明确列出 `subagents`、`workflows` 和 `semantic-navigation` 三个 Skill,使字符串来源和带筛选项的对象来源都能发现它们;子会话继续排除两个编排 Skill。

## 模型工具速查

OpenPI 提供一套固定的常驻模型工具,在 Session 开始时确定一次:Subagent(`subagent_spawn` 等 5 个)与 Workflow(`workflow`/`workflow_stop`/`workflow_status`),共 8 个。会话内工具列表不因模型动作或运行时状态改变;缺少对应状态的调用在执行层返回明确结果或 fail-closed。只有用户显式边界会改变工具:`/plan` 加入只读 Git、`plan_ready` 与 `ask_user`/`human_handoff`;`/openpi-setup` episode 加入 `configure_my_pi_setup` 与 `ask_user`/`human_handoff`;浏览器授权后启用 `openpi_browser`。Subagent 与 Workflow 的 Skill 文件仍随包发布,模型按需用 `read` 读取,不常驻普通系统 Prompt。
Expand Down
2 changes: 2 additions & 0 deletions docs/research/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ Research records preserve sourced investigation and distinguish observations, in

- [`TEXT_PROJECTION_UTF8_2026-10-03.md`](TEXT_PROJECTION_UTF8_2026-10-03.md) — preservation of literal replacement characters in bounded Workflow context and handoffs ([#648](https://github.com/openpi-dev/openpi/issues/648)).

- [`SEMANTIC_NAVIGATION_2026-11-07.md`](SEMANTIC_NAVIGATION_2026-11-07.md) — native Skill delivery, actual TypeScript navigation, occurrence-preserving diagnostic comparisons, package discovery and Bash cancellation; explicit single-file and abnormal-exit limits ([#913](https://github.com/openpi-dev/openpi/issues/913)).

## Legacy records

The following records predate [`Decision 0001`](../decisions/0001-documentation-and-evidence-governance.md). They remain useful historical sources but have not been migrated to the new metadata contract as part of this change:
Expand Down
64 changes: 64 additions & 0 deletions docs/research/SEMANTIC_NAVIGATION_2026-11-07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
status: validated
created: 2026-11-07
last-verified: 2026-11-07
applies-to: OpenPI baseline 1120cafcd3f5c1ad466df1c7b823976a3e911f72 and the semantic-navigation candidate described below; Pi SDK 1.2.0; TypeScript 7.0.2 with effect-tsgo 0.24.3
related-issues:
- https://github.com/openpi-dev/openpi/issues/913
related-prs: []
supersedes: none
---

# On-demand semantic navigation and diagnostic observations

This record preserves source-scoped observations and a candidate implementation, not a formal Benchmark, a release claim or a new architectural Decision.

## Question and sources

Can language-server results answer symbol questions that text search leaves ambiguous, while keeping execution in Pi's existing tool and lifecycle boundaries?

- Community starting points: [pi-lens](https://github.com/apmantza/pi-lens/tree/7589a95232f8521e1f71a435e4e403d446857035) and [pi-lsp](https://github.com/ian-pascoe/pi-extensions/tree/32f4991e824e2ef03872707229c59ddde80f0b9b). Their feature sets motivated investigation; they were not installed or adopted as dependencies.
- [LSP 3.17](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/) defines capability negotiation, document synchronization, navigation, pull diagnostics and shutdown. The implementation only requests advertised capabilities.
- The executable used here is the repository's installed TypeScript 7.0.2, patched by the existing Effect preparation script. Its initialize response identifies `7.0.2+effect-tsgo.0.24.3`. Results do not establish compatibility with every TypeScript build or language server.
- Pi SDK 1.2.0's native package resource loader and Bash tool were exercised independently. No provider/model call or global configuration edit was needed.

## Observed value and counterexamples

| Case at baseline 1120caf | Independent expectation | Observed result |
| --- | --- | --- |
| `sharedHintLine` alias in the workflow dashboard | Definition in `screen-chrome.ts`, line 97 | Correct definition; references returned the alias import and its use only |
| Local `isRecord` in Plan Mode | Local definition at line 72, separate from the same name in persisted state | Correct definition and five local occurrences |
| Identical diagnostic snapshots | Same text and full diagnostic occurrences | Two unchanged occurrences |
| Insert unrelated lines | Existing diagnostics move | Two ambiguous groups, retaining both locations |
| Introduce a distinct type error | Newly observed error | Type error and an additional unused hint retained |
| Fix one type error | Error disappears from the observed report | One resolved observation |
| Remove one error and create the same message elsewhere | Occurrences must not silently cancel | Same-signature before/after diagnostics remain ambiguous |
| Add another identical error | Multiplicity must survive | Ambiguous group retains one before and two after |

The diagnostic cases use a copy of real `terminal-text.ts` in a controlled temporary TypeScript project, with deliberate edits and source hashes. They establish single-document behavior, not project-wide coverage or causality. Alias references are useful but do not enumerate every reference to the original exported symbol. No latency or token-efficiency advantage was measured.

An earlier code/message multiset comparator incorrectly cancelled a removed error against a new identical error elsewhere. That rejected result remains in the original evidence. The candidate deliberately treats matching signatures in changed text as ambiguous; even harmless inserted lines can therefore require interpretation.

## Candidate and ownership

The package declares `subagents`, `workflows` and `semantic-navigation` in Pi's native manifest. Pi exposes their names, descriptions and paths; the model reads bodies when useful. Existing child filtering continues to exclude the two orchestration Skills. An adjacent Node script accepts one JSON request and starts one explicitly selected, already installed stdio server through ordinary Bash. It provides definitions, references, single-file pull snapshots and snapshot comparison. It adds no model-facing tool, service pool, model selection, automatic installation, configuration store or forced workflow.

The first manifest candidate listed only the new Skill. Full tests exposed a real compatibility difference: the baseline string package source discovered no Skills, while a source object with extension filters used convention discovery and retained `subagents` and `workflows`. Listing only the new directory removed those existing object-source resources. Explicitly listing all three preserves existing users and also exposes the two previously absent Skill entries to string-source users. The bodies remain on demand; this is a visible index change, not automatic delegation.

The three names and descriptions total 565 UTF-8 bytes at this candidate, excluding Pi's wrappers and installation-dependent paths. Of these, 354 bytes belong to the two existing orchestration entries newly visible to string-source users. This is a text-size observation, not a token or usage measurement.

Pi retains Session, Skills, trust, tool permissions and Bash cancellation. The model chooses when to navigate or compare evidence. The client enforces protocol bounds, request time limits, response validation and cleanup, and refuses server requests to edit files. Running a language server still executes local code with Bash authority; a read-only protocol client is not a sandbox. Plan Mode's existing command restrictions remain in force.

Snapshots retain the opened text's SHA-256, URI, document version, server command/arguments/reported identity and complete diagnostic occurrences. They do not freeze dependencies, configuration, environment or other documents. Comparison reports observations and ambiguity, never whole-project cleanliness or edit causation. Unsupported, failed, incomplete and incompatible results stay explicit.

## Validation boundary

The candidate CLI resolved both real navigation examples and passed all six diagnostic comparisons against the actual TypeScript server. Every observed request completed and shutdown was acknowledged; the server then returned exit code 1 with `context canceled`. The CLI retains that outcome separately. A response does not prove orderly process termination.

Pi's actual `createBashTool` cancelled an isolated invocation and the controlled server PID disappeared. This checks the existing Bash process-tree path without adding a second supervisor. Portable fixture tests separately exercise timeout cleanup, malformed/oversized frames, unsupported and incomplete reports, UTF-16 positions, edit refusal, abnormal exit and occurrence-preserving comparison.

An actual `npm pack --ignore-scripts` tarball included the Skill and adjacent script. After extraction with no package dependencies installed, Pi 1.2.0's native resource loader discovered the declared Skills and its returned base directory successfully ran the semantic script's help command. A native resource-loading regression runs against the CI-selected Pi host, including the minimum version; Windows fixture lifecycle behavior is also a separate CI gate. Neither is established by the macOS smoke alone.

Raw receipts, exact requests/results, controlled source copies, cancellation and package artifacts remain outside Git under `/Users/tsk/.codex/experiments/openpi-community-2026-11-07/semantic-delivery-v1/`. Its manifest records file hashes. The checked CLI hash is `fb4effecd87115d985d08cf35f5755860f9af68a9b0d4f97914e558b9483f1ba`. Original exploratory counterexamples remain under the sibling `semantic/` evidence directory.

Repository checks, full test totals, independent review and final CI are recorded in the implementation PR once complete. These functional observations are not a formal Benchmark: there is no representative task suite, model-quality experiment or usage comparison.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
"themes": [
"./themes"
],
"skills": [
"./skills/subagents",
"./skills/workflows",
"./skills/semantic-navigation"
],
"image": "https://raw.githubusercontent.com/openpi-dev/openpi/main/assets/openpi-package.png"
},
"dependencies": {
Expand Down
39 changes: 39 additions & 0 deletions skills/semantic-navigation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: semantic-navigation
description: Resolve symbol definitions or references when text search is ambiguous, or compare a file's language-server diagnostics before and after an edit, using an existing local stdio language server.
---

# Semantic navigation

Use Pi's ordinary `bash` tool to run the adjacent `scripts/semantic.mjs` client on demand. The model chooses the question, files and timing; each invocation starts and stops one language server.

Use an already installed server whose command and arguments are established by the project or user. Starting it executes local code with the authority of ordinary Bash. The client sends navigation and diagnostic requests, but is not a sandbox for the server. Pi's tool permissions and Plan Mode policy still apply; Plan Mode does not allow this Node command.

## Run a query

Read the command schema from `node <this-skill-directory>/scripts/semantic.mjs --help`. Send one JSON request on stdin, using a quoted heredoc to preserve literal paths and arguments. Set a Bash timeout longer than the request timeout so the client can finish cleanup.

```sh
node /absolute/path/to/semantic-navigation/scripts/semantic.mjs <<'JSON'
{
"operation": "definition",
"root": "/absolute/project",
"server": {"command": "/absolute/path/to/server", "args": ["--stdio"]},
"document": {"path": "src/example.ts", "languageId": "typescript"},
"position": {"line": 12, "column": 8},
"timeoutMs": 15000
}
JSON
```

Positions supplied to the client are one-based UTF-16 line/column coordinates; returned LSP ranges are zero-based. For `references`, choose `includeDeclaration` explicitly. Use the server's returned URI and range as evidence, then read the target source. A completed empty result means this server returned no locations; it does not prove that no references exist.

The client installs nothing and edits no source. If the server is unavailable, the requested capability is unsupported, or the request fails, retain that outcome and use available source-reading tools. Report the request outcome and process lifecycle separately: a response can complete even when shutdown is abnormal.

## Compare diagnostics

Use `operation: "diagnostics"` for a single-file pull-diagnostics snapshot. Save the returned `snapshot` before editing and collect another afterward with the same root, server and document. Compare them with `operation: "compare"`, supplying the snapshot objects as `before` and `after`.

Interpret the full comparison, including ambiguous groups and both sets of locations. When text changed, identical diagnostic messages can describe different occurrences. A newly observed or resolved diagnostic is an observation, not proof that the edit caused or fixed it.

These snapshots bind the opened text and server identity; they do not freeze project dependencies, configuration or other files. Keep those inputs stable for a useful comparison and disclose changes you know about. A full report covers the requested document only. Unsupported, incomplete, failed or incompatible evidence stays unknown; even an empty full report is not a whole-project check.
Loading
Loading