Skip to content

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

Merged
huangruiteng merged 5 commits into
loopx-project:mainfrom
luw2007:codex/issue-3344-pi-user-scope
Sep 25, 2026
Merged

huangruiteng merged 5 commits 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

Install Pi extension code once at user scope while keeping each project's private .loopx/pi/ binding local. User scope writes Pi's discoverable extensions/loopx/index.ts entrypoint; project scope remains the default and retains its existing flat entrypoint. The installer follows PI_CODING_AGENT_DIR, manages upgrades and uninstall across both files, and preserves user-owned files.

loopx slash-commands --inspect --surface pi reads both scopes and reports absent, current, stale, partial, or user-owned state, including duplicate-load warnings. This closes the prior review's gap between "files installed" and "Pi can actually load them."

Closes #3344.

Use and validation

loopx slash-commands --install --surface pi --pi-scope user
loopx slash-commands --inspect --surface pi
loopx slash-commands --uninstall --surface pi --pi-scope user

Review repairs in the current head

  • Project scope keeps its per-file uninstall semantics: a user-edited runtime no longer blocks removing the managed adapter. Verified through the real CLI with identical inputs at base a23e0817 and this head - same exit code, same statuses, same file digests, same surviving user file.
  • Deleted the compatibility path for extensions/loopx/loopx-goal.ts. That layout only existed in earlier heads of this pull request and was never in a release, so it had no real consumer.
  • The install note now names the scope it actually used instead of always describing the project directory.

Evidence

  • 51 focused tests and examples/slash-command-install-smoke.py passed; Ruff, git diff --check, py_compile, the maintainability ratchet and the public/private boundary scan passed; the exact-diff change-quality receipt is valid.
  • loopx canary premerge --from-git-diff reported three catalog canaries as timed_out. All three were re-run standalone at base a23e0817 and at this head: examples/install-local-smoke.py fails identically at both revisions with AssertionError: This command is read-only, and the packaged-install and cli-output-budget smokes pass at both, so the timeouts are load-related rather than branch regressions.
  • Against an isolated Pi v0.83.0 install, the actual extension loader discovered and loaded the user entry in two separate projects and on repeated load. The Pi RPC host exposed /loopx plus both LoopX tools from that entry.
  • The global code does not move project binding state or grant repository, credential, network, or merge authority.

Future-facing pass: Pi path and readback rules share one small installation owner, with no separate install database.

@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_command 将 args.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.ts、index.js 或 package.json 中声明的 pi.extensions;不会递归找到任意名称的 TS 文件。本次安装写出 loopx/loopx-goal.ts 和 sibling .mjs,三种入口均不存在。

核验使用 Pi v0.83.0 的固定源码 revision 845d6ff1f6643aba440341cce877ce1c43ebbc39,从原始 loader 提取未修改的 isExtensionFile、resolveExtensionEntries、discoverExtensionsInDir,对真实 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.

@huangruiteng
huangruiteng force-pushed the codex/issue-3344-pi-user-scope branch from 79a5aef to 0c39af7 Compare September 25, 2026 14:37
@huangruiteng

Copy link
Copy Markdown
Collaborator

Rebased the contributor fork branch to exact head 0c39af73b0f4acfabed62aa7eba3490ca629edd7 on main 3e443ad7c285973c40be883293970be6c0c51e06. This addresses the prior Pi discovery review: user scope writes a Pi-discoverable extensions/loopx/index.ts, while the project default keeps its existing entrypoint and each project retains its own .loopx/pi/ binding. The managed install/upgrade/uninstall lifecycle handles both files, the old managed global filename, user-owned conflicts, and PI_CODING_AGENT_DIR. slash-commands --inspect --surface pi reads both scopes and distinguishes absent/current/stale/partial/user-owned and duplicate-load states.

Validation: 54 focused tests, slash-command-install smoke, Ruff, diff check, and actual Pi v0.83.0 extension loader and RPC host checks passed. The real host discovered/loaded the global entry in two projects, survived reload, and exposed /loopx plus both LoopX tools. The exact-diff quality receipt is valid. The broad install-local-smoke.py currently fails with AssertionError: This command is read-only on both this branch and the unchanged main baseline; this is unrelated to Pi scope. Standard premerge passed 18/19 selected checks with no manual holds; its only failure is the identical current-main install-local smoke noted above.

This is ready for a new exact-head maintainer review after CI. No merge performed.

@huangruiteng

Copy link
Copy Markdown
Collaborator

@luw2007 I owe you an apology. I rebased and force-updated your fork branch with a much larger revision without discussing it with you first. That may have disrupted your local work, and I should have coordinated before changing a contributor-owned branch.

Your original user-scope Pi installer and project-local binding are the foundation of this PR. I expanded the managed entrypoint, lifecycle, readback, and real Pi host validation to address the review, while keeping that contribution central. Thank you for starting this work. I'm sorry for the intrusive way I made these changes; if the branch update caused any trouble, I'll help put it right.

@huangruiteng huangruiteng 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.

English verdict: REQUEST_CHANGES — exact head 0c39af73b0f4acfabed62aa7eba3490ca629edd7 fixes the prior Pi discovery P1, but silently changes default project-scope uninstall semantics (base exits 0 and removes the managed extension; head exits 1 and leaves LoopX loaded) and carries compatibility code for a layout that never shipped.

动机

#3344 的诉求是让 Pi 扩展代码只安装一次,同时每个项目仍保留自己的 .loopx/pi/ 绑定。这个方向正确:扩展既有的安装器 owner,而不是另建一套全局安装数据库。上一轮 P1(user scope 写成 loopx/loopx-goal.ts,Pi 无法发现)在本 head 已经修复,user scope 现在写入 extensions/loopx/index.ts,并新增 slash-commands --inspect --surface pi 读回两个 scope 的状态。

改动思路

路径规则收敛到新模块 loopx/pi_goal_mode/installation.py(_pi_agent_dir / _pi_extension_root / _pi_extension_path),安装器与 inspect 共用。--pi-scope 默认仍是 project;user scope 遵循 PI_CODING_AGENT_DIR。inspect 通过 managed marker 与内容比对,区分 absent / current / stale / partial / user_owned,并提示双 scope 重复加载。项目绑定仍由 adapter 按 ctx.cwd 决定,没有新增权限。

具体改动

关键代码讲解

  • install_slash_commands 的 Pi 卸载分支(loopx/slash_command_install.py 约 1320–1370 行):新逻辑先收集 retire_targets 中的用户自有文件;只要有一个,就整体返回 blocked_user_owned_pi_file,两个文件都不删。这个分支对 project 和 user 两个 scope 都生效。
  • legacy_user_path(install、uninstall、inspect 三处):用于退役 extensions/loopx/loopx-goal.ts。
  • inspect_pi_installations:只读取状态,ok 仅在所有 scope 都处于 absent/current 且没有重复加载时为真。

本地验证:tests/test_slash_command_install.py 51 passed;examples/slash-command-install-smoke.py ok。我本地没有 Pi 运行时,所以“真实 Pi 能加载”这一点依赖作者提供的 Pi v0.83.0 验证。

对主干的风险

[P2] 默认 project scope 的卸载语义被改变且未披露

复现(真实 CLI,同一套合成输入):--install --surface pi --pi-project P,然后把 P/.pi/extensions/pi-goal-loop-runtime.mjs 改成用户内容,再执行 --uninstall。

  • base 3e443ad:退出码 0、ok=true;托管的 loopx-goal.ts 被移除,用户的 runtime 文件保留。
  • head:退出码 1、ok=false;loopx-goal.ts 仍在,Pi 继续加载 LoopX adapter,而它导入的是被用户改过的 runtime。

用户因此无法再通过 LoopX 卸载 Pi 集成,只能手动删除。PR 描述说 project scope 保持原样,新增测试也只覆盖 user scope 的卸载阻塞。最小修复:两个 scope 都保留 base 的逐文件语义(移除托管文件,跳过用户文件);如果确实想要原子卸载,就在 PR/文档中披露这个默认行为变化,给出恢复路径,并补上 project scope 的 base/head 对照测试。

[P3] 为从未发布的布局保留兼容代码

extensions/loopx/loopx-goal.ts 只在本 PR 早先的 head 中出现过。main 和 v1.2.0 都没有 Pi user scope(git grep 查不到 pi_scope、.pi/agent 或 PI_CODING_AGENT_DIR)。三处 legacy_user_path 的处理大约 40 行,增加了永久维护成本,却没有真实的外部用户。建议在合并前删除。

CI 归因

红色检查都与 base 相同:registry_io_census ×2、stage2c (installed 0)、Release Artifacts / build 已安装 wheel 检查、node-forward-compatibility 在 20 分钟时取消。没有本 PR 新增的失败。

我的整体评价

REQUEST_CHANGES。核心目标(一次安装、按项目绑定、Pi 可发现、可读回)已基本达成,结构也收敛在一个小 owner 里。在合并之前需要先恢复或明确披露 project scope 的卸载语义,并删除只为未发布布局服务的兼容分支。本 review 不授权合并。

luw2007 and others added 4 commits September 26, 2026 02:02
Signed-off-by: luw2007 <luw2007@gmail.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Review findings on loopx-project#4369 asked for two repairs before merge.

Uninstall now keeps the per-file semantics every other surface uses: a
user-owned Pi file is reported as skipped instead of aborting the whole
scope. The previous atomic abort left the managed adapter loaded while
`loopx slash-commands --uninstall --surface pi` could no longer remove it,
so a user who edited the runtime lost the supported way to uninstall.

The `extensions/loopx/loopx-goal.ts` retirement branch covered a layout
that only existed in earlier heads of this pull request; no released
LoopX ever wrote it, so the compatibility path, its readback field, and
its test are removed.

Verified: 51 installer tests pass, slash-command-install smoke ok, ruff
clean, and the reported project-scope repro now matches base on both
exit code and file outcome with the real CLI.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng force-pushed the codex/issue-3344-pi-user-scope branch from 0c39af7 to 913ec2b Compare September 25, 2026 18:07
The install payload told every caller that the Pi surface lands in the
project's `.pi/extensions/`, which is wrong for `--pi-scope user` and was
left stale when the scope-aware docs were added. The note now names the
scope it actually used, so the CLI readback cannot contradict the file
that was just written.

Verified: 51 installer tests pass (new assertion pins scope=user), the
installer smoke passes, and ruff is clean.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng 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.

详细中文评审

结论:APPROVE。Exact head:6a4e38946ad5fe5222aa25dc136cfc076e06518e;base:a23e08175f38286682eabcf15b41a6bc439954ed。上一轮的两条阻塞(项目 scope 卸载语义被改变、为从未发布的布局保留兼容代码)已在本 head 修复并复验;早前那条 user scope 无法被 Pi 发现的 P1 也已由当前入口修正。

动机

#3344 的诉求是让 Pi 适配器只安装一次,同时每个项目继续保留自己的 .loopx/pi/ 绑定。base 只有 project scope:--pi-scope 会被参数解析直接拒绝,也没有任何读回命令,用户想让 Pi 全局可用只能手工把两个文件拷进用户扩展目录,于是失去托管标记、升级和卸载生命周期。本 head 交付了 --pi-scope user(默认仍是 project)与 slash-commands --inspect --surface pi 读回;默认路径写出的文件内容与状态和 base 逐字节一致,所以这是一个可独立验收、可回退的完整切片,而不是把后续工作切碎的前置准备。

改动思路

入口仍是既有的 loopx slash-commands,写路径全部留在 install_slash_commands,读路径新增只读的 inspect_pi_installations;scope 只决定扩展根目录和入口文件名,扩展源码与 runtime 仍由 pi_goal_mode 提供,托管标记、目标状态和退役状态继续复用 slash_command_files.py 的既有 helper。权威输入只是磁盘上的两个文件与 PI_CODING_AGENT_DIR,没有新增数据库、没有新增持久状态,因此不存在第二个安装权威。正向路径是 project/user 任选其一安装并升级;负向路径是同名文件没有托管标记时零写入并报告冲突,卸载只退役带标记的文件。之前分散在安装器里的 Pi 路径函数已并入 pi_goal_mode/installation.py,同一份路径知识现在只有一处。

具体改动

关键代码讲解

  1. loopx/pi_goal_mode/installation.py:29 _pi_extension_path:user scope 使用子目录入口 index.ts,因为 Pi 对扩展子目录只认 index.ts/index.js/manifest;project scope 保持原来的 loopx-goal.ts,runtime 名称两个 scope 相同。这条差异正是早前 P1 的修复核心。
  2. loopx/pi_goal_mode/installation.py:39 inspect_pi_installations:只读,按“文件是否齐全、是否带托管标记、内容是否等于当前源码”判定 absent/partial/user_owned/current/stale,并在两个 scope 同时存在可加载入口时给出重复加载警告;不写任何文件。
  3. loopx/slash_command_install.py:1316(install_slash_commands 的 Pi 分支):安装保持双文件原子预检,任一同名文件非托管就零写入并报告 blocked_user_owned_pi_file;卸载已恢复为逐文件语义,删除托管文件、把用户文件记为 skipped_user_file,与其它 surface 的 skip policy 一致。上一轮 P2 提出的“用户改过 runtime 后无法再通过 LoopX 卸载”在这一版不再成立。
  4. loopx/cli_commands/slash_commands.py:141 handle_slash_commands_command:--inspect 只接受 --surface pi,且与 --dry-run、--with-goal-bridge 互斥,避免把只读读回和写入操作混在一起;--pi-scope 直接透传给安装器;--dry-run 会打印选中的 scope 与目标路径且不写盘。
  5. 安装回执里的说明文本现在按 scope 生成,不再对 user scope 声称写进了项目目录。

测试面:tests/test_slash_command_install.py 覆盖 user scope 原子安装、用户文件冲突零写入、升级、PI_CODING_AGENT_DIR 覆盖、读回状态矩阵(absent/stale/partial/dual-scope)、user scope 卸载保留用户 runtime 并删除托管入口,以及本轮的默认 project scope 回归(改过 runtime 后仍能卸载)。

对主干的风险

上一轮 P2 已用真实 CLI 在 base 与 head 各跑一遍同样的合成输入复验:安装后把 runtime 改成用户内容再卸载,两个版本的退出码、ok、状态码、托管入口被删除、用户文件被保留完全一致。上一轮 P3 指出的兼容分支(extensions/loopx/loopx-goal.ts)在本 head 已整体删除,它只在本 PR 早先的 head 中出现过,main 与任何发布版本都没有写过该布局,因此删除不会影响既有用户。

仍然存在的风险与未验证项:

  • user scope 的“Pi 能发现 index.ts”依赖 host 的 loader 语义,仓库内没有测试能钉住这一点;证据是作者用固定版本 Pi 的真实 loader 与 RPC host 跑通的结论,本轮没有重跑完整 Pi TUI 会话,属未验证维度。
  • --inspect 在托管入口缺失、只剩用户 runtime 时报 partial 而不是 user_owned,两种状态都不是成功,且同时打印原始路径,属于读回粒度问题,不影响安全边界。
  • 卸载跳过用户文件后会留下一个孤儿 runtime 文件;这与 base 一致,是 skip policy 的既有定义,文档已写明。
  • 按 goal 策略本轮不查询、不等待远端 CI,因此远端红灯与否不作为评审证据;失败归因需要另立。

本 head 中的修复提交是维护者在评审前加入该分支的,作者原有的 user scope 设计与项目绑定改动仍在提交历史中保留。

我的整体评价

APPROVE。problem_context 的 long_horizon 与 user_experience 都是 improved:不再需要逐项目重复安装和手工拷贝,读回让用户能区分缺失、过期、部分安装和用户自有文件。observable_semantics 为 intentional_change_validated:默认 project 路径的文件字节与 base 一致,卸载状态与 base 一致;唯一有意的差异是 base 直接拒绝 --pi-scope,head 接受它。default_off_isolation 为 isolated:不传 --pi-scope 时行为与 base 相同。code_volume 与 change_proportionality 为必要/相称:生产侧只多了一个小模块和一条 CLI 选项,兼容分支被删除,净增集中在测试与文档。新选项不改变权限、quota 或 Goal 生命周期,只把扩展代码放到用户扩展目录,项目绑定仍在项目内;authority_semantics 的名称与实现范围一致。

合并授权来自维护者,本评审只说明该 exact head 的批准条件已经满足。

English verdict: APPROVE - exact head 6a4e389 on base a23e081. The prior project-scope uninstall regression is repaired (real-CLI base/head parity on exit code, statuses and file outcome) and the never-shipped legacy user-entry compatibility branch is deleted. User scope writes Pi's discoverable index.ts, inspect reads absent/partial/stale/user-owned/current for both scopes, and default project scope keeps byte-identical files and statuses. Validation: 51 focused installer tests, installer smoke, ruff, diff check, and a real base/head CLI comparison. Unverified: no in-repo host-discovery test for Pi's loader, and remote CI was not consulted by goal policy. Merge authority comes from the maintainer, not from this review.

@huangruiteng
huangruiteng dismissed stale reviews from steven-kid and themself September 25, 2026 18:44

Superseded by the reviewed exact head 6a4e389: the prior user-scope discovery P1 was fixed in the branch, and the project-scope uninstall regression and never-shipped legacy compatibility path raised in the later review were repaired and re-validated at that head.

@huangruiteng
huangruiteng merged commit d30c831 into loopx-project:main Sep 25, 2026
7 of 8 checks passed
@huangruiteng

Copy link
Copy Markdown
Collaborator

Self-merge decision record for exact head 6a4e38946ad5fe5222aa25dc136cfc076e06518e (base a23e08175f38286682eabcf15b41a6bc439954ed).

Changed surfaces: the Pi installer branch in loopx/slash_command_install.py, the new scope/readback module loopx/pi_goal_mode/installation.py, the slash-commands CLI option handling in loopx/cli_commands/slash_commands.py, the Pi documentation, and tests/test_slash_command_install.py.

Repairs carried by this head:

  • Project scope keeps its per-file uninstall semantics. The real CLI was run with identical inputs at base and at this head (install, replace the runtime with user content, uninstall): same exit code, same ok, same statuses, same file digests, managed adapter removed and the user file preserved. The earlier head exited 1 and left the managed adapter loaded.
  • The compatibility path for extensions/loopx/loopx-goal.ts was deleted. That layout only existed in earlier heads of this pull request and was never released.
  • The install note now names the scope it used instead of always describing the project directory.

Validation: 51 focused installer tests, examples/slash-command-install-smoke.py, Ruff, git diff --check, and the exact-diff change-quality receipt (cqr_c9c560bd01d7c1be69f6, state valid). loopx canary premerge --from-git-diff passed its direct checks, risk-profile smokes and public/private boundary scan; three catalog canaries reported timed_out, and all three were re-run standalone at base and at this head - examples/install-local-smoke.py fails identically at both revisions with AssertionError: This command is read-only, and the packaged-install and cli-output-budget smokes pass at both, so the timeouts are load-related, not branch regressions. Remote CI was not consulted because the goal resolves wait_for_ci=false; the Release Artifacts / build failure is the same as on the unchanged base.

Review record: an exact-head review was published as APPROVE on this commit. The two stale CHANGES_REQUESTED reviews were dismissed with a message pointing at this head. Merge state stayed BLOCKED because the repository ruleset requires require_last_push_approval, and the last push to this branch was made by the reviewing maintainer after the contributor's rebase, so no second approver was available. Admin bypass was used under owner authorization for this pull request; the merged tree equals the reviewed head tree (4d4e8abc7b62ef406fc82c5964c3af0bf80bbb40), so the merge introduced no content that was not reviewed at that exact head.

Residual risk carried forward: Pi host discovery of the user-scope index.ts entry is evidenced by a pinned Pi host run rather than a repository test, and --inspect reports partial rather than user_owned when only a user-owned file survives.

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

3 participants