Skip to content

feat(pi): support user-global extension scope - #4369

Open
luw2007 wants to merge 1 commit into
loopx-project:mainfrom
luw2007:codex/issue-3344-pi-user-scope
Open

luw2007 wants to merge 1 commit into
loopx-project:mainfrom
luw2007:codex/issue-3344-pi-user-scope

Conversation

@luw2007

@luw2007 luw2007 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add explicit --pi-scope {project,user} while preserving project scope as the default
  • install the managed Pi adapter/runtime atomically under ~/.pi/agent/extensions/loopx/ for user scope
  • retain fail-closed ownership handling and document /reload or restart plus project-local private bindings

Closes #3344

Validation

  • python -m pytest -q tests/test_slash_command_install.py -k pi — 8 passed
  • worktree CLI dry-run with --surface pi --pi-scope user — exact global paths returned
  • python examples/slash-command-install-smoke.py — passed
  • loopx canary premerge --from-git-diff — compile/direct checks and subsequent checks passed; examples/install-local-smoke.py timed out at 120s

Boundaries

Only extension code becomes user-global. Project binding state remains under <project>/.loopx/pi/; this grants no repository, network, credential, or merge authority.

Signed-off-by: luw2007 <luw2007@gmail.com>

@steven-kid steven-kid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

详细中文评审

结论:REQUEST_CHANGES。Exact head:79a5aefb965bc22fe632dc84e4bb272ca00a8227;base:9e2b6d425fff9b8b2ebd69a79c3d8491b12eb7b3

[P1] 新 user scope 安装成功后,Pi 无法自动发现扩展入口。 新目录采用子目录布局,但入口仍叫 loopx-goal.ts,没有 index.ts 或 package manifest。核心新增用户路径因此未达成,不能仅凭两个文件存在就批准。

动机

#3344 解决的是每个项目重复安装 Pi 适配器的成本:用户希望只安装一次扩展代码,仍然让各项目独立保留 .loopx/pi/ 绑定状态。原有 project scope 有完整的 managed-marker 与安装处理;扩展现有安装器,比另建全局安装器或手动复制更适合维护。

我阅读了 issue 的维护者收敛意见:保持 project 为默认,user scope 使用 Pi 能发现的目录入口,验证受支持 Pi 的 discovery/module aliasing,并纳入安装/升级/卸载与 readback。此次 PR 的参数设计符合这个方向,但“Pi 能实际发现”是用户结果,不是目录名称或安装 JSON 能替代的检查。

改动思路

CLI 新增 --pi-scope {project,user},handler 把选择传给同一个 install_slash_commands_pi_extension_root 决定项目目录还是用户 .pi/agent/extensions/loopx/;extension 和 runtime 都继续从既有资源包取内容,复用 _target_status、managed marker 与双文件 ownership preflight。默认 all surfaces 仍不包含 Pi,旧 project 范围仍为默认,没有新增 Goal/quota 权限。

本轮对照 base/head 的现有安装器、共享 slash_command_files.py 及未修改的 Pi adapter/runtime。项目绑定仍由 adapter 的 createBindingStore(ctx.cwd) 决定,没有随 extension 文件移到用户目录。以已有 owner 扩展 scope 是合理的最小方案,不需要新增安装数据库。

正向实测:通过真实 LoopX CLI 在隔离目录分别执行 base project、head project、head user 安装,三者都报告成功;base/head project 写出的两个文件逐字节一致。负向发现:Pi v0.83.0 的目录发现逻辑能识别两个 project 安装,却在新 user 根目录返回空列表。由此区分了“安装文件成功”与“host 加载入口成功”。

具体改动

关键代码讲解

  1. cli_commands/slash_commands.py::register_slash_commands_command 增加 scope 枚举和 project 默认值;handle_slash_commands_commandargs.pi_scope 传给安装器。既有 install/uninstall/dry-run 分发路径沿用。
  2. slash_command_install.py::_pi_extension_root 在 user 模式返回用户扩展子目录,而 _pi_extension_path 对两种 scope 都返回 loopx-goal.ts。平铺项目目录能发现该名称,子目录入口规则则不同,问题发生在这两段组合处。
  3. install_slash_commands 新增 scope 与测试可覆盖的 user-home 参数,在写入前计算统一 root;安装、卸载和 summary 路径使用该 root。既有双文件预检查对 user-owned 冲突仍然有效;没有改动内容生成器或 runtime。summary 新增 pi_scope,方便识别目标,但不能证明 host 已加载。
  4. tests/test_slash_command_install.py 增加 user scope 的两个用例:确认两个文件存在/路径正确,以及 runtime 被用户占用时两文件都不写。这些断言证明磁盘布局和冲突前置检查,没有执行 Pi discovery。

docs/guides/getting-started.md 更新 Pi 指南,说明 user scope、reload/restart 与项目私有绑定。四个文件共 +73/-15,均已阅读;没有生成资源变化。指南宣称全项目可用,当前入口缺陷需要先修复。另未见本 PR 实现 issue 提到的 absent/current/stale/dual-scope doctor 读回;安装 summary 的目标路径不能代替 host discovery/状态诊断。

对主干的风险

[P1] user scope 缺少可发现的入口。 位置:loopx/slash_command_install.py:755。Pi v0.83.0 的子目录解析只接受 index.tsindex.js 或 package.json 中声明的 pi.extensions;不会递归找到任意名称的 TS 文件。本次安装写出 loopx/loopx-goal.ts 和 sibling .mjs,三种入口均不存在。

核验使用 Pi v0.83.0 的固定源码 revision 845d6ff1f6643aba440341cce877ce1c43ebbc39,从原始 loader 提取未修改的 isExtensionFileresolveExtensionEntriesdiscoverExtensionsInDir,对真实 CLI 写出的目录执行发现逻辑。结果:base project 与 head project 均发现 loopx-goal.ts,head user 发现 []。只在临时目录把 user 入口改成 index.ts 后,同一发现逻辑立即找到 index.ts,随后恢复临时文件名。这个反例没有 mock 文件存在性,也没有把自定义发现规则当作 Pi 行为;但它仍是 loader 边界验证,不等于启动完整 Pi TUI。

来源:Pi v0.83.0 loader。最小修复是只为 user 子目录使用 index.ts,或交付受管理的 manifest;保持 project 路径兼容,同时让 dry-run、升级、卸载、ownership preflight 和读回指向一致入口。回归应从 LoopX CLI 安装走到支持版本的 host discovery,并进一步验证 /reload/loopx 注册和模块 alias 解析。

验证:Pi 聚焦测试 8 项通过;完整 installer 文件 41 passed;slash-command-install smoke 和 diff check 通过;项目默认文件内容 hash 与 base 一致。完整 Pi 启动/reload、模块 aliasing、用户目录覆盖和多 scope readback 尚未完整验证,不能从写文件测试推断通过。现有安装输出中的固定说明仍写成项目目录,也应在修复 user scope 时按 scope 同步,避免成功回执与指南矛盾。

我的整体评价

参数、owner 和 project-local binding 保持方式都较克制,旧默认安装也有独立的文件内容对照证明。问题不需要更大的架构改造:新增 user path 只差一个正确且被完整生命周期管理的 host entrypoint,但这个差异正好决定整个新增功能是否可用。

因此请求修改,而不是把“文件已写入”认定为全局支持完成。建议保留现有安装器,修正入口并补齐真实 discovery/载入与 readback,尤其保留默认 project 模式、用户文件冲突和卸载的边界。当前批准条件未满足;未来 head 应重新对照完整安装生命周期,不能仅重新跑两个新增路径测试。本评审不包含合并授权。

English verdict: REQUEST_CHANGES at exact head 79a5aef. P1: user-scope installation writes loopx/loopx-goal.ts without index.ts or a pi.extensions manifest, so Pi v0.83.0 does not auto-discover it. The real LoopX CLI reported success, but the unmodified discovery functions from pinned Pi loader revision 845d6ff1f6643aba440341cce877ce1c43ebbc39 returned no user extension; a temporary index.ts rename made it discoverable. Preserve project paths while correcting the managed user entrypoint and lifecycle/readback. All 41 installer tests, the installer smoke and diff check passed; baseline/head project files were byte-identical. Full Pi startup/reload and module alias validation remain unverified. No merge authorization.

@steven-kid

Copy link
Copy Markdown
Collaborator

English verdict: REQUEST_CHANGES at exact head 79a5aef. P1: user-scope installation writes loopx/loopx-goal.ts without index.ts or a pi.extensions manifest, so Pi v0.83.0 does not auto-discover it. The real LoopX CLI reported success, but the unmodified discovery functions from pinned Pi loader revision 845d6ff1f6643aba440341cce877ce1c43ebbc39 returned no user extension; a temporary index.ts rename made it discoverable. Preserve project paths while correcting the managed user entrypoint and lifecycle/readback. All 41 installer tests, the installer smoke and diff check passed; baseline/head project files were byte-identical. Full Pi startup/reload and module alias validation remain unverified. No merge authorization.

This branch has not been deployed

No deployments
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.

[Feature]: Support user-global Pi extension installation

2 participants