diff --git a/.delphi/exec.sh b/.delphi/exec.sh new file mode 100644 index 0000000..1cf3281 --- /dev/null +++ b/.delphi/exec.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Run a command with this clone's layout, even in hosts whose fresh shells discard session exports. +set -euo pipefail +# shellcheck source=.delphi/paths.sh +source "$(dirname "$0")/paths.sh" +[ "$#" -gt 0 ] || { echo "usage: bash .delphi/exec.sh [...]" >&2; exit 2; } +exec "$@" diff --git a/.delphi/manifest.yml b/.delphi/manifest.yml index 335e3b7..fb1aa03 100644 --- a/.delphi/manifest.yml +++ b/.delphi/manifest.yml @@ -6,7 +6,7 @@ # MINOR something new that existing clones need nothing for # MAJOR clones need cleanup (MINOR while 0.x): add .delphi/migrations/-.sh, which # setup.sh runs once per workspace in each clone (rules in Delphi's CLAUDE.md) -version: 2.0.0 +version: 2.1.0 files: # repo-relative paths; a trailing / means everything under it - .delphi/manifest.yml - .delphi/.gitattributes @@ -14,6 +14,7 @@ files: # repo-relative paths; a trailing / means everythi - .delphi/version.sh - .delphi/setup.sh - .delphi/new-worktree.sh + - .delphi/exec.sh - .delphi/paths.sh - .delphi/plugins.sh - .delphi/switch.sh diff --git a/.delphi/versions b/.delphi/versions index b5e272d..1c95e06 100644 --- a/.delphi/versions +++ b/.delphi/versions @@ -18,3 +18,4 @@ 1.1.0 a3446f7f763c setup.sh clones each repos: entry at repos/ (a normal clone on its default branch, was a bare store) and adds no worktree; new-worktree.sh makes worktrees from that clone; older bare stores are left as they are 1.2.0 d139aaf9f4a5 worktrees come from their own bare store, worktrees//.bare, separate from the plain clone at repos/; setup.sh makes the store and the default-branch worktree again; an older bare store at repos/ is left as it is 2.0.0 750acf945979 a bare repos/ from before 1.1.0 becomes the worktree store, worktrees//.bare, with its worktrees, and repos/ is cloned normally (migration; skipped with a message if it has no origin or work not on origin) +2.1.0 84b00128fc22 add a harness-independent per-command workspace bootstrap for Codex diff --git a/CLAUDE.md b/CLAUDE.md index 4b5131d..1d042da 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,9 +17,10 @@ source of truth; `docs/goals.md` lists what any change must keep. labelled `by: ai` (new-workspace: `--by ai-assisted|human` when the user says so). - `ci/plugins.sh`: writes `.claude-plugin/marketplace.json` from the plugin sets (`software/**/plugins///`, named `[.]`; a folder's scope is its - `plugins/scope`, else its `short-name`, else its name), each workspace's `workspace.yml` `plugins:` defaults (the + `plugins/scope`, else its `short-name`, else its name), each Claude Code workspace's `workspace.yml` `plugins:` defaults (the `default` set of every folder above), and its `.claude/settings.json` (enabled sets, and the SessionStart hook that sets `$DELPHI_ROOT`; never edit - it by hand). Run it after changing a set or a `workspace.yml`'s `plugins:`. + it by hand). `ci/render.sh` calls it for main-side plugin output; sync keeps branch-selected + plugin sets active while their proposal to main is pending. - `.delphi/{setup,new-worktree,switch,park,plugins}.sh`: the scripts every workspace runs (setup.sh runs `plugins.sh`, which makes this clone's local `@delphi` installs what the workspace enables and uninstalls ones the marketplace dropped, so plugin changes need no migration); `.delphi/paths.sh` @@ -31,18 +32,29 @@ source of truth; `docs/goals.md` lists what any change must keep. version, with its hash from `.delphi/version.sh`), `.delphi/migrations/-.sh` (clone cleanup, run by `setup.sh`). - `templates/workspace/`: `workspace.yml`, `CLAUDE.md` (`{{name}}`, `{{folder}}`), the managed - `.github/workflows/delphi.yml` every workspace carries unchanged. The general `new-worktree`, - `switch-workspace`, `setup-workspace`, and `journal` skills are in `software/workspace-inherit/`. + `.github/workflows/delphi.yml` every workspace carries unchanged. The general skills are in + `software/workspace-inherit/.claude/skills/`; Codex adds its bootstrap from `templates/harnesses/` + to the common instruction base once at creation. - `software/plugins/claude/default/`: the `delphi` plugin set, a mod whose `/ws-delphi` pane switches workspaces (`hooks/register.tsx`, tests in `tests/ws.test.ts`, run by `claude plugin test`); `/ws-delphi --web` serves the same cards in a browser tab (`web/server.py`, `web/index.html`). - `software/…/workspaces//`: the workspaces. Org structure is plain directories. A project folder (the one holding `workspaces/`) may add `README.md`, `AUTHORING.md`, and `workspace-defaults/` - (copied once into a new workspace there). Any folder may add `workspace-inherit/` (written onto the - `ws/*` root of every workspace below on each refresh, never proposed; `opt-out:` in a - `workspace.yml` skips a path). + (translated once into a new workspace there). Existing source layouts stay intact; optional + `source.yml` declares a different authoring format. Any org/project folder may add `workspace-inherit/`; + CI prepares inheritance in temporary staging and refresh copies it only to ws branches. + Their `workspace.generated` records ownership; `opt-out:` transfers a native path to the workspace. + Main keeps owned native files and canonical sources, never inherited copies or ledgers. - `.github/workflows/delphi.yml` (identical to the template's copy), `.github/CODEOWNERS`; issue templates (idea, spike, epic, dev work) and the PR template in `.github/`, filed with the `create-ticket` skill (`.claude/skills/`). - `tests/e2e.sh`: end-to-end test in a throwaway sandbox (bare origin, stub `gh` logging to `gh.log`). +- `ci/render.sh [--check] [--workspace ] [ []]`: update plugin + output, or prepare inherited native files and ledgers in optional temporary staging. Main-side + checks reject managed copies, ledgers and ownership collisions; inherited output is never committed there. + `ci/harnesses.sh` reads `ci/harnesses/.sh` through pure `harness_field` queries; + `ci/sources.sh` reads independently selected formats; `ci/inherit.sh` resolves sources. + `ci/managed.sh` shares ownership logic with sync, whose refresh + copies staged output. Every workspace must explicitly declare its harness. Codex uses + `.delphi/exec.sh` to initialize helper commands in independent shells. ## Rules @@ -52,11 +64,18 @@ source of truth; `docs/goals.md` lists what any change must keep. headers): name the file or key that holds them ("the folders in `.delphi/park.list`", "each repo under `repos:`"), never its entries. A copied list goes stale. Runtime tools: bash, git, and `gh` (only to open or update PRs). - Every script: `#!/usr/bin/env bash`, `set -euo pipefail`, `shellcheck`-clean. -- Skills name nothing harness-specific (SKILL.md is the shared Agent Skills format): call scripts by +- Keep Claude skill sources under workspace-inherit/.claude/skills with their metadata intact. + Each descriptor owns `translate_skill`; native metadata conversion, identifier mappings and + helper bootstrap affect only generated output. Write skills once in Claude format; translate + identifiers and feature bullets, never exact source sentences or per-skill copies. Validation + rejects unmapped Claude identifiers in other harnesses; qualified code-repository paths stay literal. + Shared-source paths and opt-out keys follow `docs/design.md`'s portable-path rule; existing owned + workspace filenames are unaffected. + Skill scripts stay harness-independent (SKILL.md uses the Agent Skills format): call scripts by their path in the skill's folder, `bash scripts/