HOMELAB-1609: feat(extensions): vendor skill-args, todo, and ask-user-question from @juicesharp/* #37

Merged
aaron merged 5 commits from plane/HOMELAB-1609-ext into main 2026-09-20 17:54:37 +00:00
Owner

What

Extension-port leg of HOMELAB-1609 (uninstall @juicesharp/rpiv-* pi packages after porting the used surface). Vendors the MIT-licensed source of three npm packages into this repo as first-class extensions:

new dir source surface
skill-args/ @juicesharp/rpiv-args /skill: expansion engine (input + before_agent_start hooks)
todo/ @juicesharp/rpiv-todo todo tool + /todos command + overlay widget
ask-user-question/ @juicesharp/rpiv-ask-user-question ask_user_question tool (full UI + RPC fallback + external editor)

De-rpiv'ing (no @juicesharp/* imports remain)

  • rpiv-config → inlined local-config.ts per package (loadJsonConfigWithLegacyFallback, validateGuidanceFields, GuidanceFields). XDG path resolution, legacy ~/.config/<name>/config.json fallback, and validateGuidanceFields semantics are byte-identical. Config dir names stay rpiv-todo / rpiv-ask-user-question on purpose, so existing user configs keep working.
  • rpiv-i18n → stripped. Both state/i18n-bridge.ts files are a constant English identity passthrough — exactly the behavior that already ran when the optional SDK was absent. The rpiv-i18n/loader registration block and the now-inert locales/ directories were removed.
  • No rpiv-pi / rpiv-core imports existed in any of the three packages (verified by grep).
  • Tool names todo / ask_user_question and command name todos are unchanged; skill-args preserves the byte-exact <skill name=… location=…> wrapper, the Skill input: trailer, $N/$ARGUMENTS gating, always-on ${SKILL_DIR}/${SESSION_ID} and shell substitution, block-output masking, and the shell-timeout frontmatter override (0 = disable).

Verification (run in this worktree)

skill-args:           tsc --noEmit → exit 0   vitest run → 36 passed (2 files)
todo:                 tsc --noEmit → exit 0   vitest run →  4 passed (1 file)
ask-user-question:    tsc --noEmit → exit 0   vitest run →  4 passed (1 file)

skill-args/tests/args-pipeline.test.ts is the migration safety net: 32 tests over the full expansion pipeline (substitution, shell execution order, block masking, timeout resolution, wrapper byte-format). Smoke tests in each package assert the default export registers the expected tool/command/handler names against a mock ExtensionAPI.

CI: three new typecheck + npm test jobs in .forgejo/workflows/ci.yaml, mirroring the existing packages.

Not in this PR

  • pi-skills/ + pi-swarm-suite/agents/ (owned by the parallel skills/agents worktree).
  • Actual npm uninstall of the @juicesharp/* packages, settings.json edits, and live boot verification (orchestrator, post-merge).

Notes for the orchestrator

  • ~/.pi/agent/settings.json still lists the external @juicesharp/* packages, so the live boot will not pick these vendored copies up until the uninstall/settings step lands. Do not expect duplicate-tool protection from the vendored dirs alone.
  • rpiv-pi's siblings.ts registry does name rpiv-ask-user-question, rpiv-todo, and rpiv-args; once they are removed from settings, rpiv-pi reports them as missing plugins and /rpiv-setup would try to reinstall them. If rpiv-pi is also being uninstalled this is moot; otherwise its sibling registry needs reconciling.
## What Extension-port leg of HOMELAB-1609 (uninstall `@juicesharp/rpiv-*` pi packages after porting the used surface). Vendors the MIT-licensed source of three npm packages into this repo as first-class extensions: | new dir | source | surface | |---|---|---| | `skill-args/` | `@juicesharp/rpiv-args` | `/skill:` expansion engine (`input` + `before_agent_start` hooks) | | `todo/` | `@juicesharp/rpiv-todo` | `todo` tool + `/todos` command + overlay widget | | `ask-user-question/` | `@juicesharp/rpiv-ask-user-question` | `ask_user_question` tool (full UI + RPC fallback + external editor) | ## De-rpiv'ing (no `@juicesharp/*` imports remain) - `rpiv-config` → inlined `local-config.ts` per package (`loadJsonConfigWithLegacyFallback`, `validateGuidanceFields`, `GuidanceFields`). XDG path resolution, legacy `~/.config/<name>/config.json` fallback, and `validateGuidanceFields` semantics are byte-identical. Config dir names stay `rpiv-todo` / `rpiv-ask-user-question` on purpose, so existing user configs keep working. - `rpiv-i18n` → stripped. Both `state/i18n-bridge.ts` files are a constant English identity passthrough — exactly the behavior that already ran when the optional SDK was absent. The `rpiv-i18n/loader` registration block and the now-inert `locales/` directories were removed. - No `rpiv-pi` / `rpiv-core` imports existed in any of the three packages (verified by grep). - Tool names `todo` / `ask_user_question` and command name `todos` are unchanged; `skill-args` preserves the byte-exact `<skill name=… location=…>` wrapper, the `Skill input:` trailer, `$N`/`$ARGUMENTS` gating, always-on `${SKILL_DIR}`/`${SESSION_ID}` and shell substitution, block-output masking, and the `shell-timeout` frontmatter override (0 = disable). ## Verification (run in this worktree) ``` skill-args: tsc --noEmit → exit 0 vitest run → 36 passed (2 files) todo: tsc --noEmit → exit 0 vitest run → 4 passed (1 file) ask-user-question: tsc --noEmit → exit 0 vitest run → 4 passed (1 file) ``` `skill-args/tests/args-pipeline.test.ts` is the migration safety net: 32 tests over the full expansion pipeline (substitution, shell execution order, block masking, timeout resolution, wrapper byte-format). Smoke tests in each package assert the default export registers the expected tool/command/handler names against a mock `ExtensionAPI`. CI: three new `typecheck` + `npm test` jobs in `.forgejo/workflows/ci.yaml`, mirroring the existing packages. ## Not in this PR - `pi-skills/` + `pi-swarm-suite/agents/` (owned by the parallel skills/agents worktree). - Actual `npm uninstall` of the `@juicesharp/*` packages, settings.json edits, and live boot verification (orchestrator, post-merge). ## Notes for the orchestrator - `~/.pi/agent/settings.json` still lists the external `@juicesharp/*` packages, so the live boot will not pick these vendored copies up until the uninstall/settings step lands. Do not expect duplicate-tool protection from the vendored dirs alone. - `rpiv-pi`'s `siblings.ts` registry *does* name `rpiv-ask-user-question`, `rpiv-todo`, and `rpiv-args`; once they are removed from settings, rpiv-pi reports them as missing plugins and `/rpiv-setup` would try to reinstall them. If rpiv-pi is also being uninstalled this is moot; otherwise its sibling registry needs reconciling.
MIT-licensed port of @juicesharp/rpiv-args with no @juicesharp/*
runtime imports (the package had none). Preserves the full expansion
pipeline byte-for-byte: $N/$ARGUMENTS gated by TOKEN_REGEX,
${SKILL_DIR}/${SESSION_ID} always-on, inline !`cmd` and fenced ! shell
substitution with block-output masking, 120s default timeout with
per-skill shell-timeout frontmatter override (0 = disable), the exact
<skill name=... location=...> wrapper, the 'Skill input:' trailer, and
the before_agent_start skill-invocation protocol.

Adds package.json/tsconfig/vitest config mirroring pi-swarm-suite, plus
36 tests (smoke + full pipeline).
MIT-licensed port of @juicesharp/rpiv-todo. Tool name `todo`, command
name `/todos`, and widget key `rpiv-todos` are preserved verbatim
(load-bearing in session history and 237/831 recorded sessions).

De-rpiv'ed:
- config.ts now imports the inlined ./local-config.ts instead of
  @juicesharp/rpiv-config; XDG path resolution, legacy ~/.config
  fallback, defaults, and validateGuidanceFields are byte-identical.
- state/i18n-bridge.ts is a constant English identity passthrough
  (exactly what ran before when the optional i18n SDK was absent);
  the `@juicesharp/rpiv-i18n/loader` registration block and the inert
  locales/ directory are removed.

Adds package.json/tsconfig/vitest config mirroring pi-swarm-suite plus
smoke tests (tool + command + lifecycle handler registration).
MIT-licensed port of @juicesharp/rpiv-ask-user-question. Tool name
`ask_user_question` is preserved verbatim (load-bearing in session
history and 270/831 recorded sessions). Full UI, RPC fallback, and
external-editor paths are unchanged.

De-rpiv'ed:
- config.ts now imports the inlined ./local-config.ts instead of
  @juicesharp/rpiv-config; XDG path resolution, legacy ~/.config
  fallback, defaults, and validateGuidanceFields are byte-identical.
- state/i18n-bridge.ts is a constant English identity passthrough
  (exactly what ran before when the optional i18n SDK was absent);
  the `@juicesharp/rpiv-i18n/loader` registration block and the inert
  locales/ directory are removed.

Adds package.json/tsconfig/vitest config mirroring pi-swarm-suite plus
smoke tests (tool + reconciler registration and strip/restore behavior).
HOMELAB-1609: ci(forgejo): gate the three vendored extension packages
All checks were successful
CI / pr-title (pull_request) Successful in 1s
CI / pi-swarm-suite (pull_request) Successful in 2m44s
CI / pi-otel-telemetry (pull_request) Successful in 42s
CI / skill-args (pull_request) Successful in 27s
CI / todo (pull_request) Successful in 28s
CI / ask-user-question (pull_request) Successful in 38s
99e57f7214
Adds typecheck + vitest jobs for skill-args, todo, and ask-user-question
(same shape as the pi-swarm-suite / pi-otel-telemetry jobs) and lists
the three new first-class extensions in the README table with their
vendoring provenance.
Author
Owner

CI green on 99e57f7: .forgejo/workflows/ci.yaml run "HOMELAB-1609: ci(forgejo): gate the three vendored extension packages" → [success] (pr-title + skill-args + todo + ask-user-question all passed; existing pi-swarm-suite / pi-otel-telemetry jobs untouched).

Local reproduction in the worktree (paste from the leg report):

  • skill-args: tsc --noEmit exit 0 · vitest run → 36 passed (2 files)
  • todo: tsc --noEmit exit 0 · vitest run → 4 passed (1 file)
  • ask-user-question: tsc --noEmit exit 0 · vitest run → 4 passed (1 file)
CI green on `99e57f7`: `.forgejo/workflows/ci.yaml` run **"HOMELAB-1609: ci(forgejo): gate the three vendored extension packages" → [success]** (`pr-title` + `skill-args` + `todo` + `ask-user-question` all passed; existing `pi-swarm-suite` / `pi-otel-telemetry` jobs untouched). Local reproduction in the worktree (paste from the leg report): - `skill-args`: `tsc --noEmit` exit 0 · `vitest run` → 36 passed (2 files) - `todo`: `tsc --noEmit` exit 0 · `vitest run` → 4 passed (1 file) - `ask-user-question`: `tsc --noEmit` exit 0 · `vitest run` → 4 passed (1 file)
Author
Owner

Independent review verdict — HOMELAB-1609 extension port (PR #37, head 99e57f7)

Verdict: APPROVE — no blockers. CI green on the head commit; merging.

Two fresh-context reviewers ran independently (separate pi -p --no-session processes, primary sources only: the diff, the checked-out branch, the upstream MIT packages at ~/.pi/agent/npm/node_modules/@juicesharp/*). Both returned no blockers; the landing worker independently reproduced the load-bearing checks below. Reviewer ≠ implementer.

Verified with commands (not claims)

Check Result
Head-commit status GET /commits/99e57f7…/status → state: success, 6/6 contexts (pr-title, pi-swarm-suite, pi-otel-telemetry, skill-args, todo, ask-user-question)
Local reproduction npm ci && npx tsc --noEmit && npx vitest run per package → tsc exit 0 ×3; skill-args 36 passed (2 files), todo 4 passed, ask-user-question 4 passed — matches the PR body exactly
Full-package diff vs upstream diff -rq ~/.pi/agent/npm/node_modules/@juicesharp/rpiv-{args,todo,ask-user-question} <vendored> → only index.ts, package.json, state/i18n-bridge.ts, config.ts differ (+ new tests/tsconfig/vitest.config/local-config.ts; locales/ removed)
skill-args/args.ts md5sum → 78544b68f06f78c0e26dfcb18c4e98bb on both sides — byte-identical, so the wrapper format, Skill input: trailer, $N/$ARGUMENTS gating, always-on ${SKILL_DIR}/${SESSION_ID}, inline+fenced shell, block-output masking and shell-timeout resolution are preserved by construction
config.ts hunks import-line only (@juicesharp/rpiv-config → ./local-config.js); config dir names preserved ("rpiv-todo", "rpiv-ask-user-question")
local-config.ts resolveConfigDir inlines process.env.XDG_CONFIG_HOME?.trim() ≡ upstream readEnvVar(...); expandTilde/legacyConfigPath/loadJsonConfigWithLegacyFallback/validateGuidanceFields logic-identical; the un-vendored surface (saveJsonConfig, validateConfig, modelKey, parseModelKey) is referenced nowhere — reduced write surface
De-rpiv zero @juicesharp imports/requires/dynamic-imports in all .ts; 0 occurrences in all three lockfiles; clean npm ci pulls no @juicesharp package. The remaining occurrences are comments, package.json descriptions, or docs (the allowed MIT-attribution class)
Tool/command names TOOL_NAME = "todo", COMMAND_NAME = "todos" (todo/tool/types.ts:11,13), ASK_USER_QUESTION_TOOL_NAME = "ask_user_question" (ask-user-question/ask-user-question.ts:74); widget key "rpiv-todos" preserved (todo/todo-overlay.ts:23)
i18n strip both bridges are a constant English identity passthrough; I18N_NAMESPACE consumers and the rpiv-i18n/loader block removed; no locales/registerLocalesFromDir references remain; locales/ dirs gone
Scope git diff --name-status main...HEAD → 94 added, 2 modified (.forgejo/workflows/ci.yaml, README.md), 0 deleted; no node_modules committed
Differential config harness (reviewer) vendored local-config vs real rpiv-config@2.10.1 over XDG/legacy/malformed/tilde/relative edge cases → 6/6 identical; 12-case loadJsonConfig corpus and 30-case hostile validateGuidanceFields corpus → identical; every t(key, fallback) cross-checked against the shipped en.json → 0 mismatches

Concerns (non-blocking, for follow-up)

  1. Coverage is inverted relative to risk. The four files with genuine behavior change ({todo,ask-user-question}/config.ts + state/i18n-bridge.ts) have zero tests, while 32 tests protect skill-args/args.ts — a file that was not modified and has no @juicesharp dependency upstream. Both reviewers closed the gap externally (differential harness above), but the repo's own evidence for two acceptance criteria is currently a comment. A ~10-case matrix with a temp HOME/XDG_CONFIG_HOME would pin it after the upstream reference is gone.
  2. "Byte-identical" is overstated for one observable string. todo/local-config.ts:107 / ask-user-question/local-config.ts:107 warn local-config: invalid JSON at … where upstream emitted rpiv-config: …. Behaviorally inert; log greps change. Related doc drift: todo/docs/configuration.md:23 and ask-user-question/docs/configuration.md:50 still quote the old rpiv-config: string.
  3. Vendored docs describe functionality this PR removed (they are verbatim upstream copies): todo/README.md:65,115, todo/docs/overlay.md:118,126,128, ask-user-question/README.md:89, ask-user-question/docs/localization.md — all promise nine bundled locales and pi install npm:@juicesharp/rpiv-i18n chrome. No locales ship and no registration path exists any more. A three-line "Vendored — the install instructions below refer to upstream" header per README would resolve it.
  4. Stale doc import example: ask-user-question/docs/tool-schema.md:113 still shows from "@juicesharp/rpiv-ask-user-question/events" for an event contract that now lives in ./events.ts.
  5. Root README self-contradiction: lines 20-21 still list @juicesharp/rpiv-todo/-args as "installed separately … not part of this repo" while lines 37-44 add them as repo members.
  6. No upstream version pinned anywhere in the vendored copies (they are 2.10.1). The repo precedent pins it: NOTICE:6-7 records @tintinweb/pi-subagents v0.10.3 for pi-swarm-suite. Since byte-exactness is the acceptance criterion, the source release should be recorded before the npm packages are uninstalled. (MIT attribution itself is satisfied: per-dir LICENSE files are the genuine upstream MIT text with Copyright (c) 2026 juicesharp, plus description/header attribution.)
  7. NOTICE not updated to list the three new vendored packages, unlike the existing pi-swarm-suite entry.
  8. i18n-comment rationale is inaccurate: the bridges say the identity passthrough is "exactly the behavior the extension already exhibited when the SDK was absent", but @juicesharp/rpiv-i18n was installed and the loader was registering locales. The defensible justification is what was verified: no ~/.config/rpiv-i18n/locale.json exists, the active locale is undefined, and en.json is byte-identical to every inline fallback → zero visible change today. Residual loss: /languages for these two namespaces.
  9. The three new CI jobs are not self-gating. They run and pass, but Forgejo branch protection must actually list skill-args / todo / ask-user-question as required checks or a red run still merges. Not verifiable from the repo (read-only review).
  10. Uninstall sequencing (disclosed in the PR body, must stay atomic). ~/.pi/agent/extensions is a separate clone of this repo, so pulling it loads these three dirs while settings.json still lists the npm packages → todo / ask_user_question register twice until the npm uninstall + settings step lands. skill-args is already safe there (args.ts WRAPPED_PREFIX re-entrancy guard). pi's exact behavior on two same-name tools is unverified; the orchestrator step must remove the npm entries and settings lines atomically.
  11. Minor: skill-args's session_start index invalidation on reason: "reload"|"startup" is asserted only for handler count (smoke.test.ts:30); the /reload re-enumeration path is unasserted.

Deferred acceptance legs (named, not silently skipped)

  • Live pi boot of the three vendored dirs — deferred to the orchestrator's uninstall/settings step; loading them in a real session requires touching settings.json, which this landing must not do.
  • Non-English locale behavior — not observable in this environment (no locale.json), so i18n equivalence is verified for the current configuration, not in general (accepted by the frozen criterion).
  • Duplicate same-name tool resolution — unverified; see concern 10.
## Independent review verdict — HOMELAB-1609 extension port (PR #37, head `99e57f7`) **Verdict: APPROVE — no blockers. CI green on the head commit; merging.** Two fresh-context reviewers ran independently (separate `pi -p --no-session` processes, primary sources only: the diff, the checked-out branch, the upstream MIT packages at `~/.pi/agent/npm/node_modules/@juicesharp/*`). Both returned **no blockers**; the landing worker independently reproduced the load-bearing checks below. Reviewer ≠ implementer. ### Verified with commands (not claims) | Check | Result | |---|---| | Head-commit status | `GET /commits/99e57f7…/status` → **state: success**, 6/6 contexts (pr-title, pi-swarm-suite, pi-otel-telemetry, **skill-args**, **todo**, **ask-user-question**) | | Local reproduction | `npm ci && npx tsc --noEmit && npx vitest run` per package → tsc exit 0 ×3; **skill-args 36 passed (2 files)**, todo 4 passed, ask-user-question 4 passed — matches the PR body exactly | | Full-package diff vs upstream | `diff -rq ~/.pi/agent/npm/node_modules/@juicesharp/rpiv-{args,todo,ask-user-question} <vendored>` → only `index.ts`, `package.json`, `state/i18n-bridge.ts`, `config.ts` differ (+ new tests/tsconfig/vitest.config/local-config.ts; `locales/` removed) | | `skill-args/args.ts` | `md5sum` → `78544b68f06f78c0e26dfcb18c4e98bb` on **both** sides — byte-identical, so the wrapper format, `Skill input:` trailer, `$N`/`$ARGUMENTS` gating, always-on `${SKILL_DIR}`/`${SESSION_ID}`, inline+fenced shell, block-output masking and `shell-timeout` resolution are preserved **by construction** | | `config.ts` hunks | import-line only (`@juicesharp/rpiv-config` → `./local-config.js`); config dir names preserved (`"rpiv-todo"`, `"rpiv-ask-user-question"`) | | `local-config.ts` | `resolveConfigDir` inlines `process.env.XDG_CONFIG_HOME?.trim()` ≡ upstream `readEnvVar(...)`; `expandTilde`/`legacyConfigPath`/`loadJsonConfigWithLegacyFallback`/`validateGuidanceFields` logic-identical; the un-vendored surface (`saveJsonConfig`, `validateConfig`, `modelKey`, `parseModelKey`) is referenced nowhere — reduced write surface | | De-rpiv | zero `@juicesharp` imports/requires/dynamic-imports in all `.ts`; **0** occurrences in all three lockfiles; clean `npm ci` pulls no `@juicesharp` package. The remaining occurrences are comments, `package.json` descriptions, or docs (the allowed MIT-attribution class) | | Tool/command names | `TOOL_NAME = "todo"`, `COMMAND_NAME = "todos"` (`todo/tool/types.ts:11,13`), `ASK_USER_QUESTION_TOOL_NAME = "ask_user_question"` (`ask-user-question/ask-user-question.ts:74`); widget key `"rpiv-todos"` preserved (`todo/todo-overlay.ts:23`) | | i18n strip | both bridges are a constant English identity passthrough; `I18N_NAMESPACE` consumers and the `rpiv-i18n/loader` block removed; no `locales`/`registerLocalesFromDir` references remain; `locales/` dirs gone | | Scope | `git diff --name-status main...HEAD` → 94 added, **2 modified** (`.forgejo/workflows/ci.yaml`, `README.md`), 0 deleted; no `node_modules` committed | | Differential config harness (reviewer) | vendored `local-config` vs real `rpiv-config@2.10.1` over XDG/legacy/malformed/tilde/relative edge cases → 6/6 identical; 12-case `loadJsonConfig` corpus and 30-case hostile `validateGuidanceFields` corpus → identical; every `t(key, fallback)` cross-checked against the shipped `en.json` → 0 mismatches | ### Concerns (non-blocking, for follow-up) 1. **Coverage is inverted relative to risk.** The four files with genuine behavior change (`{todo,ask-user-question}/config.ts` + `state/i18n-bridge.ts`) have **zero** tests, while 32 tests protect `skill-args/args.ts` — a file that was not modified and has no `@juicesharp` dependency upstream. Both reviewers closed the gap externally (differential harness above), but the repo's own evidence for two acceptance criteria is currently a comment. A ~10-case matrix with a temp `HOME`/`XDG_CONFIG_HOME` would pin it after the upstream reference is gone. 2. **"Byte-identical" is overstated for one observable string.** `todo/local-config.ts:107` / `ask-user-question/local-config.ts:107` warn `local-config: invalid JSON at …` where upstream emitted `rpiv-config: …`. Behaviorally inert; log greps change. Related doc drift: `todo/docs/configuration.md:23` and `ask-user-question/docs/configuration.md:50` still quote the old `rpiv-config:` string. 3. **Vendored docs describe functionality this PR removed** (they are verbatim upstream copies): `todo/README.md:65,115`, `todo/docs/overlay.md:118,126,128`, `ask-user-question/README.md:89`, `ask-user-question/docs/localization.md` — all promise nine bundled locales and `pi install npm:@juicesharp/rpiv-i18n` chrome. No locales ship and no registration path exists any more. A three-line "Vendored — the install instructions below refer to upstream" header per README would resolve it. 4. **Stale doc import example:** `ask-user-question/docs/tool-schema.md:113` still shows `from "@juicesharp/rpiv-ask-user-question/events"` for an event contract that now lives in `./events.ts`. 5. **Root README self-contradiction:** lines 20-21 still list `@juicesharp/rpiv-todo`/`-args` as "installed separately … **not** part of this repo" while lines 37-44 add them as repo members. 6. **No upstream version pinned** anywhere in the vendored copies (they are `2.10.1`). The repo precedent pins it: `NOTICE:6-7` records `@tintinweb/pi-subagents v0.10.3` for `pi-swarm-suite`. Since byte-exactness is the acceptance criterion, the source release should be recorded before the npm packages are uninstalled. (MIT attribution itself **is** satisfied: per-dir `LICENSE` files are the genuine upstream MIT text with `Copyright (c) 2026 juicesharp`, plus `description`/header attribution.) 7. **`NOTICE` not updated** to list the three new vendored packages, unlike the existing `pi-swarm-suite` entry. 8. **i18n-comment rationale is inaccurate:** the bridges say the identity passthrough is "exactly the behavior the extension already exhibited when the SDK was absent", but `@juicesharp/rpiv-i18n` **was** installed and the loader **was** registering locales. The defensible justification is what was verified: no `~/.config/rpiv-i18n/locale.json` exists, the active locale is `undefined`, and `en.json` is byte-identical to every inline fallback → zero visible change today. Residual loss: `/languages` for these two namespaces. 9. **The three new CI jobs are not self-gating.** They run and pass, but Forgejo branch protection must actually list `skill-args` / `todo` / `ask-user-question` as required checks or a red run still merges. Not verifiable from the repo (read-only review). 10. **Uninstall sequencing (disclosed in the PR body, must stay atomic).** `~/.pi/agent/extensions` is a separate clone of this repo, so pulling it loads these three dirs while `settings.json` still lists the npm packages → `todo` / `ask_user_question` register twice until the npm uninstall + settings step lands. `skill-args` is already safe there (`args.ts` `WRAPPED_PREFIX` re-entrancy guard). pi's exact behavior on two same-name tools is unverified; the orchestrator step must remove the npm entries and settings lines atomically. 11. **Minor:** `skill-args`'s `session_start` index invalidation on `reason: "reload"|"startup"` is asserted only for handler count (`smoke.test.ts:30`); the `/reload` re-enumeration path is unasserted. ### Deferred acceptance legs (named, not silently skipped) - Live pi boot of the three vendored dirs — deferred to the orchestrator's uninstall/settings step; loading them in a real session requires touching `settings.json`, which this landing must not do. - Non-English locale behavior — not observable in this environment (no `locale.json`), so i18n equivalence is verified for the current configuration, not in general (accepted by the frozen criterion). - Duplicate same-name tool resolution — unverified; see concern 10.
HOMELAB-1609: merge main into plane/HOMELAB-1609-ext
All checks were successful
CI / pr-title (pull_request) Successful in 0s
CI / pi-swarm-suite (pull_request) Successful in 2m51s
CI / pi-otel-telemetry (pull_request) Successful in 27s
CI / skill-args (pull_request) Successful in 22s
CI / todo (pull_request) Successful in 27s
CI / ask-user-question (pull_request) Successful in 31s
72e625a76e
Main advanced to 901fe7a (PR #36, skills+agents leg), which added a
`pi-skills` row to the README extension table at the same position this
branch adds its three rows. Conflict resolved by keeping both: the
`pi-skills` row first, then skill-args / todo / ask-user-question.

No content change to skill-args/, todo/ or ask-user-question/ — the three
reviewed directories are tree-identical to 99e57f7.
aaron merged commit cf064e3186 into main 2026-09-20 17:54:37 +00:00
Author
Owner

Landed.

Merged as cf064e3186f4ac8b0990a24b716ede7a7970b0fb (merge commit, source branch kept).

Landing notes

  1. Base had moved. main advanced to 901fe7a (PR #36, skills+agents leg) after CI went green on 99e57f7, and that leg added a pi-skills row to the README extension table at the same position as this PR's three rows. mergeable went false with a real content conflict in README.md, so a conflict-resolution commit was added: 72e625a — "HOMELAB-1609: merge main into plane/HOMELAB-1609-ext", resolving README by keeping the pi-skills row first, then skill-args / todo / ask-user-question + the vendored note. Nothing else was resolved or edited.
    • The review verdict still applies to the new head: git diff --stat 99e57f7 HEAD -- skill-args todo ask-user-question → empty. The three reviewed directories are tree-identical to the SHA the independent reviewers read; only README.md changed.
  2. Re-verified CI on the new head 72e625a — 6/6 contexts success (pr-title, pi-swarm-suite, pi-otel-telemetry, skill-args, todo, ask-user-question). Merged only after that.
  3. Live clone updated (~/.pi/agent/extensions, a separate clone of this repo): fast-forward 901fe7a → cf064e3, tree identical to origin/main, skill-args/ + todo/ + ask-user-question/ now present. skill-args/args.ts md5 78544b68f06f78c0e26dfcb18c4e98bb — unchanged from the npm package.
  4. Not done here (later gated orchestrator step, per the landing brief): no settings.json edit, no npm uninstall, ~/.pi/agent/agents/.rpiv-managed.json untouched. ⚠️ This means the duplicate-registration window is now open (concern 10): the three dirs load from the live clone while settings.json still lists npm:@juicesharp/rpiv-{args,todo,ask-user-question}, so todo / ask_user_question will double-register on the next pi boot until the uninstall + settings edit land atomically. skill-args is safe (args.ts re-entrancy guard).

Concerns 1–11 from the review verdict above remain open and unaddressed by this landing; concerns 1 (no tests for local-config.ts / i18n-bridge.ts), 6 (upstream version 2.10.1 not pinned in-repo — note PR #36's leg did add a NOTICE line for pi-skills, so this leg is now visibly the outlier) and 3 (docs describing removed i18n capability) are the ones worth a follow-up ticket.

**Landed.** Merged as `cf064e3186f4ac8b0990a24b716ede7a7970b0fb` (merge commit, source branch kept). ### Landing notes 1. **Base had moved.** `main` advanced to `901fe7a` (PR #36, skills+agents leg) after CI went green on `99e57f7`, and that leg added a `pi-skills` row to the README extension table at the same position as this PR's three rows. `mergeable` went `false` with a real content conflict in `README.md`, so a conflict-resolution commit was added: **`72e625a` — "HOMELAB-1609: merge main into plane/HOMELAB-1609-ext"**, resolving README by keeping the `pi-skills` row first, then `skill-args` / `todo` / `ask-user-question` + the vendored note. Nothing else was resolved or edited. - **The review verdict still applies to the new head:** `git diff --stat 99e57f7 HEAD -- skill-args todo ask-user-question` → **empty**. The three reviewed directories are tree-identical to the SHA the independent reviewers read; only `README.md` changed. 2. **Re-verified CI on the new head** `72e625a` — 6/6 contexts success (`pr-title`, `pi-swarm-suite`, `pi-otel-telemetry`, `skill-args`, `todo`, `ask-user-question`). Merged only after that. 3. **Live clone updated** (`~/.pi/agent/extensions`, a separate clone of this repo): fast-forward `901fe7a` → **`cf064e3`**, tree identical to `origin/main`, `skill-args/` + `todo/` + `ask-user-question/` now present. `skill-args/args.ts` md5 `78544b68f06f78c0e26dfcb18c4e98bb` — unchanged from the npm package. 4. **Not done here (later gated orchestrator step, per the landing brief):** no `settings.json` edit, no `npm uninstall`, `~/.pi/agent/agents/.rpiv-managed.json` untouched. ⚠️ **This means the duplicate-registration window is now open** (concern 10): the three dirs load from the live clone while `settings.json` still lists `npm:@juicesharp/rpiv-{args,todo,ask-user-question}`, so `todo` / `ask_user_question` will double-register on the next pi boot until the uninstall + settings edit land **atomically**. `skill-args` is safe (`args.ts` re-entrancy guard). Concerns 1–11 from the review verdict above remain open and unaddressed by this landing; concerns 1 (no tests for `local-config.ts` / `i18n-bridge.ts`), 6 (upstream version `2.10.1` not pinned in-repo — note PR #36's leg did add a `NOTICE` line for `pi-skills`, so this leg is now visibly the outlier) and 3 (docs describing removed i18n capability) are the ones worth a follow-up ticket.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Homelab/pi-extensions!37
No description provided.