feat: add Kimi worker adapter, parity skills, and launcher hardening #1

Open
hermes-os wants to merge 1 commit from feat/kimi-adapter-and-parity into main
hermes-os commented 2026-07-30 15:42:11 +00:00 (Migrated from github.com)

Lands work that had been sitting uncommitted in the installed copy at /root/coding-agent-system, so main can move forward again.

Contents

Kimi worker support

  • host/local/bin/agent-kimi — host adapter
  • lib/kimi_config.py, lib/kimi_session_guard.py
  • tests/test_kimi_config.py, tests/test_kimi_session_guard.py

Skills from the agent-scripts parity review

  • create-cli, github-project-triage, ssh-doctor, worker-first
  • docs/steipete-agent-scripts-parity.md, docs/plan/steipete-parity.md

Launcher and contract hardening

  • host/local/bin/agent-claude, host/local/bin/agent-codex
  • hooks/dispatch.py, lib/host_contract.py, lib/skill_layout.py
  • bin/agent-system-doctor, configure-hosts.py
  • tests/test_agent_claude_launcher.py, tests/test_agent_permission_contract.py

32 paths, +3768/-64.

Verification

./validate.sh passes at the branch head 2992c46: 140 tests, 2 skipped, repository check PASS.

Why this was uncommitted

/root/.agents/bin/* symlinks point directly into this repository's working tree, so the checked-out branch is the live installed engineering system. The earlier fast-forward of main to aef4e97 was refused because those uncommitted changes to AGENTS.md would have been overwritten. Now that the work is committed on a branch, main can advance normally — GitHub reports this branch as cleanly mergeable, so the two AGENTS.md edits do not overlap.

The host stays checked out on this branch until the PR merges, to avoid breaking the live adapters.

Lands work that had been sitting uncommitted in the installed copy at `/root/coding-agent-system`, so `main` can move forward again. ## Contents **Kimi worker support** - `host/local/bin/agent-kimi` — host adapter - `lib/kimi_config.py`, `lib/kimi_session_guard.py` - `tests/test_kimi_config.py`, `tests/test_kimi_session_guard.py` **Skills from the agent-scripts parity review** - `create-cli`, `github-project-triage`, `ssh-doctor`, `worker-first` - `docs/steipete-agent-scripts-parity.md`, `docs/plan/steipete-parity.md` **Launcher and contract hardening** - `host/local/bin/agent-claude`, `host/local/bin/agent-codex` - `hooks/dispatch.py`, `lib/host_contract.py`, `lib/skill_layout.py` - `bin/agent-system-doctor`, `configure-hosts.py` - `tests/test_agent_claude_launcher.py`, `tests/test_agent_permission_contract.py` 32 paths, +3768/-64. ## Verification `./validate.sh` passes at the branch head `2992c46`: 140 tests, 2 skipped, repository check PASS. ## Why this was uncommitted `/root/.agents/bin/*` symlinks point directly into this repository's working tree, so the checked-out branch *is* the live installed engineering system. The earlier fast-forward of `main` to `aef4e97` was refused because those uncommitted changes to `AGENTS.md` would have been overwritten. Now that the work is committed on a branch, `main` can advance normally — GitHub reports this branch as cleanly mergeable, so the two `AGENTS.md` edits do not overlap. The host stays checked out on this branch until the PR merges, to avoid breaking the live adapters.
chatgpt-codex-connector[bot] (Migrated from github.com) reviewed 2026-07-30 15:55:08 +00:00
chatgpt-codex-connector[bot] (Migrated from github.com) left a comment

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2992c468f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

### 💡 Codex Review Here are some automated review suggestions for this pull request. **Reviewed commit:** `2992c468f6` <details> <summary>ℹ️ About Codex in GitHub</summary> <br/> [Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". </details>
@ -192,3 +212,3 @@
for name in ("agent-claude", "agent-codex"):
for name in host_launchers:
source = host_integration / "bin" / name
for binary in (agents / "bin" / name, home / ".local" / "bin" / name):
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P2 Badge Validate launcher element types before deduplicating

If hostLaunchers is a JSON list containing a non-string unhashable value, such as ["agent-claude", {}], constructing set(host_launchers) raises TypeError before the later element-type validation runs. The doctor therefore exits with a traceback instead of reporting agent hostLaunchers configuration is invalid; validate that every item is a string before deduplicating.

Useful? React with 👍 / 👎.

**<sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> Validate launcher element types before deduplicating** If `hostLaunchers` is a JSON list containing a non-string unhashable value, such as `["agent-claude", {}]`, constructing `set(host_launchers)` raises `TypeError` before the later element-type validation runs. The doctor therefore exits with a traceback instead of reporting `agent hostLaunchers configuration is invalid`; validate that every item is a string before deduplicating. Useful? React with 👍 / 👎.
@ -29,0 +371,4 @@
rewrite_config_arguments "$@" || exit $?
if [[ -n "$staging_dir" ]]; then
if ! /usr/bin/chown "$uid:$gid" -- "${staged_config_files[@]}" "$staging_dir"; then
echo "agent-claude: could not transfer staged configs to execution user '$run_as'" >&2
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P1 Badge Keep OpenClaw memory inaccessible to Claude workers

On an OpenClaw host using the default claude-agent execution user, this grants that general Claude worker read/write access to /root/.openclaw/workspace/MEMORY.md; the loop immediately above also grants recursive access to the workspace memory directory. This contradicts the explicit isolation goal in docs/plan/steipete-parity.md:28 and allows unrelated repository workers to inspect or alter persistent personal context, so these ACLs must remain restricted to the owning orchestrator rather than the shared Claude runner.

AGENTS.md reference: AGENTS.md:L114-L118

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Keep OpenClaw memory inaccessible to Claude workers** On an OpenClaw host using the default `claude-agent` execution user, this grants that general Claude worker read/write access to `/root/.openclaw/workspace/MEMORY.md`; the loop immediately above also grants recursive access to the workspace memory directory. This contradicts the explicit isolation goal in `docs/plan/steipete-parity.md:28` and allows unrelated repository workers to inspect or alter persistent personal context, so these ACLs must remain restricted to the owning orchestrator rather than the shared Claude runner. AGENTS.md reference: [AGENTS.md:L114-L118](https://github.com/hermes-os/coding-agent-system/blob/2992c468f69c38162539103397cd67216f5d1869/AGENTS.md#L114-L118) Useful? React with 👍 / 👎.
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P1 Badge Stop scanning Claude options at --

For a noninteractive invocation such as agent-claude -p -- -h, the -h is positional data after the end-of-options marker, but this scan still classifies the entire invocation as passthrough. The passthrough branch then launches Claude without the explicit managed permission arguments, relying on mutable provider configuration instead; stop classification at --, as the later permission parser already does.

AGENTS.md reference: AGENTS.md:L28-L30

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Stop scanning Claude options at `--`** For a noninteractive invocation such as `agent-claude -p -- -h`, the `-h` is positional data after the end-of-options marker, but this scan still classifies the entire invocation as passthrough. The passthrough branch then launches Claude without the explicit managed permission arguments, relying on mutable provider configuration instead; stop classification at `--`, as the later permission parser already does. AGENTS.md reference: [AGENTS.md:L28-L30](https://github.com/hermes-os/coding-agent-system/blob/2992c468f69c38162539103397cd67216f5d1869/AGENTS.md#L28-L30) Useful? React with 👍 / 👎.
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P1 Badge Require explicit read mode for Codex reviews

When the command is review or exec review, this unconditionally overwrites the declared or default AGENT_ACCESS_MODE=write with read. That changes the real permission profile based solely on a role/command name, contrary to the repository contract; callers that need a read-only review should declare AGENT_ACCESS_MODE=read, while an explicit write profile must remain unchanged.

AGENTS.md reference: AGENTS.md:L31-L33

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Require explicit read mode for Codex reviews** When the command is `review` or `exec review`, this unconditionally overwrites the declared or default `AGENT_ACCESS_MODE=write` with `read`. That changes the real permission profile based solely on a role/command name, contrary to the repository contract; callers that need a read-only review should declare `AGENT_ACCESS_MODE=read`, while an explicit write profile must remain unchanged. AGENTS.md reference: [AGENTS.md:L31-L33](https://github.com/hermes-os/coding-agent-system/blob/2992c468f69c38162539103397cd67216f5d1869/AGENTS.md#L31-L33) Useful? React with 👍 / 👎.
@ -0,0 +92,4 @@
case "$argument" in
--yolo|-y|--yes)
requested_yolo=1
;;
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P1 Badge Reject clustered Kimi yolo flags in read mode

When AGENT_ACCESS_MODE=read, accepted clusters such as -ymoperator still enable Kimi's -y flag, but this check only detects an argument that equals -y. The clustered-option parser in lib/kimi_session_guard.py explicitly treats y as a standalone flag, so the invocation passes preflight and launches with yolo enabled despite the read-mode contract; detect y inside valid short-option clusters or reject such clusters in read mode.

AGENTS.md reference: AGENTS.md:L31-L33

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Reject clustered Kimi yolo flags in read mode** When `AGENT_ACCESS_MODE=read`, accepted clusters such as `-ymoperator` still enable Kimi's `-y` flag, but this check only detects an argument that equals `-y`. The clustered-option parser in `lib/kimi_session_guard.py` explicitly treats `y` as a standalone flag, so the invocation passes preflight and launches with yolo enabled despite the read-mode contract; detect `y` inside valid short-option clusters or reject such clusters in read mode. AGENTS.md reference: [AGENTS.md:L31-L33](https://github.com/hermes-os/coding-agent-system/blob/2992c468f69c38162539103397cd67216f5d1869/AGENTS.md#L31-L33) Useful? React with 👍 / 👎.
@ -0,0 +125,4 @@
exec "$kimi_bin" "$@" \
--agent-file "$agent_file" \
--config-file "$config_file" \
"${permission_args[@]}"
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P1 Badge Place managed Kimi options before the argument terminator

For an accepted invocation such as agent-kimi --print -- prompt, Kimi treats -- as the end of options, so the subsequently appended --agent-file, --config-file, and --yolo tokens are positional arguments rather than configuration flags. This launches without the canonical policy, managed hooks, or explicit write bypass; insert the managed options before the caller's -- or reject that form.

AGENTS.md reference: AGENTS.md:L28-L30

Useful? React with 👍 / 👎.

**<sub><sub>![P1 Badge](https://img.shields.io/badge/P1-orange?style=flat)</sub></sub> Place managed Kimi options before the argument terminator** For an accepted invocation such as `agent-kimi --print -- prompt`, Kimi treats `--` as the end of options, so the subsequently appended `--agent-file`, `--config-file`, and `--yolo` tokens are positional arguments rather than configuration flags. This launches without the canonical policy, managed hooks, or explicit write bypass; insert the managed options before the caller's `--` or reject that form. AGENTS.md reference: [AGENTS.md:L28-L30](https://github.com/hermes-os/coding-agent-system/blob/2992c468f69c38162539103397cd67216f5d1869/AGENTS.md#L28-L30) Useful? React with 👍 / 👎.
@ -0,0 +27,4 @@
if os.geteuid() != 0 or not SETPRIV.is_file():
return False
user = pwd.getpwnam(user_name)
return identity_is_mapped(Path("/proc/self/uid_map"), user.pw_uid) and identity_is_mapped(
chatgpt-codex-connector[bot] (Migrated from github.com) commented 2026-07-30 15:55:08 +00:00

P2 Badge Handle absent service accounts before evaluating test skips

When the suite runs as root on a host without the optional claude-agent account, pwd.getpwnam() raises KeyError while the skipUnless decorators are being evaluated, so test_agent_claude_launcher cannot even be imported. This currently makes ./validate.sh fail in a standard root container; treat an unknown account as False so the environment-dependent tests are skipped as intended.

Useful? React with 👍 / 👎.

**<sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> Handle absent service accounts before evaluating test skips** When the suite runs as root on a host without the optional `claude-agent` account, `pwd.getpwnam()` raises `KeyError` while the `skipUnless` decorators are being evaluated, so `test_agent_claude_launcher` cannot even be imported. This currently makes `./validate.sh` fail in a standard root container; treat an unknown account as `False` so the environment-dependent tests are skipped as intended. Useful? React with 👍 / 👎.
This pull request has changes conflicting with the target branch.
  • skills/capabilities/scripts/agent-capabilities.py
  • skills/portfolio/SKILL.md
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/kimi-adapter-and-parity:feat/kimi-adapter-and-parity
git switch feat/kimi-adapter-and-parity

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff feat/kimi-adapter-and-parity
git switch feat/kimi-adapter-and-parity
git rebase main
git switch main
git merge --ff-only feat/kimi-adapter-and-parity
git switch feat/kimi-adapter-and-parity
git rebase main
git switch main
git merge --no-ff feat/kimi-adapter-and-parity
git switch main
git merge --squash feat/kimi-adapter-and-parity
git switch main
git merge --ff-only feat/kimi-adapter-and-parity
git switch main
git merge feat/kimi-adapter-and-parity
git push origin main
Sign in to join this conversation.
No description provided.