diff --git a/skills/delegation/delegating-to-claude-p/SKILL.md b/skills/delegation/delegating-to-claude-p/SKILL.md index 6c51896..3bf58be 100644 --- a/skills/delegation/delegating-to-claude-p/SKILL.md +++ b/skills/delegation/delegating-to-claude-p/SKILL.md @@ -1,7 +1,7 @@ --- name: delegating-to-claude-p description: Use when authoring a non-interactive `claude -p` invocation or designing a delegation prompt for autonomous Claude on the consumer side. Provides the empirically-validated flag set, prompt template, steers-vs-needs-naming map, failure-mode catalog, recipe templates, and cost reference distilled from 22 sub-experiments (S1 → S22) in the agentic-harness-lab v0.8.0 dogfood arc. Trigger phrases include "delegate to claude -p", "claude -p flags", "autonomous claude", "one-shot claude", "claude -p prompt", "headless claude". Do NOT use for interactive Claude Code sessions, brainstorming, or genuine multi-turn work - `claude -p` is a one-shot contract; pick interactive Claude for those. -placement: "Domain skill. Lives at `plugins/delegation/skills/delegating-to-claude-p/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills." +placement: "Domain skill. Lives at `skills/delegation/delegating-to-claude-p/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill delegating-to-claude-p`. NOT a meta skill." --- # Delegating to `claude -p` @@ -12,6 +12,37 @@ Invoke this skill any time you are about to write a `claude -p` invocation or de The single guiding finding: **hard gates and explicit prompt verbs are what steer `claude -p`. Soft documentation (CLAUDE.md content, skill indices, advisory rules) is largely inert in non-interactive mode unless the user prompt names it explicitly.** +## Captured workflow delegation + +This section applies only inside an Agentic Workspace (for example a +Syntropic137 workflow workspace) whose session-store capability installs the +`syn-delegate` shim and sets `AGENTIC_SESSION_STORE_PROVIDER=local`. Check with +`command -v syn-delegate`. Outside such a workspace the shim does not exist: +skip to the raw `claude -p` recipes below. + +When `AGENTIC_SESSION_STORE_PROVIDER=local`, use the installed structured shim: + +```sh +syn-delegate claude --prompt="$TASK_PROMPT" --timeout 600 +``` + +Keep the `=` in `--prompt="$TASK_PROMPT"`: a prompt that starts with `-` is +otherwise read as an option and the shim exits 2 without launching. The shim +passes the prompt to the harness after `--`, so it can never become a CLI flag. +`--sandbox` is Codex-only; the shim rejects it for `claude`. + +Use `--model` when selecting a model explicitly. Run from the intended working +directory. Existing harness configuration controls permissions; the shim does +not grant permissions. It records intent before launch, binds the delegate's own +native session ID, and preserves its actual exit status even when a caller uses +`|| true` or a pipeline. Claude's shell hook supplies exact parent context; +Codex supplies its native `CODEX_THREAD_ID`. Missing parent context or durable +storage denies launch. Do not fabricate these context values or fall back to a +raw CLI to bypass a capture failure. + +The raw CLI examples below describe uncaptured use and underlying harness +options. In captured workflows, use the shim so the run can discover this launch. + ## The validated invocation ```sh diff --git a/skills/delegation/delegating-to-codex/SKILL.md b/skills/delegation/delegating-to-codex/SKILL.md index 2eb4962..fe0a47a 100644 --- a/skills/delegation/delegating-to-codex/SKILL.md +++ b/skills/delegation/delegating-to-codex/SKILL.md @@ -1,7 +1,7 @@ --- name: delegating-to-codex description: Use when authoring a non-interactive `codex exec` invocation or deciding whether to hand a task from Claude Code to OpenAI Codex CLI. Provides the validated autonomous invocation, the sandbox/approval ladder, the JSON event schema for triage, a when-to-delegate framework, failure modes, and one empirical trial. Trigger phrases include "delegate to codex", "codex exec", "hand this to codex", "run codex", "codex --full-auto", "ask codex", "second opinion from codex", "have codex use a skill", "run a skill in codex", "codex pr-review". Do NOT use for interactive pair-programming in the Codex TUI, or for trivial CRUD/UI/first-attempt tasks where a model handoff adds no value. For autonomous Claude (not Codex), use `delegating-to-claude-p` instead. -placement: "Domain skill. Lives at `plugins/delegation/skills/delegating-to-codex/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills." +placement: "Domain skill. Lives at `skills/delegation/delegating-to-codex/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill delegating-to-codex`. NOT a meta skill." --- # Delegating to `codex exec` @@ -19,6 +19,41 @@ The single most important difference from `claude -p`: **Codex has no built-in cost cap.** `claude -p` enforces `--max-budget-usd`; `codex exec` has no equivalent. The only hard bound is an external one (see the budget section). +## Captured workflow delegation + +This section applies only inside an Agentic Workspace (for example a +Syntropic137 workflow workspace) whose session-store capability installs the +`syn-delegate` shim and sets `AGENTIC_SESSION_STORE_PROVIDER=local`. Check with +`command -v syn-delegate`. Outside such a workspace the shim does not exist: +skip to the raw `codex exec` recipes below, which keep the same sandbox rules. + +When `AGENTIC_SESSION_STORE_PROVIDER=local`, use the installed structured shim: + +```sh +syn-delegate codex --prompt="$TASK_PROMPT" --timeout 600 +``` + +Keep the `=` in `--prompt="$TASK_PROMPT"`: a prompt that starts with `-` is +otherwise read as an option and the shim exits 2 without launching. The shim +passes the prompt to the harness after `--`, so it can never become a CLI flag. + +Use `--model` when selecting a model explicitly. Run from the intended working +directory. The shim always passes Codex an explicit `--sandbox`: `workspace-write` +by default, or `read-only` via `--sandbox read-only` or +`AGENTIC_DELEGATE_CODEX_SANDBOX=read-only`. Any other value is refused before +launch. Before every launch it probes the Codex sandbox live, in the same mode, +directory and environment Codex will get, and launches only if the probe +passes (see the ladder below); otherwise it records `launch_failed` and exits +69. The shim grants no other permissions. It records intent before launch, binds the delegate's own +native session ID, and preserves its actual exit status even when a caller uses +`|| true` or a pipeline. Claude's shell hook supplies exact parent context; +Codex supplies its native `CODEX_THREAD_ID`. Missing parent context or durable +storage denies launch. Do not fabricate these context values or fall back to a +raw CLI to bypass a capture failure. + +The raw CLI examples below describe uncaptured use and underlying harness +options. In captured workflows, use the shim so the run can discover this launch. + ## The validated invocation ```sh @@ -86,14 +121,20 @@ Pick the least privilege that lets the task finish. Granularity Codex exposes: |---|---|---| | `-s read-only` | Read files; no writes, no commands | Analysis / review only | | `-s workspace-write` | Write + run inside the workspace; no network | The default for fmt/test/edit loops | -| `-s danger-full-access` | Writes anywhere, network | Almost never; prefer adding `--add-dir` to widen scope precisely | -| `--dangerously-bypass-approvals-and-sandbox` | No sandbox, no prompts | ONLY when the host is already externally sandboxed (CI container, disposable VM) | -### Inside a container, the bypass flag is the correct choice, not the reckless one +Nothing above `workspace-write` is on the ladder. Modes and flags that switch +Codex's sandbox off are not used by these recipes, and `syn-delegate` refuses +them (`--sandbox` accepts only `read-only` and `workspace-write`). When writes +must reach a directory outside the workspace, pass `--add-dir ` to a raw +`codex exec` instead. `syn-delegate` has no `--add-dir` option; under the shim, +run from a working directory that already contains every path Codex must write. + +### Inside a workspace container: keep the sandbox, fix the container `-s workspace-write` makes Codex sandbox itself with **bubblewrap**, and -bubblewrap needs an unprivileged user namespace. Docker does not grant that by -default, so inside a container every sandboxed operation fails: +bubblewrap needs an unprivileged user namespace. Docker's default seccomp +profile denies that to a container without `CAP_SYS_ADMIN`, so in a workspace +started with the default profile every sandboxed operation fails: ``` warning: Codex could not find bubblewrap on PATH ... will use the bundled @@ -106,22 +147,53 @@ Failed to write file /workspace/palindrome.py Read that stack carefully: the missing-bwrap line is a **warning** and Codex continues with a bundled copy. The namespace denial underneath it is the real fault, and the write failure is only the symptom. Diagnosing from the first -plausible line sends you to install bubblewrap, which does not help. - -When the host is already a container, use: +plausible line sends you to install bubblewrap, which does not help. Worse, +`codex exec` still exits 0, so a caller that trusts the exit status records a +run that did nothing as completed. + +The fix belongs to the workspace, not the invocation. In Agentic Workspace +images, `agentic_isolation` applies the Codex sandbox policy to every image labelled +`agentic.codex_cli_version` (the Codex-capable workspace images are). It adds a +narrow seccomp profile (Docker's default plus `clone`/`unshare` for the user, +mount, pid, net and ipc namespaces, and `mount`, `umount2`, `pivot_root`) +while `--cap-drop=ALL`, `no-new-privileges` and the read-only root stay in +force. On AppArmor hosts (Ubuntu 24.04, where the symptom is +`bwrap: Failed to make / slave: Permission denied`) it also applies the +AppArmor profile `agentic-codex-sandbox`, which the host administrator loads +on the Docker host (see "Loading the AppArmor profile" below); it admits only the mounts bubblewrap +performs, so Codex must run from a directory under `/workspace`. With both, +`-s workspace-write` works as designed: writes inside the workspace succeed +and writes outside it are denied. For any other container, grant the same +thing yourself: a seccomp profile that admits those syscalls (and, on AppArmor +hosts, an AppArmor profile that admits bubblewrap's mounts). Do not swap the +sandbox for a bypass flag. + +#### Loading the AppArmor profile + +The profile ships in the `agentic-isolation` Python package at +`agentic_isolation/apparmor/agentic-codex-sandbox`. Locate and load it on the +host that runs the Docker daemon, using the Python environment where +`agentic-isolation` is installed: ```sh -codex exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check \ - -C /workspace "$TASK_PROMPT" < /dev/null +PROFILE="$(python3 -c 'from agentic_isolation import codex_sandbox_apparmor_profile_path as p; print(p())')" +sudo apparmor_parser -r "$PROFILE" ``` -The container is the sandbox. Codex sandboxing inside it is redundant and -broken, so the flag restores correct behaviour rather than removing a -protection. On a developer laptop the earlier warning still stands. +`apparmor_parser -r` lasts until reboot. To load it at every boot, copy it to +`/etc/apparmor.d/agentic-codex-sandbox` (`sudo cp "$PROFILE" /etc/apparmor.d/`) +and load it from there. + +Without the shim, run the same probe yourself before trusting a run: +`codex sandbox -c 'sandbox_mode="workspace-write"' -- true` must exit 0. -Reach for `--dangerously-bypass-approvals-and-sandbox` only in an -already-isolated host. On a developer machine it is the equivalent of handing -out an unsandboxed shell. +`syn-delegate codex` probes `codex sandbox -c 'sandbox_mode=""' -- true` +live before every launch and refuses when it fails: it records `launch_failed` +with reason `codex_sandbox_unavailable` and exits 69, rather than running a +Codex that cannot execute a single command. There is no status file to trust. +The entrypoint logs the same probe at startup (`[entrypoint] codex sandbox:`) +for diagnosis only. If you hit the refusal, the workspace lacks the policy or +you are outside `/workspace`; do not route around it with a raw `codex exec`. ## Budget: there is no built-in cap @@ -246,7 +318,12 @@ the format section is what steers the output. See Trial T2. | `--base cannot be used with [PROMPT]` | `codex exec review` takes its built-in rubric OR custom instructions, not both | Pick one: `review --base` for the stock rubric, or plain `codex exec` with your own prompt | | Cannot write files / run commands | Default sandbox is `read-only` | Set `-s workspace-write` explicitly | | Refuses to run | Not inside a git repo | Add `--skip-git-repo-check` | -| Writes need a dir outside the workspace | `workspace-write` is workspace-scoped | Add `--add-dir ` rather than escalating to `danger-full-access` | +| Writes need a dir outside the workspace | `workspace-write` is workspace-scoped | Raw `codex exec`: add `--add-dir `, keep the sandbox mode. `syn-delegate` has no `--add-dir`; run from a directory covering the paths | +| `bwrap: No permissions to create a new namespace`, every write fails, exit 0 | Workspace runs Docker's default seccomp profile | Agentic Workspace: use an image labelled `agentic.codex_cli_version` through `agentic_isolation`, which applies the Codex sandbox policy. Other containers: add a seccomp profile admitting the namespace syscalls | +| `bwrap: Failed to make / slave: Permission denied` | AppArmor host, workspace confined by `docker-default` | Load `agentic-codex-sandbox` on the host: `sudo apparmor_parser -r "$PROFILE"` (see "Loading the AppArmor profile"); copy to `/etc/apparmor.d/` to persist | +| `bwrap: Can't bind mount ... Permission denied` | Codex started outside `/workspace` on an AppArmor host | Run from a directory under `/workspace` | +| `syn-delegate` exits 69, `launch_failed` / `codex_sandbox_unavailable` | The live probe found the Codex sandbox unusable | Same fixes; the stderr line names the bwrap cause | +| `syn-delegate` exits 2, `--prompt: expected one argument` | Prompt starts with `-` | Use `--prompt="$TASK_PROMPT"` | | Command fails on a quirky local env (e.g. `pytest` exit 127 under pyenv) | Sandbox shell inherits host PATH quirks | Under `-s workspace-write` Codex often self-recovers (Trial T1); for wrappers, pre-set env via `-c shell_environment_policy...` | ## Trial T1 — empirical reference diff --git a/skills/delegation/writing-handoffs/SKILL.md b/skills/delegation/writing-handoffs/SKILL.md index 9fd5e0a..86a5032 100644 --- a/skills/delegation/writing-handoffs/SKILL.md +++ b/skills/delegation/writing-handoffs/SKILL.md @@ -1,7 +1,7 @@ --- name: writing-handoffs description: Use when you need to compact the current conversation into a handoff document so a fresh session or agent can continue a branch or task with full context. Trigger phrases include "write a handoff", "hand this off", "compact this for a fresh agent", "handoff doc", "summarize this branch's context", "I'll pick this up later", "create a handoff for the next session". Produces a structured Markdown doc (from a template) capturing purpose, current state, files affected, rationale, do's-and-don'ts learned, and suggested skills. Do NOT use to author PRDs, ADRs, plans, or specs — those are separate durable artifacts that a handoff references by path, not reproduces. Do NOT use for a routine end-of-task summary message; a handoff is a written file for a different session to load. -placement: "Domain skill. Lives at `plugins/delegation/skills/writing-handoffs/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills." +placement: "Domain skill. Lives at `skills/delegation/writing-handoffs/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill writing-handoffs`. NOT a meta skill." --- # Writing Handoffs