Skip to content
Merged
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ histories stay joined and edits on either side meet in normal three-way merges.

```sh
git clone -b ws/argos-dev https://github.com/Northeastern-Electric-Racing/Delphi.git argos-dev
cd argos-dev && .delphi/setup.sh # clones workspace.yml's repos into repos/ (git-ignored)
cd argos-dev && .delphi/setup.sh # repos/ stores + default-branch worktrees in worktrees/ (git-ignored)
git switch -c my-change # edit, commit, push, open a PR into ws/argos-dev
git fetch origin && git merge origin/ws/argos-dev # update your branch any time
```

After your PR merges into `ws/<name>`, CI proposes it: a PR `ws/<name> → main` from
`propose/<name>`. Merge that with a merge commit or squash, never rebase. Never push to `ws/*` or
`main` directly (protect them). Code changes go in `repos/<name>`, through that repo's own PRs.
`main` directly (protect them). Code changes go in a worktree, `worktrees/<repo>/<branch>` (`.delphi/new-worktree.sh`), through that repo's own PRs.

**Conflicts.** If `main` and `ws/<name>` changed the same lines, CI lists the files and skips that
workspace. Fix it in a PR into `ws/<name>`: on a branch cut from `ws/<name>`, run
Expand All @@ -57,7 +57,7 @@ workspace. Fix it in a PR into `ws/<name>`: on a branch cut from `ws/<name>`, ru

```yaml
harness: claude-code
repos: # cloned into repos/<name> by .delphi/setup.sh
repos: # stored in repos/<name>, checked out in worktrees/<name>/ by .delphi/setup.sh
argos: https://github.com/Northeastern-Electric-Racing/Argos.git
```

Expand Down
10 changes: 6 additions & 4 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,14 @@ Nobody pushes to `ws/*` or `main` directly (branch protection; CI's token is the

## 5. `.delphi/setup.sh` (in every workspace)

Reads `repos:` from `workspace.yml`, clones each into `repos/<name>` unless present, and adds
`/repos/` to the clone's `.git/info/exclude` once. Nothing else. Must run on macOS `/bin/bash` 3.2
Reads `repos:` from `workspace.yml` and, for each not yet present, fetches it into a bare store at
`repos/<name>`, then checks out its default branch as the first worktree,
`worktrees/<name>/<default-branch>/` (re-created if missing). Adds `/repos/` and `/worktrees/` to
the clone's `.git/info/exclude` once. Nothing else: code is edited only in worktrees. Must run on macOS `/bin/bash` 3.2
and Git Bash: no bash-4 features, POSIX awk only.

`.delphi/new-worktree.sh <repo> <branch> [<base>]` creates or reuses `repos/worktrees/<repo>/<branch>`:
checks out an existing branch, else starts one from `<base>` (default `origin/HEAD`). Same shell rules.
`.delphi/new-worktree.sh <repo> <branch> [<base>]` creates or reuses `worktrees/<repo>/<branch>`
from that store: checks out an existing branch, else starts one from `<base>` (default `origin/HEAD`). Same shell rules.
The template's `new-worktree` skill makes worktrees the default way to start a branch.

`.delphi/link.sh <workspace>|main` checks out `origin/ws/<workspace>` (or `origin/main`) as a
Expand Down
4 changes: 2 additions & 2 deletions docs/goals.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ anyone, person or agent, work on a workspace with plain git and send improvement
- **G1. Workspaces live in Delphi.** Each workspace is a folder on `main` with every file at its
normal harness location.
- **G2. The workspace is the repo root.** Checking out `ws/<name>` gives exactly that workspace at
the root. `.delphi/setup.sh` clones the code repos it lists.
the root. `.delphi/setup.sh` checks out the code repos it lists as worktrees.
- **G3. Both directions, automatically.** Refresh: changes on `main` reach `ws/<name>`. Propose:
merged workspace changes reach `main` as a PR.
- **G4. Conflicts are reported, never guessed.** A conflicting workspace is skipped with its files
Expand All @@ -25,6 +25,6 @@ anyone, person or agent, work on a workspace with plain git and send improvement

- **I1.** Changes reach `main` and `ws/*` only through PRs (CI's refreshes excepted).
- **I2.** `ws/<name>` history is joined to `main`; no unrelated histories, no force-pushes to `ws/*`.
- **I3.** Code repos in `repos/` never appear as workspace changes.
- **I3.** Code repos in `repos/` and `worktrees/` never appear as workspace changes.
- **I4.** `setup.sh` works on macOS bash 3.2 and Git Bash.
- **I5.** Everything is testable end to end without GitHub (`tests/e2e.sh`).
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: new-worktree
description: Create or reuse a worktree for a branch of a repo in repos/ (repos/worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
description: Create or reuse a worktree for a branch of a code repo (worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
---

Make every new branch as a worktree, never by branching in `repos/<repo>/`, unless the user explicitly says not to use worktrees. `repos/<repo>/` stays a clean checkout of the default branch.
`repos/<repo>` is a bare store (no files); every checkout of a code repo is a worktree under `worktrees/<repo>/`. `.delphi/setup.sh` makes the default branch's (`worktrees/<repo>/<default-branch>/`); keep it a clean reference: fetch and fast-forward only. Make every other branch with this script, never by switching branches in an existing worktree, unless the user explicitly says not to use worktrees.

Run from the workspace root:

Expand All @@ -13,6 +13,6 @@ bash .delphi/new-worktree.sh <repo> <branch> [<base>]

An existing branch (local or on origin, e.g. a PR's head) is checked out; anything else is created from `<base>` (default: the repo's default branch). It's safe to re-run. It prints the worktree path: `cd` there and do all work in it.

After the branch merges, remove it with `git -C repos/<repo> worktree remove ../worktrees/<repo>/<branch>`.
After the branch merges, remove it with `git -C repos/<repo> worktree remove ../../worktrees/<repo>/<branch>`.

Argos: always pass `origin/develop` as `<base>`. New ticket branches follow `{issue-number}-{kebab-case-title}`. Run `npm ci` in the worktree's `angular-client/` before building, testing, or running the client.
6 changes: 3 additions & 3 deletions software/application-software/argos/defaults/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@

Argos is a real-time telemetry platform for Northeastern Electric Racing (NER). Angular 19 frontend (`angular-client/`) and Rust backend (`scylla-server/`), with schema tooling in `charybdis/` and MQTT broker config in `siren-base/`.

The Argos repo is checked out at `repos/argos/`. Paths below are relative to a checkout of it. The ticket number is the branch's leading number (`533-csv-upload` → `#533`).
The Argos repo's `develop` is checked out at `worktrees/argos/develop/`. Paths below are relative to any Argos worktree. The ticket number is the branch's leading number (`533-csv-upload` → `#533`).

## Worktrees

- `repos/argos/` is a clean reference to `develop`. Never edit, branch, commit, or run dev servers there. Only fetch, fast-forward `develop`, and manage worktrees from it.
- Every ticket gets its own worktree at `repos/worktrees/argos/<branch>/`, and every workflow (implement, test, run, commit, PR) runs there. Create or reuse one with the `new-worktree` skill, based on `origin/develop`: `bash .delphi/new-worktree.sh argos <branch> origin/develop`.
- `worktrees/argos/develop/` is a clean reference to `develop`. Never edit, branch, commit, or run dev servers there; only fetch and fast-forward it.
- Every ticket gets its own worktree at `worktrees/argos/<branch>/`, and every workflow (implement, test, run, commit, PR) runs there. Create or reuse one with the `new-worktree` skill, based on `origin/develop`: `bash .delphi/new-worktree.sh argos <branch> origin/develop`.
- A new worktree has no `node_modules`: run `npm ci` in its `angular-client/` before testing or running the client.

## Local Development
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Implement a piece of work based on a spec or set of tickets.
disable-model-invocation: true
---

Implement the ticket(s) the user names, one ticket per fresh context, each in its own worktree at `repos/worktrees/argos/<branch>/` (never in `repos/argos/`). Create the worktree first if it doesn't exist.
Implement the ticket(s) the user names, one ticket per fresh context, each in its own worktree at `worktrees/argos/<branch>/` (never in `worktrees/argos/develop/`). Create the worktree first if it doesn't exist.

1. Work test-first at the spec's agreed seams, one behavior at a time: write a failing test, then the minimum code to pass it, and refactor only while green. Test behavior through public interfaces, and mock only at system boundaries.
2. Check as you go:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: new-worktree
description: Create or reuse a worktree for a branch of a repo in repos/ (repos/worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
description: Create or reuse a worktree for a branch of a code repo (worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
---

Make every new branch as a worktree, never by branching in `repos/<repo>/`, unless the user explicitly says not to use worktrees. `repos/<repo>/` stays a clean checkout of the default branch.
`repos/<repo>` is a bare store (no files); every checkout of a code repo is a worktree under `worktrees/<repo>/`. `.delphi/setup.sh` makes the default branch's (`worktrees/<repo>/<default-branch>/`); keep it a clean reference: fetch and fast-forward only. Make every other branch with this script, never by switching branches in an existing worktree, unless the user explicitly says not to use worktrees.

Run from the workspace root:

Expand All @@ -13,6 +13,6 @@ bash .delphi/new-worktree.sh <repo> <branch> [<base>]

An existing branch (local or on origin, e.g. a PR's head) is checked out; anything else is created from `<base>` (default: the repo's default branch). It's safe to re-run. It prints the worktree path: `cd` there and do all work in it.

After the branch merges, remove it with `git -C repos/<repo> worktree remove ../worktrees/<repo>/<branch>`.
After the branch merges, remove it with `git -C repos/<repo> worktree remove ../../worktrees/<repo>/<branch>`.

Argos: always pass `origin/develop` as `<base>`. New ticket branches follow `{issue-number}-{kebab-case-title}`. Run `npm ci` in the worktree's `angular-client/` before building, testing, or running the client.
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#!/usr/bin/env bash
# .delphi/new-worktree.sh <repo> <branch> [<base>]: create or reuse repos/worktrees/<repo>/<branch>
# for repos/<repo> and print its path. An existing branch (local or on origin) is checked out; a new
# one starts from <base> (default: origin's default branch). Runs on bash 3.2 and Git Bash.
# .delphi/new-worktree.sh <repo> <branch> [<base>]: create or reuse worktrees/<repo>/<branch> from
# the store .delphi/setup.sh made at repos/<repo>, and print its path. An existing branch
# (local or on origin) is checked out; a new one starts from <base> (default: origin's default
# branch). Runs on bash 3.2 and Git Bash.
set -euo pipefail
root=$(cd "$(dirname "$0")/.." && pwd)
repo=${1:?usage: new-worktree.sh <repo> <branch> [<base>]} branch=${2:?usage: new-worktree.sh <repo> <branch> [<base>]}
base=${3:-origin/HEAD} dest="$root/repos/worktrees/$repo/$branch"
base=${3:-origin/HEAD} dest="$root/worktrees/$repo/$branch"
g() { git -C "$root/repos/$repo" "$@"; }
g fetch -q origin
if [ -d "$dest" ]; then :
elif g rev-parse -q --verify "refs/heads/$branch" >/dev/null || g rev-parse -q --verify "refs/remotes/origin/$branch" >/dev/null; then
elif g rev-parse -q --verify "refs/heads/$branch" >/dev/null; then
g worktree add -q "$dest" "$branch"
elif g rev-parse -q --verify "refs/remotes/origin/$branch" >/dev/null; then
g worktree add -q --track -b "$branch" "$dest" "origin/$branch"
else
g worktree add -q --no-track -b "$branch" "$dest" "$base"
fi
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
# .delphi/setup.sh: run in a checkout of ws/<name> (the workspace root). Clones each repo listed
# under `repos:` in workspace.yml into repos/<name> (skipping ones already there) and adds /repos/
# to this clone's .git/info/exclude. Safe to re-run. Keep it bash 3.2 (macOS) and Git Bash safe:
# no bash-4 features, POSIX awk only.
# .delphi/setup.sh: run in a checkout of ws/<name> (the workspace root). For each repo listed under
# `repos:` in workspace.yml, fetches it into a bare store at repos/<name> (unless present) and checks
# out its default branch as the first worktree, worktrees/<name>/<default-branch>. Adds /repos/ and
# /worktrees/ to this clone's .git/info/exclude. Safe to re-run. Keep it bash 3.2 (macOS) and Git
# Bash safe: no bash-4 features, POSIX awk only.
set -euo pipefail
cd "$(dirname "$0")/.."

Expand All @@ -16,15 +17,32 @@ list=$(awk '
while read -r name url; do
[ -n "$name" ] || continue
case "$name" in . | .. | *[!A-Za-z0-9._-]*) echo "setup: skipping unsafe repo name '$name'" >&2 && continue ;; esac
if [ -e "repos/$name" ]; then
store=repos/$name
if [ -e "$store" ]; then
echo "repos/$name: already present"
else
git clone "$url" "repos/$name" </dev/null
git init -q --bare "$store"
git -C "$store" remote add origin "$url"
git -C "$store" fetch -q origin </dev/null
git -C "$store" remote set-head origin -a >/dev/null </dev/null
fi
done <<EOF
def=$(git -C "$store" symbolic-ref -q --short refs/remotes/origin/HEAD) ||
{ echo "setup: repos/$name has no origin/HEAD; skipping its worktree" >&2 && continue; }
def=${def#origin/}
dest=worktrees/$name/$def
if [ -e "$dest" ]; then continue
elif git -C "$store" rev-parse -q --verify "refs/heads/$def" >/dev/null; then
git -C "$store" worktree add -q "$PWD/$dest" "$def" ||
echo "setup: could not check out $dest (is $def checked out in repos/$name?)" >&2
else
git -C "$store" worktree add -q --track -b "$def" "$PWD/$dest" "origin/$def"
fi
done <<EOF2
$list
EOF
EOF2

exclude=$(git rev-parse --git-path info/exclude)
mkdir -p "$(dirname "$exclude")"
grep -qxF /repos/ "$exclude" 2>/dev/null || echo /repos/ >>"$exclude"
for d in /repos/ /worktrees/; do
grep -qxF "$d" "$exclude" 2>/dev/null || echo "$d" >>"$exclude"
done
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Delphi workspace

You're in Delphi workspace `argos-dev` (branch `ws/argos-dev`); code repos live in `repos/`. Make new branches as worktrees (`new-worktree` skill) unless the user says not to. Work here unless the task clearly belongs to another project.
You're in Delphi workspace `argos-dev` (branch `ws/argos-dev`); code repos are checked out as worktrees under `worktrees/<repo>/` (`.delphi/setup.sh` makes the default branch's). Make new branches as worktrees (`new-worktree` skill) unless the user says not to. Work here unless the task clearly belongs to another project.

# NER Software conventions

Expand All @@ -19,12 +19,12 @@ You're in Delphi workspace `argos-dev` (branch `ws/argos-dev`); code repos live

Argos is a real-time telemetry platform for Northeastern Electric Racing (NER). Angular 19 frontend (`angular-client/`) and Rust backend (`scylla-server/`), with schema tooling in `charybdis/` and MQTT broker config in `siren-base/`.

The Argos repo is checked out at `repos/argos/`. Paths below are relative to a checkout of it. The ticket number is the branch's leading number (`533-csv-upload` → `#533`).
The Argos repo's `develop` is checked out at `worktrees/argos/develop/`. Paths below are relative to any Argos worktree. The ticket number is the branch's leading number (`533-csv-upload` → `#533`).

## Worktrees

- `repos/argos/` is a clean reference to `develop`. Never edit, branch, commit, or run dev servers there. Only fetch, fast-forward `develop`, and manage worktrees from it.
- Every ticket gets its own worktree at `repos/worktrees/argos/<branch>/`, and every workflow (implement, test, run, commit, PR) runs there. Create or reuse one with the `new-worktree` skill, based on `origin/develop`: `bash .delphi/new-worktree.sh argos <branch> origin/develop`.
- `worktrees/argos/develop/` is a clean reference to `develop`. Never edit, branch, commit, or run dev servers there; only fetch and fast-forward it.
- Every ticket gets its own worktree at `worktrees/argos/<branch>/`, and every workflow (implement, test, run, commit, PR) runs there. Create or reuse one with the `new-worktree` skill, based on `origin/develop`: `bash .delphi/new-worktree.sh argos <branch> origin/develop`.
- A new worktree has no `node_modules`: run `npm ci` in its `angular-client/` before testing or running the client.

## Local Development
Expand Down Expand Up @@ -69,4 +69,4 @@ Issues live in GitHub Issues on `Northeastern-Electric-Racing/Argos` via the `gh

## Domain docs

The glossary and ADRs are workspace docs, not files in `repos/argos/`: `docs/CONTEXT.md` and `docs/adr/` at the workspace root. Edit them there and they're proposed back to Delphi. Read `docs/CONTEXT.md` and the relevant ADRs before exploring, use the glossary's terms, and flag any conflict with an ADR. ADR filenames follow `repos/argos/docs/agents/domain.md` (`<NNNN>-<prefix>-<topic-slug>.md`).
The glossary and ADRs are workspace docs, not files in the Argos repo: `docs/CONTEXT.md` and `docs/adr/` at the workspace root. Edit them there and they're proposed back to Delphi. Read `docs/CONTEXT.md` and the relevant ADRs before exploring, use the glossary's terms, and flag any conflict with an ADR. ADR filenames follow `docs/agents/domain.md` in any Argos worktree (`<NNNN>-<prefix>-<topic-slug>.md`).
6 changes: 3 additions & 3 deletions templates/workspace/.claude/skills/new-worktree/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: new-worktree
description: Create or reuse a worktree for a branch of a repo in repos/ (repos/worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
description: Create or reuse a worktree for a branch of a code repo (worktrees/<repo>/<branch>). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees.
---

Make every new branch as a worktree, never by branching in `repos/<repo>/`, unless the user explicitly says not to use worktrees. `repos/<repo>/` stays a clean checkout of the default branch.
`repos/<repo>` is a bare store (no files); every checkout of a code repo is a worktree under `worktrees/<repo>/`. `.delphi/setup.sh` makes the default branch's (`worktrees/<repo>/<default-branch>/`); keep it a clean reference: fetch and fast-forward only. Make every other branch with this script, never by switching branches in an existing worktree, unless the user explicitly says not to use worktrees.

Run from the workspace root:

Expand All @@ -13,4 +13,4 @@ bash .delphi/new-worktree.sh <repo> <branch> [<base>]

An existing branch (local or on origin, e.g. a PR's head) is checked out; anything else is created from `<base>` (default: the repo's default branch). It's safe to re-run. It prints the worktree path: `cd` there and do all work in it.

After the branch merges, remove it with `git -C repos/<repo> worktree remove ../worktrees/<repo>/<branch>`.
After the branch merges, remove it with `git -C repos/<repo> worktree remove ../../worktrees/<repo>/<branch>`.
Loading
Loading