diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d5b4daa61c..54d307470e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,11 @@ repos: language: python additional_dependencies: [toml, pydantic] files: ^agentydragon/tasks/(?:\.done/)?[0-9]{2}-.*\.md$ + - id: enforce-tasks-md-only + name: Enforce only Markdown files in agentydragon/tasks/ + entry: python3 agentydragon/tools/check_tasks_files.py + language: python + files: ^agentydragon/tasks/(?!\.worktrees/)(?!\.done/).* - id: cargo-build name: Check Rust workspace builds entry: bash -lc 'cd codex-rs && RUSTFLAGS="-D warnings" cargo build --workspace --locked' diff --git a/agentydragon/README.md b/agentydragon/README.md index e638379980..f5d50fb0df 100644 --- a/agentydragon/README.md +++ b/agentydragon/README.md @@ -54,7 +54,7 @@ Tasks live under `agentydragon/tasks/` as individual Markdown files. Please upda - - ```sh - # Accept a full slug (NN-slug) or two-digit task ID (NN), optionally multiple; use --tmux to open each in a tmux window: -- agentydragon/tasks/create-task-worktree.sh [--agent] [--tmux] [...] +- agentydragon/tools/create-task-worktree.sh [--agent] [--tmux] [...] - ``` - - Without `--agent`, this creates or reuses a worktree at @@ -65,7 +65,7 @@ Tasks live under `agentydragon/tasks/` as individual Markdown files. Please upda ```sh # Generate and apply commit(s) for completed task(s) in their worktrees: -agentydragon/tasks/launch-commit-agent.sh [...] +agentydragon/tools/launch-commit-agent.sh [...] ``` After the Developer agent finishes and updates the task file, the Commit agent will write the commit message to a temporary file and then commit using that file (`git commit -F`). An external orchestrator can then stage files and run pre-commit hooks as usual. You do not need to run `git commit` manually. diff --git a/agentydragon/prompts/scaffolding-setup.md b/agentydragon/prompts/scaffolding-setup.md index a7c941d1ba..425cb05645 100644 --- a/agentydragon/prompts/scaffolding-setup.md +++ b/agentydragon/prompts/scaffolding-setup.md @@ -7,7 +7,7 @@ tydragon-driven task workflow: e, “Status”, “Goal”, and sections for “Acceptance Criteria”, “Implementation”, and “Notes”. 2. **Worktree launcher** - - Implement `agentydragon/tasks/create-task-worktree.sh` with: + - Implement `agentydragon/tools/create-task-worktree.sh` with: - `--agent` mode to spin up a Codex agent in the worktree, - `--tmux` to tile panes for multiple tasks in a single tmux session, - two‑digit or slug ID resolution. @@ -15,7 +15,7 @@ e, “Status”, “Goal”, and sections for “Acceptance Criteria”, “Impl 3. **Helper scripts** - Add `agentydragon/tasks/review-unmerged-task-branches.sh` to review and merge task branches. - - Add `agentydragon/tasks/launch-project-manager.sh` to invoke the Project Manager agent prompt. + - Add `agentydragon/tools/launch-project-manager.sh` to invoke the Project Manager agent prompt. 4. **Project‑manager prompts** - Create `agentydragon/prompts/manager.md` containing the following Project Manager agent prompt: @@ -64,4 +64,3 @@ the next step. --- Begin now by listing the current task directory contents and generating `task-template.md`. - diff --git a/agentydragon/tasks/.done/15-agent-worktree-sandbox-configuration.md b/agentydragon/tasks/.done/15-agent-worktree-sandbox-configuration.md index 3bc53b2825..f45bca3493 100644 --- a/agentydragon/tasks/.done/15-agent-worktree-sandbox-configuration.md +++ b/agentydragon/tasks/.done/15-agent-worktree-sandbox-configuration.md @@ -36,7 +36,49 @@ The `create-task-worktree.sh --agent` invocation: **How it was implemented** - Extended `create-task-worktree.sh` `--agent` mode to launch the Codex agent under a Landlock+seccomp sandbox by invoking `codex debug landlock --full-auto`, which grants write access only to the worktree (`cwd`) and the platform temp folder (`TMPDIR`), and disables network. - Updated the `-a|--agent` help text to reflect the new sandbox behavior and tempdir whitelist. -- Added `agentydragon/tasks/15-sandbox-test.sh`, a test script demonstrating allowed writes inside the worktree and TMPDIR and blocked writes to directories outside those paths. +- Added a test script demonstrating allowed writes inside the worktree and TMPDIR and blocked writes to directories outside those paths: + + ```bash + #!/usr/bin/env bash + # Test script for Task 15: verify sandbox restrictions and allowances + set -euo pipefail + + worktree_root="$(cd "$(dirname "$0")"/.. && pwd)" + + echo "Running sandbox tests in worktree: $worktree_root" + + # Test write inside worktree + echo -n "Test: write inside worktree... " + if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$worktree_root/inside_test'"; then + echo "PASS" + else + echo "FAIL" >&2 + exit 1 + fi + + # Test write inside TMPDIR + tmpdir=${TMPDIR:-/tmp} + echo -n "Test: write inside TMPDIR ($tmpdir)... " + if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$tmpdir/tmp_test'"; then + echo "PASS" + else + echo "FAIL" >&2 + exit 1 + fi + + # Prepare external directory under HOME to test outside worktree/TMPDIR + external_dir="$HOME/sandbox_test_dir" + mkdir -p "$external_dir" + rm -f "$external_dir/outside_test" + + echo -n "Test: write outside allowed paths ($external_dir)... " + if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$external_dir/outside_test'"; then + echo "FAIL: outside write succeeded" >&2 + exit 1 + else + echo "PASS" + fi + ``` **How it works** When invoked with `--agent`, `create-task-worktree.sh` changes into the task worktree and launches: diff --git a/agentydragon/tasks/.done/15-sandbox-test.sh b/agentydragon/tasks/.done/15-sandbox-test.sh deleted file mode 100755 index 1e9577ee66..0000000000 --- a/agentydragon/tasks/.done/15-sandbox-test.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# Test script for Task 15: verify sandbox restrictions and allowances -set -euo pipefail - -# Determine worktree root (script is placed under agentydragon/tasks) -worktree_root="$(cd "$(dirname "$0")"/.. && pwd)" - -echo "Running sandbox tests in worktree: $worktree_root" - -# Test write inside worktree -echo -n "Test: write inside worktree... " -if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$worktree_root/inside_test'"; then - echo "PASS" -else - echo "FAIL" >&2 - exit 1 -fi - -# Test write inside TMPDIR -tmpdir=${TMPDIR:-/tmp} -echo -n "Test: write inside TMPDIR ($tmpdir)... " -if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$tmpdir/tmp_test'"; then - echo "PASS" -else - echo "FAIL" >&2 - exit 1 -fi - -# Prepare external directory under HOME to test outside worktree/TMPDIR -external_dir="$HOME/sandbox_test_dir" -mkdir -p "$external_dir" -rm -f "$external_dir/outside_test" - -echo -n "Test: write outside allowed paths ($external_dir)... " -if codex debug landlock --full-auto /usr/bin/env bash -c "touch '$external_dir/outside_test'"; then - echo "FAIL: outside write succeeded" >&2 - exit 1 -else - echo "PASS" -fi diff --git a/agentydragon/tools/check_tasks_files.py b/agentydragon/tools/check_tasks_files.py new file mode 100755 index 0000000000..781320a4fe --- /dev/null +++ b/agentydragon/tools/check_tasks_files.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +""" +check_tasks_files.py: Pre-commit hook to ensure only Markdown files in agentydragon/tasks/ (excluding .worktrees and .done). +""" +import sys +from pathlib import Path + +def main(): + bad = [] + for f in sys.argv[1:]: + p = Path(f) + # skip worktree copies and done archives + if p.is_relative_to(Path('agentydragon/tasks/.worktrees')) or p.is_relative_to(Path('agentydragon/tasks/.done')): + continue + # allow only .md files + if p.suffix.lower() != '.md': + bad.append(f) + if bad: + print('Error: only Markdown (.md) files are allowed under agentydragon/tasks/:', file=sys.stderr) + for f in bad: + print(f' {f}', file=sys.stderr) + sys.exit(1) + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/agentydragon/tasks/create-task-worktree.sh b/agentydragon/tools/create-task-worktree.sh similarity index 98% rename from agentydragon/tasks/create-task-worktree.sh rename to agentydragon/tools/create-task-worktree.sh index c0d92213e5..a4789d3235 100755 --- a/agentydragon/tasks/create-task-worktree.sh +++ b/agentydragon/tools/create-task-worktree.sh @@ -176,5 +176,5 @@ if [ "$agent_mode" = true ]; then # After the Developer agent exits, stage and commit via the Commit agent helper echo "Running Commit agent to finalize task $task_slug" - "$repo_root/agentydragon/tasks/launch-commit-agent.sh" "$task_slug" + "$repo_root/agentydragon/tools/launch-commit-agent.sh" "$task_slug" fi diff --git a/agentydragon/tasks/launch-commit-agent.sh b/agentydragon/tools/launch-commit-agent.sh similarity index 100% rename from agentydragon/tasks/launch-commit-agent.sh rename to agentydragon/tools/launch-commit-agent.sh diff --git a/agentydragon/tasks/launch-project-manager.sh b/agentydragon/tools/launch-project-manager.sh similarity index 93% rename from agentydragon/tasks/launch-project-manager.sh rename to agentydragon/tools/launch-project-manager.sh index 0213462ff4..a13cef0da6 100755 --- a/agentydragon/tasks/launch-project-manager.sh +++ b/agentydragon/tools/launch-project-manager.sh @@ -14,4 +14,4 @@ if [ ! -f "$prompt_file" ]; then exit 1 fi -codex "$(<"$prompt_file")" \ No newline at end of file +codex "$(<"$prompt_file")" diff --git a/agentydragon/tools/manager_utils/launch_ready_to_merge.sh b/agentydragon/tools/manager_utils/launch_ready_to_merge.sh index 7eb738090a..b2647c99c9 100755 --- a/agentydragon/tools/manager_utils/launch_ready_to_merge.sh +++ b/agentydragon/tools/manager_utils/launch_ready_to_merge.sh @@ -11,4 +11,4 @@ if [ -z "$ready" ]; then fi echo "Launching tasks: $ready" -agentydragon/tasks/create-task-worktree.sh --agent --tmux $ready +agentydragon/tools/create-task-worktree.sh --agent --tmux $ready