Add installable agent lifecycle hooks with Ponytail as the reference integration #76

Closed
opened 2026-08-30 10:28:30 +00:00 by hugo · 1 comment
Owner

Goal

Add a small DS4Server-owned agent lifecycle extension mechanism so integrations such as Ponytail can be installed, enabled, and run inside DS4Server without depending on another host's Pi, OpenCode, Claude, or Codex installation.

Ponytail is the reference integration and must work end to end when installed from its own Git repository. The design should expose the lifecycle semantics Ponytail needs, not attempt to reproduce the complete Pi or OpenCode plugin APIs.

Verified reference behavior

Pi now presents hooks as part of its unified extension system. Ponytail's current Pi adapter uses session_start, input, before_agent_start, agent_start, and agent_end together with command registration, per-session state, status notifications, and bundled skills.

Ponytail's OpenCode adapter uses a per-turn system-prompt transform, a command-before hook, persistent mode state, and bundled skill paths.

Ponytail also ships a portable package descriptor at .codex-plugin/plugin.json and a command-hook manifest at hooks/claude-codex-hooks.json. That manifest currently requires only:

  • SessionStart
  • UserPromptSubmit
  • SubagentStart

Those hooks already emit additional instruction context and mode status in a structured form. Supporting this narrow portable surface allows DS4Server to install the Ponytail repository directly without loading its Pi extension module or OpenCode plugin.

References:

Recheck the current Ponytail release and manifests when implementation begins. The issue was prepared against Ponytail 4.9.0.

Current DS4Server state

DS4Server already:

  • discovers standard skills from ~/.agents/skills;
  • injects the skill catalog and workspace instructions into agent prompts;
  • has explicit initial-turn, tool-continuation, compaction, and Ralph child-generation paths;
  • owns tool execution, cancellation, approval, and UI lifecycle state in Rust.

It does not currently have:

  • an extension package registry or installer;
  • lifecycle hook dispatch;
  • enabled-extension skill roots;
  • isolated extension data directories;
  • structured hook output handling;
  • a way to reapply extension context after resume or compaction.

The implementation must extend these existing paths rather than introduce a second agent loop.

Phase 1: define the minimal package contract

Use a versioned Rust-owned extension model. For the first version, accept the portable subset already present in Ponytail's .codex-plugin/plugin.json:

  • name
  • version
  • description and author metadata
  • skills directory
  • hooks manifest path

Reject invalid manifests, duplicate IDs, unsupported schema shapes, absolute paths, path traversal, and symlink escapes. Every referenced file must resolve inside the installed package root.

Parse only the required subset. Unknown optional presentation fields may be ignored, but unsupported executable capabilities must produce a clear diagnostic rather than silently appearing active.

Store each package under DS4Server's Application Support directory with a separate writable data directory. Persist:

  • extension ID and enabled state;
  • original source URL and requested ref;
  • exact resolved Git commit;
  • installed version;
  • validated hook and skill declarations;
  • last load or execution error.

Installation and updates must be atomic: stage and validate the new checkout first, then replace the active version. Keep the previous version until activation succeeds so a failed update can roll back.

Phase 2: add explicit install and management controls

Add an Agent Extensions section to the existing Preferences window using the shared panel, row, button, and toggle styles.

The minimum UI must support:

  • install from an HTTPS Git repository URL with an optional branch, tag, or commit;
  • display name, version, source, resolved commit, enabled state, declared hooks, and skill count;
  • enable/disable;
  • explicit update;
  • uninstall;
  • a visible error when the package, manifest, runtime, or hook cannot load.

Use the existing Rust Git dependency directly. Do not invoke git, npm, npx, pi, opencode, codex, or another package manager as a subprocess. Do not run package post-install scripts or automatically install JavaScript dependencies.

Before enabling an extension with command hooks, show a clear trust confirmation explaining that its hook commands execute local code with the user's account permissions. Installation alone must not silently enable an unreviewed extension. Updates that change the resolved commit must require the new version to pass validation before activation.

Do not auto-update extensions.

Phase 3: implement a bounded command-hook runner

Run hook commands from the package's own manifest, not from another agent's installed plugin directory.

For compatibility with Ponytail's existing hook command:

  • provide the package root through CLAUDE_PLUGIN_ROOT;
  • provide a DS4Server-owned, extension-specific writable directory through PLUGIN_DATA;
  • also expose DS4SERVER_PLUGIN_ROOT, DS4SERVER_PLUGIN_DATA, the project root, session ID, and event name;
  • use the selected project's canonical path as the event working directory where appropriate.

The compatibility environment is local to the child process and must not read or modify ~/.pi, OpenCode configuration, or a Codex plugin cache.

Execution rules:

  1. Parse the configured command with the already-installed shlex dependency.
  2. Expand only documented whole variables such as the package-root placeholder.
  3. Resolve script paths and reject package-relative paths that escape the package root.
  4. Execute argv directly with std::process::Command; never pass the manifest command through /bin/sh or an interactive user shell.
  5. Send one bounded JSON event on stdin.
  6. Accept one bounded UTF-8 or JSON result on stdout and keep bounded stderr for diagnostics.
  7. Apply a short configurable host constant timeout, initially matching Ponytail's five-second declaration, with a hard upper ceiling.
  8. Tie the child process to generation cancellation and terminate its process group on timeout, cancellation, extension disable, or application shutdown.
  9. Reject malformed, oversized, or mismatched event output as a hook failure; never inject partial output.

A missing executable such as node must produce one actionable extension error. It must not crash the app or emit an error before every model token.

Hook failures outside a security gate should omit that hook's output for the turn, surface the failure, and allow the core agent to continue. Later successful invocations may clear the transient error.

Phase 4: map the lifecycle into the existing agent loop

Implement deterministic dispatch in installation order for these initial events:

SessionStart

Fire when:

  • a new chat session begins, using reason startup;
  • an existing session becomes active, using reason resume;
  • a completed durable compaction rebuilds the visible context, using reason compact.

Provide session ID, reason, canonical project directory, model, and timestamp. Respect each manifest matcher.

Treat hookSpecificOutput.additionalContext as hidden system-level agent context. Persist enough source metadata to avoid duplicate injection in one visible context and to re-arm it after compaction. A hook may not replace DS4Server's base tool schema, workspace instructions, direct user instructions, or safety policy.

Treat systemMessage as user-visible extension status or activity metadata, not as untrusted assistant text.

UserPromptSubmit

Fire once for each actual user-authored prompt before the coding-agent generation starts. Provide the original prompt, session ID, and project directory.

Additional context returned by the hook must affect that same turn. The original user prompt remains authoritative and must not be silently discarded or rewritten by the initial protocol.

This event must cover queued user input when it later becomes active. Host-only commands such as /compact must retain their current behavior.

SubagentStart

Fire before each fresh Ralph child round with agent_type set to ralph, its round number, the parent session ID, and the same project root.

Inject returned additional context into that child's system prompt only. It must not leak the parent conversation or weaken Ralph's fresh-context boundary. Future native subagent types should reuse this dispatcher rather than add a Ponytail-specific path.

The first version does not need generic tool-call interception. If before-tool hooks are added later, transformed calls must be revalidated and risk-assessed after every transformation, and extensions must never be able to auto-approve a tool.

Phase 5: expose extension skills through the existing skill system

For every enabled extension:

  1. Validate its declared skill directories.
  2. Reuse the existing AgentSkill frontmatter parser and prompt catalog.
  3. Add only the validated skill roots to the normal read-tool allowlist.
  4. Keep extension skills separate from ~/.agents/skills and Dev Brain skills in diagnostics while presenting one deduplicated catalog to the model.
  5. Remove them immediately from new prompts and tool access when the extension is disabled or uninstalled.
  6. Resolve duplicate skill names deterministically and show the conflict instead of silently choosing a package.

Do not copy extension skills into ~/.agents/skills. Their lifecycle belongs to the installed extension version.

Phase 6: Ponytail end-to-end validation

Install a pinned current Ponytail commit from https://github.com/DietrichGebert/ponytail.git through the new DS4Server flow. Do not use an already installed copy from Pi, OpenCode, Claude, or Codex.

Verify all of the following:

  • Ponytail's six bundled skills are discovered from the installed package.
  • A new session runs SessionStart and receives the configured default ruleset.
  • /ponytail lite, /ponytail full, /ponytail ultra, /ponytail off, /ponytail status, and /ponytail default MODE produce the intended mode behavior from the package hooks.
  • Mode state is isolated to DS4Server's extension data and follows Ponytail's session/default semantics.
  • The active mode is restored on resume.
  • Compaction re-injects the current ruleset exactly once.
  • Every Ralph child receives the active ruleset through SubagentStart.
  • Disabling Ponytail stops prompt injection and removes its skills without deleting unrelated state.
  • Uninstall removes the package and its DS4Server-owned state after explicit confirmation.
  • Missing node, hook timeout, malformed output, and a hook crash remain recoverable and visible.
  • No Pi, OpenCode, Claude, or Codex configuration or plugin directory is read or changed.

Use a small deterministic fixture extension for ordinary automated tests so the test suite does not require network access or Ponytail. Keep the real pinned Ponytail installation as an explicit integration test.

Security and correctness tests

Add focused coverage for:

  • manifest parsing and schema-version rejection;
  • path traversal, absolute path, and symlink escape rejection;
  • duplicate extension and skill IDs;
  • deterministic hook ordering and matcher behavior;
  • environment and data-directory isolation;
  • timeout, cancellation, process-group cleanup, output limits, invalid UTF-8, malformed JSON, and non-zero exit;
  • SessionStart deduplication and compaction re-arming;
  • same-turn UserPromptSubmit context;
  • Ralph fresh-context inheritance;
  • enable, disable, failed update rollback, and uninstall;
  • application restart with persisted registry/state;
  • preservation of the existing tool approval and workspace-instruction hierarchy.

Acceptance criteria

  • A user can install, review, enable, disable, update, and uninstall an extension from DS4Server without another agent harness.
  • Enabled packages can contribute validated skills and the three defined lifecycle hooks.
  • Hook execution is bounded, cancellable, deterministic, directly spawned without a shell, and visibly diagnosable.
  • Extension output cannot replace core DS4Server policy or bypass tool validation and approval.
  • Current Ponytail installs from its Git repository and passes every Phase 6 behavior check.
  • DS4Server never reads or mutates another host's plugin installation or configuration.
  • Existing ~/.agents/skills, Dev Brain skills, AGENTS.md reconciliation, tool continuation, compaction, and Ralph behavior remain intact when no extension is enabled.
  • The normal repository gates pass: cargo fmt --all -- --check, Clippy with -D warnings, make bundle, and cargo test --all-features.

Likely code areas

  • src/agent.rs
  • src/app/generation.rs
  • src/app.rs
  • src/config.rs
  • src/database.rs
  • src/app/preferences.rs
  • src/app/view/preferences.rs
  • a small dedicated Rust extension module rather than embedding extension logic throughout the UI and agent loop

Non-goals

  • Full binary or source compatibility with Pi's ExtensionAPI.
  • Loading OpenCode server plugins or opencode.json.
  • Loading extensions from an existing Pi, OpenCode, Claude, or Codex installation.
  • Embedding a JavaScript runtime or bundling Node.
  • Custom providers, model replacement, arbitrary custom UI, custom renderers, keyboard shortcuts, themes, or dynamic LLM tool registration.
  • Marketplace search, ratings, automatic dependency installation, or automatic updates.
  • Allowing lifecycle extensions to bypass DS4Server permissions or execute package post-install scripts.
## Goal Add a small DS4Server-owned agent lifecycle extension mechanism so integrations such as Ponytail can be installed, enabled, and run inside DS4Server without depending on another host's Pi, OpenCode, Claude, or Codex installation. Ponytail is the reference integration and must work end to end when installed from its own Git repository. The design should expose the lifecycle semantics Ponytail needs, not attempt to reproduce the complete Pi or OpenCode plugin APIs. ## Verified reference behavior Pi now presents hooks as part of its unified extension system. Ponytail's current Pi adapter uses session_start, input, before_agent_start, agent_start, and agent_end together with command registration, per-session state, status notifications, and bundled skills. Ponytail's OpenCode adapter uses a per-turn system-prompt transform, a command-before hook, persistent mode state, and bundled skill paths. Ponytail also ships a portable package descriptor at .codex-plugin/plugin.json and a command-hook manifest at hooks/claude-codex-hooks.json. That manifest currently requires only: - SessionStart - UserPromptSubmit - SubagentStart Those hooks already emit additional instruction context and mode status in a structured form. Supporting this narrow portable surface allows DS4Server to install the Ponytail repository directly without loading its Pi extension module or OpenCode plugin. References: - Pi extension lifecycle: https://pi.dev/docs/latest/extensions - Ponytail repository: https://github.com/DietrichGebert/ponytail - Ponytail package metadata: https://github.com/DietrichGebert/ponytail/blob/main/package.json - Ponytail Pi adapter: https://github.com/DietrichGebert/ponytail/tree/main/pi-extension Recheck the current Ponytail release and manifests when implementation begins. The issue was prepared against Ponytail 4.9.0. ## Current DS4Server state DS4Server already: - discovers standard skills from ~/.agents/skills; - injects the skill catalog and workspace instructions into agent prompts; - has explicit initial-turn, tool-continuation, compaction, and Ralph child-generation paths; - owns tool execution, cancellation, approval, and UI lifecycle state in Rust. It does not currently have: - an extension package registry or installer; - lifecycle hook dispatch; - enabled-extension skill roots; - isolated extension data directories; - structured hook output handling; - a way to reapply extension context after resume or compaction. The implementation must extend these existing paths rather than introduce a second agent loop. ## Phase 1: define the minimal package contract Use a versioned Rust-owned extension model. For the first version, accept the portable subset already present in Ponytail's .codex-plugin/plugin.json: - name - version - description and author metadata - skills directory - hooks manifest path Reject invalid manifests, duplicate IDs, unsupported schema shapes, absolute paths, path traversal, and symlink escapes. Every referenced file must resolve inside the installed package root. Parse only the required subset. Unknown optional presentation fields may be ignored, but unsupported executable capabilities must produce a clear diagnostic rather than silently appearing active. Store each package under DS4Server's Application Support directory with a separate writable data directory. Persist: - extension ID and enabled state; - original source URL and requested ref; - exact resolved Git commit; - installed version; - validated hook and skill declarations; - last load or execution error. Installation and updates must be atomic: stage and validate the new checkout first, then replace the active version. Keep the previous version until activation succeeds so a failed update can roll back. ## Phase 2: add explicit install and management controls Add an Agent Extensions section to the existing Preferences window using the shared panel, row, button, and toggle styles. The minimum UI must support: - install from an HTTPS Git repository URL with an optional branch, tag, or commit; - display name, version, source, resolved commit, enabled state, declared hooks, and skill count; - enable/disable; - explicit update; - uninstall; - a visible error when the package, manifest, runtime, or hook cannot load. Use the existing Rust Git dependency directly. Do not invoke git, npm, npx, pi, opencode, codex, or another package manager as a subprocess. Do not run package post-install scripts or automatically install JavaScript dependencies. Before enabling an extension with command hooks, show a clear trust confirmation explaining that its hook commands execute local code with the user's account permissions. Installation alone must not silently enable an unreviewed extension. Updates that change the resolved commit must require the new version to pass validation before activation. Do not auto-update extensions. ## Phase 3: implement a bounded command-hook runner Run hook commands from the package's own manifest, not from another agent's installed plugin directory. For compatibility with Ponytail's existing hook command: - provide the package root through CLAUDE_PLUGIN_ROOT; - provide a DS4Server-owned, extension-specific writable directory through PLUGIN_DATA; - also expose DS4SERVER_PLUGIN_ROOT, DS4SERVER_PLUGIN_DATA, the project root, session ID, and event name; - use the selected project's canonical path as the event working directory where appropriate. The compatibility environment is local to the child process and must not read or modify ~/.pi, OpenCode configuration, or a Codex plugin cache. Execution rules: 1. Parse the configured command with the already-installed shlex dependency. 2. Expand only documented whole variables such as the package-root placeholder. 3. Resolve script paths and reject package-relative paths that escape the package root. 4. Execute argv directly with std::process::Command; never pass the manifest command through /bin/sh or an interactive user shell. 5. Send one bounded JSON event on stdin. 6. Accept one bounded UTF-8 or JSON result on stdout and keep bounded stderr for diagnostics. 7. Apply a short configurable host constant timeout, initially matching Ponytail's five-second declaration, with a hard upper ceiling. 8. Tie the child process to generation cancellation and terminate its process group on timeout, cancellation, extension disable, or application shutdown. 9. Reject malformed, oversized, or mismatched event output as a hook failure; never inject partial output. A missing executable such as node must produce one actionable extension error. It must not crash the app or emit an error before every model token. Hook failures outside a security gate should omit that hook's output for the turn, surface the failure, and allow the core agent to continue. Later successful invocations may clear the transient error. ## Phase 4: map the lifecycle into the existing agent loop Implement deterministic dispatch in installation order for these initial events: ### SessionStart Fire when: - a new chat session begins, using reason startup; - an existing session becomes active, using reason resume; - a completed durable compaction rebuilds the visible context, using reason compact. Provide session ID, reason, canonical project directory, model, and timestamp. Respect each manifest matcher. Treat hookSpecificOutput.additionalContext as hidden system-level agent context. Persist enough source metadata to avoid duplicate injection in one visible context and to re-arm it after compaction. A hook may not replace DS4Server's base tool schema, workspace instructions, direct user instructions, or safety policy. Treat systemMessage as user-visible extension status or activity metadata, not as untrusted assistant text. ### UserPromptSubmit Fire once for each actual user-authored prompt before the coding-agent generation starts. Provide the original prompt, session ID, and project directory. Additional context returned by the hook must affect that same turn. The original user prompt remains authoritative and must not be silently discarded or rewritten by the initial protocol. This event must cover queued user input when it later becomes active. Host-only commands such as /compact must retain their current behavior. ### SubagentStart Fire before each fresh Ralph child round with agent_type set to ralph, its round number, the parent session ID, and the same project root. Inject returned additional context into that child's system prompt only. It must not leak the parent conversation or weaken Ralph's fresh-context boundary. Future native subagent types should reuse this dispatcher rather than add a Ponytail-specific path. The first version does not need generic tool-call interception. If before-tool hooks are added later, transformed calls must be revalidated and risk-assessed after every transformation, and extensions must never be able to auto-approve a tool. ## Phase 5: expose extension skills through the existing skill system For every enabled extension: 1. Validate its declared skill directories. 2. Reuse the existing AgentSkill frontmatter parser and prompt catalog. 3. Add only the validated skill roots to the normal read-tool allowlist. 4. Keep extension skills separate from ~/.agents/skills and Dev Brain skills in diagnostics while presenting one deduplicated catalog to the model. 5. Remove them immediately from new prompts and tool access when the extension is disabled or uninstalled. 6. Resolve duplicate skill names deterministically and show the conflict instead of silently choosing a package. Do not copy extension skills into ~/.agents/skills. Their lifecycle belongs to the installed extension version. ## Phase 6: Ponytail end-to-end validation Install a pinned current Ponytail commit from https://github.com/DietrichGebert/ponytail.git through the new DS4Server flow. Do not use an already installed copy from Pi, OpenCode, Claude, or Codex. Verify all of the following: - Ponytail's six bundled skills are discovered from the installed package. - A new session runs SessionStart and receives the configured default ruleset. - /ponytail lite, /ponytail full, /ponytail ultra, /ponytail off, /ponytail status, and /ponytail default MODE produce the intended mode behavior from the package hooks. - Mode state is isolated to DS4Server's extension data and follows Ponytail's session/default semantics. - The active mode is restored on resume. - Compaction re-injects the current ruleset exactly once. - Every Ralph child receives the active ruleset through SubagentStart. - Disabling Ponytail stops prompt injection and removes its skills without deleting unrelated state. - Uninstall removes the package and its DS4Server-owned state after explicit confirmation. - Missing node, hook timeout, malformed output, and a hook crash remain recoverable and visible. - No Pi, OpenCode, Claude, or Codex configuration or plugin directory is read or changed. Use a small deterministic fixture extension for ordinary automated tests so the test suite does not require network access or Ponytail. Keep the real pinned Ponytail installation as an explicit integration test. ## Security and correctness tests Add focused coverage for: - manifest parsing and schema-version rejection; - path traversal, absolute path, and symlink escape rejection; - duplicate extension and skill IDs; - deterministic hook ordering and matcher behavior; - environment and data-directory isolation; - timeout, cancellation, process-group cleanup, output limits, invalid UTF-8, malformed JSON, and non-zero exit; - SessionStart deduplication and compaction re-arming; - same-turn UserPromptSubmit context; - Ralph fresh-context inheritance; - enable, disable, failed update rollback, and uninstall; - application restart with persisted registry/state; - preservation of the existing tool approval and workspace-instruction hierarchy. ## Acceptance criteria - A user can install, review, enable, disable, update, and uninstall an extension from DS4Server without another agent harness. - Enabled packages can contribute validated skills and the three defined lifecycle hooks. - Hook execution is bounded, cancellable, deterministic, directly spawned without a shell, and visibly diagnosable. - Extension output cannot replace core DS4Server policy or bypass tool validation and approval. - Current Ponytail installs from its Git repository and passes every Phase 6 behavior check. - DS4Server never reads or mutates another host's plugin installation or configuration. - Existing ~/.agents/skills, Dev Brain skills, AGENTS.md reconciliation, tool continuation, compaction, and Ralph behavior remain intact when no extension is enabled. - The normal repository gates pass: cargo fmt --all -- --check, Clippy with -D warnings, make bundle, and cargo test --all-features. ## Likely code areas - src/agent.rs - src/app/generation.rs - src/app.rs - src/config.rs - src/database.rs - src/app/preferences.rs - src/app/view/preferences.rs - a small dedicated Rust extension module rather than embedding extension logic throughout the UI and agent loop ## Non-goals - Full binary or source compatibility with Pi's ExtensionAPI. - Loading OpenCode server plugins or opencode.json. - Loading extensions from an existing Pi, OpenCode, Claude, or Codex installation. - Embedding a JavaScript runtime or bundling Node. - Custom providers, model replacement, arbitrary custom UI, custom renderers, keyboard shortcuts, themes, or dynamic LLM tool registration. - Marketplace search, ratings, automatic dependency installation, or automatic updates. - Allowing lifecycle extensions to bypass DS4Server permissions or execute package post-install scripts.
hugo added the enhancement label 2026-08-30 10:28:30 +00:00
hugo changed title from implement hooks for the agent process in the form as pi has it to Add installable agent lifecycle hooks with Ponytail as the reference integration 2026-08-30 11:07:10 +00:00
Author
Owner

Implemented and pushed in commit 3977261 (Add installable agent lifecycle extensions).

Implementation:

  • Added a versioned, persistent Rust extension registry with HTTPS git2 install/update, optional refs, exact commit pins, atomic staged activation/rollback, validation of schema/capabilities/paths/symlinks, trust-gated enablement, disable, and confirmed uninstall.
  • Added the native Agent Extensions Preferences section with package metadata, hook/skill inventory, state, errors, explicit update, trust, and uninstall controls.
  • Added direct argv hook execution with shlex parsing, documented variable expansion, isolated per-extension/per-session environment, bounded JSON stdin/stdout/stderr, timeout, cancellation, process-group termination, and persisted recoverable diagnostics.
  • Wired SessionStart startup/resume/compact, same-turn UserPromptSubmit including queued input, and SubagentStart for every fresh Ralph round into the existing agent loop. Context is hidden system context, deduplicated per visible session context, and never replaces core tools, workspace instructions, user prompts, or approval policy.
  • Integrated enabled package skills into the existing catalog and read-only allowlist with deterministic conflict errors and immediate removal after disable/uninstall.
  • Validated Ponytail 4.9.0 from https://github.com/DietrichGebert/ponytail.git at pinned commit 2ed6c52c9d7e5e56942508591085fd45dea277d3: six skills; lite/full/ultra/off/status/default behavior; startup/resume/compact/Ralph inheritance; state isolation; disable; uninstall; and recoverable failures.

Review: DS4 has no corresponding agent-extension lifecycle, so this is a new DS4Server feature. Existing generation, tool validation/approval, AGENTS.md, Dev Brain, compaction, and Ralph paths remain authoritative and the no-hook path stays direct.

Verification:

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • make bundle
  • cargo test --all-features: 197 passed, 17 ignored, 0 failed
  • explicit pinned Ponytail integration test: passed
  • focused registry/security/lifecycle suite: passed
Implemented and pushed in commit 3977261 (Add installable agent lifecycle extensions). Implementation: - Added a versioned, persistent Rust extension registry with HTTPS git2 install/update, optional refs, exact commit pins, atomic staged activation/rollback, validation of schema/capabilities/paths/symlinks, trust-gated enablement, disable, and confirmed uninstall. - Added the native Agent Extensions Preferences section with package metadata, hook/skill inventory, state, errors, explicit update, trust, and uninstall controls. - Added direct argv hook execution with shlex parsing, documented variable expansion, isolated per-extension/per-session environment, bounded JSON stdin/stdout/stderr, timeout, cancellation, process-group termination, and persisted recoverable diagnostics. - Wired SessionStart startup/resume/compact, same-turn UserPromptSubmit including queued input, and SubagentStart for every fresh Ralph round into the existing agent loop. Context is hidden system context, deduplicated per visible session context, and never replaces core tools, workspace instructions, user prompts, or approval policy. - Integrated enabled package skills into the existing catalog and read-only allowlist with deterministic conflict errors and immediate removal after disable/uninstall. - Validated Ponytail 4.9.0 from https://github.com/DietrichGebert/ponytail.git at pinned commit 2ed6c52c9d7e5e56942508591085fd45dea277d3: six skills; lite/full/ultra/off/status/default behavior; startup/resume/compact/Ralph inheritance; state isolation; disable; uninstall; and recoverable failures. Review: DS4 has no corresponding agent-extension lifecycle, so this is a new DS4Server feature. Existing generation, tool validation/approval, AGENTS.md, Dev Brain, compaction, and Ralph paths remain authoritative and the no-hook path stays direct. Verification: - cargo fmt --all -- --check - cargo clippy --all-targets --all-features -- -D warnings - make bundle - cargo test --all-features: 197 passed, 17 ignored, 0 failed - explicit pinned Ponytail integration test: passed - focused registry/security/lifecycle suite: passed
hugo closed this issue 2026-08-30 14:06:17 +00:00
Sign in to join this conversation.