diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 072ae42..30ebedf 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -20,6 +20,17 @@ RUN npm install -g playwright \ && playwright install --with-deps chromium \ && chmod -R a+rx /ms-playwright +# Install pi and seed personal resources for both supported users. +ARG PI_VERSION=1.1.0 +ARG I_HAVE_ADHD_REV=723af7d9afaf43eb871dbcce6129e2bf80de90d5 +RUN npm install -g --ignore-scripts @earendil-works/pi-coding-agent@${PI_VERSION} +COPY --chown=node:node pi/ /home/node/.pi/agent/ +COPY pi/ /root/.pi/agent/ +RUN pi install "git:github.com/ayghri/i-have-adhd@${I_HAVE_ADHD_REV}" \ + && touch /root/.pi/agent/.i-have-adhd-always \ + && su node -c "pi install git:github.com/ayghri/i-have-adhd@${I_HAVE_ADHD_REV}" \ + && su node -c "touch /home/node/.pi/agent/.i-have-adhd-always" + # Tell dev container features where the target user's home directory is. # The devcontainer CLI passes `_REMOTE_USER_HOME`/`_CONTAINER_USER_HOME` to every # feature's install.sh, but envbuilder (used by Coder) only sets `_REMOTE_USER` diff --git a/.devcontainer/pi/AGENTS.md b/.devcontainer/pi/AGENTS.md new file mode 100644 index 0000000..7dfe317 --- /dev/null +++ b/.devcontainer/pi/AGENTS.md @@ -0,0 +1,10 @@ +# Personal preferences + +- Skip Go and Ruby basics; explain only non-obvious trade-offs. +- Prefer stdlib and boring tools. Ask before adding a dependency. +- Go: wrap errors with %w, context as first argument, table tests, no global state or init(). +- Never run destructive git (push --force, reset --hard, clean -fd) or drop data without asking. +- When intent is unclear, ask one concrete question in prose instead of guessing. +- Keep project rules in the project's AGENTS.md, not here. +- Done means builds and tests pass, linters are clean, and command output is shown. +- Never claim a check passed unless you ran it; list anything untested. diff --git a/.devcontainer/pi/prompts/plan.md b/.devcontainer/pi/prompts/plan.md new file mode 100644 index 0000000..ca3f7a7 --- /dev/null +++ b/.devcontainer/pi/prompts/plan.md @@ -0,0 +1,6 @@ +--- +description: Plan vertical slices for an agreed spec section. +--- + +Use the plan-slices skill for this section of docs/SPEC.md: $@ +Stop after writing the plan and request approval; do not implement. diff --git a/.devcontainer/pi/prompts/slice.md b/.devcontainer/pi/prompts/slice.md new file mode 100644 index 0000000..7cf77f8 --- /dev/null +++ b/.devcontainer/pi/prompts/slice.md @@ -0,0 +1,13 @@ +--- +description: Implement one approved plan slice with TDD and verification. +--- + +Implement only slice $2 of plan $1 in docs/plans/. +Resolve the plan by its exact filename or unique numeric prefix. +If the plan or slice is missing or ambiguous, ask before making changes. +Read AGENTS.md, the referenced spec, and the full plan; confirm prerequisites. +Add or update a test, run it to observe the expected failure, then implement the +smallest change and rerun it. For non-testable changes, explain the alternative +verification. Use debug-loop if a test fails twice. +Finish with verify-done, showing evidence and anything untested. Do not start the +next slice or commit changes unless asked. diff --git a/.devcontainer/pi/prompts/spec.md b/.devcontainer/pi/prompts/spec.md new file mode 100644 index 0000000..e0f031e --- /dev/null +++ b/.devcontainer/pi/prompts/spec.md @@ -0,0 +1,6 @@ +--- +description: Clarify a feature and update its spec before coding. +--- + +Use the spec-first skill for: $@ +Read project context first. Stop after the spec and request review; do not implement. diff --git a/.devcontainer/pi/skills/debug-loop/SKILL.md b/.devcontainer/pi/skills/debug-loop/SKILL.md new file mode 100644 index 0000000..d03d579 --- /dev/null +++ b/.devcontainer/pi/skills/debug-loop/SKILL.md @@ -0,0 +1,18 @@ +--- +name: debug-loop +description: Debug systematically when a test fails twice or a defect needs investigation. +--- + +# Debug loop + +1. Reproduce with the smallest existing test or command. Capture the exact failure. +2. Read the relevant code, logs, and recent diff before proposing a fix. +3. State one falsifiable hypothesis and the evidence supporting it. +4. Make one focused change or diagnostic experiment; rerun the reproducer. +5. Record whether the hypothesis held. Undo only your own unsuccessful experiment, + preserving the user's changes; never use destructive git. +6. Stop after three failed hypotheses. Summarize evidence and ask one concrete + question instead of continuing to guess. +7. When fixed, add a regression test where appropriate and use verify-done. + +Do not bundle unrelated fixes, weaken tests, or delegate debugging to a squad. diff --git a/.devcontainer/pi/skills/plan-slices/SKILL.md b/.devcontainer/pi/skills/plan-slices/SKILL.md new file mode 100644 index 0000000..4d92d3b --- /dev/null +++ b/.devcontainer/pi/skills/plan-slices/SKILL.md @@ -0,0 +1,21 @@ +--- +name: plan-slices +description: Turn an agreed spec section into small, verifiable vertical slices. +--- + +# Plan slices + +1. Read the agreed section of docs/SPEC.md and the project's commands and layout. + If requirements are unresolved, use spec-first instead. +2. Inspect existing plans in docs/plans/; choose the next unused NNN-name.md. + Start at 000 if no plans exist. Never overwrite a different plan. +3. Write the plan with a reference to the spec section and numbered vertical slices. +4. For each slice include: + - One observable outcome and explicit boundaries. + - Tests to add or update before implementation. + - Relevant files and dependencies on earlier slices. + - A concrete verify command using the project's existing tooling. +5. Keep each slice independently verifiable; split oversized slices. +6. Ask for plan approval before implementing anything. + +Do not add code or new tooling. Avoid speculative abstractions and unrelated cleanup. diff --git a/.devcontainer/pi/skills/spec-first/SKILL.md b/.devcontainer/pi/skills/spec-first/SKILL.md new file mode 100644 index 0000000..2b45bf5 --- /dev/null +++ b/.devcontainer/pi/skills/spec-first/SKILL.md @@ -0,0 +1,17 @@ +--- +name: spec-first +description: Clarify a new feature or vague request into a spec before writing code. +--- + +# Spec first + +1. Read the project's AGENTS.md and existing docs/SPEC.md. +2. Ask at most five focused questions about outcomes, constraints, and acceptance criteria. + Ask only what cannot be learned from the repository; wait for answers. +3. Propose the smallest useful scope and make exclusions explicit. +4. After agreement, create or update the relevant section of docs/SPEC.md. + Include observable behavior, edge cases, and acceptance criteria. +5. Show the spec change and ask for review before planning implementation. + +Do not write application code, install dependencies, or invent project requirements. +Keep the next action visible and avoid turning a small request into a large framework. diff --git a/.devcontainer/pi/skills/verify-done/SKILL.md b/.devcontainer/pi/skills/verify-done/SKILL.md new file mode 100644 index 0000000..96a4702 --- /dev/null +++ b/.devcontainer/pi/skills/verify-done/SKILL.md @@ -0,0 +1,18 @@ +--- +name: verify-done +description: Run the project's checks and show evidence before claiming work is done. +--- + +# Verify done + +1. Read AGENTS.md and the project's task configuration for the actual check commands. +2. If the project defines `mise run check`, run it. Otherwise run its documented + build, test, and lint commands; never assume mise or a check task exists. +3. Show the commands, exit status, and relevant output. Summarize long output + accurately and explicitly identify any omitted portions. +4. Inspect the diff for unintended changes and sensitive data. +5. List what remains untested, skipped, or blocked and why. +6. Only say done when acceptance criteria are met and required checks pass. + +A failed or unavailable check is not a pass. Do not add testing tools just to +satisfy this skill. Use debug-loop for repeated failures. diff --git a/README.md b/README.md index 03bc461..646c12d 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ My personal devcontainer for VSCode. - `@openprose/prose-cli` (npm) - Namespace CLI (`nsc`) - Playwright with the Chromium browser (and required OS dependencies) +- pi coding agent with i-have-adhd and a lean global workflow ## APT packages @@ -62,6 +63,68 @@ To wire everything up inside the container: slash command, then ask Copilot to interact with your repositories, issues, and pull requests. +## pi coding agent + +The image installs `@earendil-works/pi-coding-agent@1.1.0` globally using +`npm install --ignore-scripts`. Both `node` and `root` get their own +`~/.pi/agent/` with: + +- Short personal preferences from [AGENTS.md](.devcontainer/pi/AGENTS.md). +- The native [i-have-adhd](https://github.com/ayghri/i-have-adhd) package, + pinned to commit `723af7d9afaf43eb871dbcce6129e2bf80de90d5`, and its always-on marker. +- Four editable skills: spec-first, plan-slices, verify-done, and debug-loop. +- Three prompt templates: `/spec `, `/plan `, and + `/slice `. + +These are global resources, so they work in any repository without copying a +skeleton. No superpowers package is installed. The skills create project specs +and plans only when requested; they do not impose the approvals project's stack. +Verification uses `mise run check` only when the project defines it, otherwise +the project's documented checks. + +### First use + +1. Rebuild the container, then launch `pi` as your normal workspace user. +2. Run `/login` and choose GitHub Copilot if using your Copilot subscription. +3. Use `/model`, then Ctrl+S to save your default model. +4. Start with `/spec `, review the spec, then `/plan
` and + implement approved slices with `/slice `. + +Authentication and model choices are deliberately not baked into the image. +Persist your user's `~/.pi` using your workspace platform's home persistence or a +private volume if they should survive container replacement. A volume mounted +over this directory hides the image defaults, so seed an empty volume from the +image first. Do not commit authentication files or share this volume between users. +Node and root have separate configuration and login state. + +Use `/i-have-adhd off` or `/i-have-adhd on` per session. Remove +`~/.pi/agent/.i-have-adhd-always` to disable the default for new sessions. +Edit the bundled resources under `.devcontainer/pi/` and rebuild to change image +defaults, or edit your own `~/.pi/agent/` and use `/reload` for session resources. +Changes to image defaults do not update an existing persistent volume. + +### Optional project-local pi-squad + +Install squad only in the target project, not globally in this image: + +```bash +cd /path/to/project +pi install -l npm:pi-squad +``` + +Review project-local packages before granting trust with `/trust`, then restart +pi and use `/squad defaults` and `/squad agents`. Commit `.pi/settings.json` +and any project role overrides in `.pi/squad/agents/`; add `.pi/npm/` and +`.pi/git/` to that project's `.gitignore`. Keep stack-specific instructions in +the project's `AGENTS.md` and squad overrides, not the global preferences. + +Use squad for milestones after approving a spec and plan. Start with concurrency +2, make shared contracts dependency edges, and avoid inheriting the entire +session unless needed. Inspect the diff and run the project checks yourself +before recording `squad_review`; use `forkFromTask` for rework. Debugging and +small changes stay solo. Squad state lives separately in `~/.pi/squad/`, so +persist that directory too if you need to resume runs. + ## Faster Coder startup: prebuilt image cache on GHCR Coder builds this dev container with [envbuilder](https://github.com/coder/envbuilder), diff --git a/scripts/verify-devcontainer.sh b/scripts/verify-devcontainer.sh index f2148c4..3b7a0ce 100755 --- a/scripts/verify-devcontainer.sh +++ b/scripts/verify-devcontainer.sh @@ -11,6 +11,7 @@ # 1. the effective user is `node`, not root, # 2. tmux is on PATH and can start a session that reads ~/.tmux.conf, # 3. the lifecycle ran to completion (postCreateCommand sentinel exists). +# 4. pi and its global resources are installed for the active user. # # Any failed check exits non-zero so CI fails loudly instead of silently # dropping you into a broken shell. @@ -80,6 +81,43 @@ else fail "lifecycle sentinel missing ($sentinel); postCreateCommand did not complete" fi +# 4. pi and the global workflow must be available without logging in. +if command -v pi >/dev/null 2>&1 && pi --version; then + pass "pi is on PATH and runs" +else + fail "pi is missing or cannot run" +fi + +agent_dir="${HOME}/.pi/agent" +for resource in AGENTS.md .i-have-adhd-always \ + skills/spec-first/SKILL.md skills/plan-slices/SKILL.md \ + skills/verify-done/SKILL.md skills/debug-loop/SKILL.md \ + prompts/spec.md prompts/plan.md prompts/slice.md \ + git/github.com/ayghri/i-have-adhd/extensions/i-have-adhd.ts \ + git/github.com/ayghri/i-have-adhd/extensions/context-compat.ts \ + git/github.com/ayghri/i-have-adhd/skills/i-have-adhd/SKILL.md; do + if [ -f "${agent_dir}/${resource}" ]; then + pass "pi resource present: $resource" + else + fail "pi resource missing: ${agent_dir}/${resource}" + fi +done + +if node -e ' + const fs = require("node:fs"); + const settings = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); + const installed = (settings.packages || []).some(pkg => { + const source = typeof pkg === "string" ? pkg : pkg?.source; + return typeof source === "string" && + source.startsWith("git:github.com/ayghri/i-have-adhd@"); + }); + process.exit(installed ? 0 : 1); +' "${agent_dir}/settings.json"; then + pass "i-have-adhd is registered globally" +else + fail "i-have-adhd is not registered globally" +fi + echo "=== Verification complete ===" if [ "$failures" -ne 0 ]; then echo "$failures check(s) failed." >&2