Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
10 changes: 10 additions & 0 deletions .devcontainer/pi/AGENTS.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 6 additions & 0 deletions .devcontainer/pi/prompts/plan.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 13 additions & 0 deletions .devcontainer/pi/prompts/slice.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 6 additions & 0 deletions .devcontainer/pi/prompts/spec.md
Original file line number Diff line number Diff line change
@@ -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.
18 changes: 18 additions & 0 deletions .devcontainer/pi/skills/debug-loop/SKILL.md
Original file line number Diff line number Diff line change
@@ -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.
21 changes: 21 additions & 0 deletions .devcontainer/pi/skills/plan-slices/SKILL.md
Original file line number Diff line number Diff line change
@@ -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.
17 changes: 17 additions & 0 deletions .devcontainer/pi/skills/spec-first/SKILL.md
Original file line number Diff line number Diff line change
@@ -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.
18 changes: 18 additions & 0 deletions .devcontainer/pi/skills/verify-done/SKILL.md
Original file line number Diff line number Diff line change
@@ -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.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 <feature>`, `/plan <spec section>`, and
`/slice <plan filename or number> <slice number>`.

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 <feature>`, review the spec, then `/plan <section>` and
implement approved slices with `/slice <plan> <n>`.

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),
Expand Down
38 changes: 38 additions & 0 deletions scripts/verify-devcontainer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down