lathe-cli 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -6
- package/bin/lathe +19 -8
- package/bin/lathe-feature +72 -0
- package/bin/lathe-feature-done +88 -0
- package/bin/lathe-init +115 -46
- package/bin/lathe-ls +33 -0
- package/bin/lathe-meta +1 -1
- package/bin/lathe-process +1 -1
- package/bin/lathe-target +1 -1
- package/package.json +1 -1
- package/template/develop/bin/sync.sh +68 -38
- package/template/develop/harness/hooks/commit-runs.sh +2 -2
- package/template/develop/harness/hooks/copy_transcript.sh +2 -2
- package/template/develop/harness/hooks/log.sh +3 -3
- package/template/git-hooks/post-merge +15 -8
- package/template/helper-claude/.claude/CLAUDE.md +28 -0
- package/template/helper-claude/.claude/settings.json +5 -0
- package/template/helper-claude/.claude/skills/lathe-cli/SKILL.md +163 -0
- /package/template/{meta-overlay → develop/harness}/meta/CLAUDE.md +0 -0
- /package/template/{meta-overlay/meta/.claude → develop/harness/meta}/settings.json +0 -0
- /package/template/{meta-overlay/meta/.claude → develop/harness/meta}/skills/improvement-recording/SKILL.md +0 -0
- /package/template/{meta-overlay/meta/.claude → develop/harness/meta}/skills/log-reading/SKILL.md +0 -0
- /package/template/{meta-overlay → develop}/improvements/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -28,30 +28,55 @@ mkdir myapp && cd myapp
|
|
|
28
28
|
lathe init
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
これで以下ができます(v1.2 layout):
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
myapp/
|
|
35
35
|
├── .git/ 共有 bare repo
|
|
36
|
+
├── .claude/ project-root helper(lathe-cli skill)
|
|
37
|
+
├── CLAUDE.md helper の役割記述
|
|
36
38
|
├── main/ main worktree(あなたの app code)
|
|
37
|
-
├── develop/ develop worktree
|
|
38
|
-
|
|
39
|
+
├── develop/ develop worktree
|
|
40
|
+
│ ├── harness/ tracked、target + meta 両方の agent spec の正
|
|
41
|
+
│ │ ├── CLAUDE.md, settings.json, skills/, agents/, ... target 用
|
|
42
|
+
│ │ └── meta/ meta 用
|
|
43
|
+
│ ├── bin/sync.sh tracked(branch-aware、target or meta runtime に展開)
|
|
44
|
+
│ ├── runs/ tracked(hook auto-commit)
|
|
45
|
+
│ └── (CLAUDE.md, .claude/, hooks/, workflow/, plan_template.html — gitignored sync output)
|
|
46
|
+
└── meta/ meta worktree
|
|
47
|
+
├── harness/, bin/, runs/, improvements/ tracked(develop から inherit)
|
|
48
|
+
└── (CLAUDE.md, .claude/ — gitignored sync output、harness/meta/ から)
|
|
39
49
|
```
|
|
40
50
|
|
|
41
|
-
|
|
51
|
+
`harness/` が agent spec の唯一の正。target と meta の両方の指示書が `harness/`(target は root、meta は `harness/meta/`)に集約されているので、harness/ さえあれば同じ harness で再現可能。runtime の `.claude/` `CLAUDE.md` は gitignored で sync.sh が生成。
|
|
42
52
|
|
|
43
53
|
## 日常コマンド
|
|
44
54
|
|
|
45
55
|
```sh
|
|
56
|
+
lathe feature <name> [--from main|develop]
|
|
57
|
+
# features/<name>/ worktree + feature/<name> 枝
|
|
58
|
+
lathe feature-done <name> # 安全に worktree + branch + remote を一掃
|
|
59
|
+
lathe ls # worktree / branch / 最近の runs / improvements
|
|
60
|
+
lathe process <pr#> # PR pickup → tasks/<pr#>/ worktree → target 起動
|
|
46
61
|
lathe target [args...] # cd develop/target && claude args
|
|
47
62
|
lathe meta [args...] # cd meta/meta && claude args
|
|
48
63
|
lathe sync # develop/bin/sync.sh 手動実行
|
|
49
|
-
lathe process <pr#> # PR pickup → tasks/<pr#>/ worktree 作成 → target 起動
|
|
50
64
|
lathe help # ヘルプ
|
|
51
65
|
```
|
|
52
66
|
|
|
53
67
|
どの worktree や project root で実行しても、git の共通 dir から自動で正しい場所に移動します。
|
|
54
68
|
|
|
69
|
+
## helper agent(project root の `.claude/`)
|
|
70
|
+
|
|
71
|
+
`lathe init` 中に「helper agent を Claude Code か Codex か」を対話で聞かれます(デフォルト: Claude Code)。選んだ template が project root の `.claude/` に配置され、`lathe-cli` skill が入ります。
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
cd <project_root>
|
|
75
|
+
claude # Lathe 操作の質問はここで聞ける
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
helper は **Lathe 操作のアシスタント**で、target/meta のような実装エージェントではありません。`lathe feature` や PR 処理のフローに迷ったら相談する相手として常駐します。
|
|
79
|
+
|
|
55
80
|
## 標準ワークフロー
|
|
56
81
|
|
|
57
82
|
```sh
|
|
@@ -91,7 +116,7 @@ git push origin main
|
|
|
91
116
|
## 設計の要点
|
|
92
117
|
|
|
93
118
|
- **branch / worktree でロール分離**:各 agent / role が物理的に別ディレクトリで動くので、CLAUDE.md / settings.json / hooks が混ざらない
|
|
94
|
-
- **harness は meta
|
|
119
|
+
- **harness/ は agent spec の単一の正**:target も meta も自分の設定は `harness/`(meta 用は `harness/meta/`)から sync.sh で worktree root の runtime ファイルに展開される。Claude Code 本体の `.claude/` sensitive-file guard を agent tool で突破できないため、harness/ を編集(普通の dir、guard なし)→ shell sync.sh で `.claude/` 上書き、という迂回経路
|
|
95
120
|
- **runs/ は develop で auto-commit**:target session の Stop hook が `git commit` するので、meta は `git merge develop` で読める。symlink や中央 store 不要
|
|
96
121
|
- **post-merge hook が auto-sync**:meta の harness 改善が develop に merge された瞬間に target/.claude/ が再生成される
|
|
97
122
|
|
package/bin/lathe
CHANGED
|
@@ -28,17 +28,28 @@ lathe — agent harness CLI
|
|
|
28
28
|
Initialize a project with main / develop / meta worktrees backed by a
|
|
29
29
|
shared bare git repo, then drive target / meta agents over Claude Code.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Setup:
|
|
32
32
|
init Initialize Lathe in current (empty) directory.
|
|
33
|
-
Creates ./.git (bare)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
Creates ./.git (bare), three worktrees (main/develop/meta),
|
|
34
|
+
post-merge hook (auto-syncs harness on develop or meta merges),
|
|
35
|
+
and (interactively) a project-root .claude/ helper for Lathe ops.
|
|
36
|
+
|
|
37
|
+
Daily ops:
|
|
38
|
+
feature <name> Create features/<name>/ worktree on a new
|
|
39
|
+
feature/<name> branch (default base: main; --from develop)
|
|
40
|
+
feature-done <name>
|
|
41
|
+
Tear down a feature: worktree + branch (+ remote if any).
|
|
42
|
+
Refuses if uncommitted/unpushed unless --force.
|
|
37
43
|
process <pr#> Pick up a GitHub PR for target processing
|
|
38
44
|
(creates ./tasks/<pr#>/ worktree, launches target)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
ls List worktrees, branches, recent runs/improvements
|
|
46
|
+
|
|
47
|
+
Agent launchers:
|
|
48
|
+
target [args] cd develop, claude args (target's runtime sync'd from harness/)
|
|
49
|
+
meta [args] cd meta, claude args (meta's runtime sync'd from harness/meta/)
|
|
50
|
+
sync Re-run sync.sh in develop (only if post-merge missed)
|
|
51
|
+
|
|
52
|
+
Other:
|
|
42
53
|
help This message
|
|
43
54
|
|
|
44
55
|
LATHE_HOME=$LATHE_HOME
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# lathe feature <name> [--from main|develop]
|
|
3
|
+
# Create a feature worktree at ./features/<name> on a new branch
|
|
4
|
+
# feature/<name>, branched from main (default) or develop.
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
: "${LATHE_HOME:?must be set by lathe dispatcher}"
|
|
8
|
+
source "$LATHE_HOME/bin/_lathe-lib.sh"
|
|
9
|
+
|
|
10
|
+
NAME=""
|
|
11
|
+
FROM="main"
|
|
12
|
+
while [ $# -gt 0 ]; do
|
|
13
|
+
case "$1" in
|
|
14
|
+
--from)
|
|
15
|
+
FROM="$2"; shift 2 ;;
|
|
16
|
+
--from=*)
|
|
17
|
+
FROM="${1#--from=}"; shift ;;
|
|
18
|
+
-*)
|
|
19
|
+
echo "lathe feature: unknown flag $1" >&2; exit 1 ;;
|
|
20
|
+
*)
|
|
21
|
+
if [ -z "$NAME" ]; then NAME="$1"; else
|
|
22
|
+
echo "lathe feature: extra argument $1" >&2; exit 1
|
|
23
|
+
fi
|
|
24
|
+
shift ;;
|
|
25
|
+
esac
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
if [ -z "$NAME" ]; then
|
|
29
|
+
echo "Usage: lathe feature <name> [--from main|develop]" >&2
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
PROJECT_ROOT="$(lathe_project_root)" || {
|
|
34
|
+
echo "lathe feature: not inside a Lathe project" >&2
|
|
35
|
+
exit 1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
GIT_DIR="$PROJECT_ROOT/.git"
|
|
39
|
+
BRANCH="feature/$NAME"
|
|
40
|
+
WT="$PROJECT_ROOT/features/$NAME"
|
|
41
|
+
|
|
42
|
+
# Sanity: base branch exists
|
|
43
|
+
if ! git --git-dir="$GIT_DIR" rev-parse --verify "$FROM" >/dev/null 2>&1; then
|
|
44
|
+
echo "lathe feature: base branch '$FROM' does not exist" >&2
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Sanity: feature branch / worktree don't already exist
|
|
49
|
+
if git --git-dir="$GIT_DIR" rev-parse --verify "$BRANCH" >/dev/null 2>&1; then
|
|
50
|
+
echo "lathe feature: branch '$BRANCH' already exists" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
if [ -e "$WT" ]; then
|
|
54
|
+
echo "lathe feature: $WT already exists" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
mkdir -p "$PROJECT_ROOT/features"
|
|
59
|
+
git --git-dir="$GIT_DIR" worktree add --quiet -b "$BRANCH" "$WT" "$FROM"
|
|
60
|
+
|
|
61
|
+
cat <<EOF
|
|
62
|
+
Created feature worktree:
|
|
63
|
+
|
|
64
|
+
branch: $BRANCH (from $FROM)
|
|
65
|
+
path: $WT
|
|
66
|
+
|
|
67
|
+
Next:
|
|
68
|
+
cd $WT
|
|
69
|
+
# vibe code, commit, push
|
|
70
|
+
git push -u origin $BRANCH
|
|
71
|
+
gh pr create --base develop --title "..." --body "..."
|
|
72
|
+
EOF
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# lathe feature-done <name> [--keep-branch] [--keep-remote] [--force]
|
|
3
|
+
# Tear down a feature worktree safely:
|
|
4
|
+
# 1. refuse if uncommitted changes exist (unless --force)
|
|
5
|
+
# 2. refuse if local has commits not pushed to upstream (unless --force)
|
|
6
|
+
# 3. git worktree remove features/<name>
|
|
7
|
+
# 4. (unless --keep-branch) git branch -D feature/<name>
|
|
8
|
+
# 5. (unless --keep-remote) git push origin :feature/<name>
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
: "${LATHE_HOME:?must be set by lathe dispatcher}"
|
|
12
|
+
source "$LATHE_HOME/bin/_lathe-lib.sh"
|
|
13
|
+
|
|
14
|
+
NAME=""
|
|
15
|
+
KEEP_BRANCH=0
|
|
16
|
+
KEEP_REMOTE=0
|
|
17
|
+
FORCE=0
|
|
18
|
+
while [ $# -gt 0 ]; do
|
|
19
|
+
case "$1" in
|
|
20
|
+
--keep-branch) KEEP_BRANCH=1; shift ;;
|
|
21
|
+
--keep-remote) KEEP_REMOTE=1; shift ;;
|
|
22
|
+
--force) FORCE=1; shift ;;
|
|
23
|
+
-*) echo "lathe feature-done: unknown flag $1" >&2; exit 1 ;;
|
|
24
|
+
*)
|
|
25
|
+
if [ -z "$NAME" ]; then NAME="$1"; else
|
|
26
|
+
echo "lathe feature-done: extra argument $1" >&2; exit 1
|
|
27
|
+
fi
|
|
28
|
+
shift ;;
|
|
29
|
+
esac
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
if [ -z "$NAME" ]; then
|
|
33
|
+
echo "Usage: lathe feature-done <name> [--keep-branch] [--keep-remote] [--force]" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
PROJECT_ROOT="$(lathe_project_root)" || {
|
|
38
|
+
echo "lathe feature-done: not inside a Lathe project" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
GIT_DIR="$PROJECT_ROOT/.git"
|
|
43
|
+
BRANCH="feature/$NAME"
|
|
44
|
+
WT="$PROJECT_ROOT/features/$NAME"
|
|
45
|
+
|
|
46
|
+
if [ ! -d "$WT" ]; then
|
|
47
|
+
echo "lathe feature-done: $WT does not exist" >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# 1. uncommitted changes?
|
|
52
|
+
if [ -n "$(git -C "$WT" status --porcelain 2>/dev/null)" ]; then
|
|
53
|
+
if [ "$FORCE" = 0 ]; then
|
|
54
|
+
echo "lathe feature-done: uncommitted changes in $WT. Commit or use --force." >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# 2. unpushed commits?
|
|
60
|
+
if [ "$FORCE" = 0 ]; then
|
|
61
|
+
upstream="$(git -C "$WT" rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null || true)"
|
|
62
|
+
if [ -n "$upstream" ]; then
|
|
63
|
+
ahead="$(git -C "$WT" rev-list --count "$upstream..HEAD" 2>/dev/null || echo 0)"
|
|
64
|
+
if [ "$ahead" -gt 0 ]; then
|
|
65
|
+
echo "lathe feature-done: $ahead local commit(s) ahead of $upstream. Push or use --force." >&2
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
echo "==> Removing worktree $WT ..."
|
|
72
|
+
git --git-dir="$GIT_DIR" worktree remove "$WT"
|
|
73
|
+
|
|
74
|
+
if [ "$KEEP_BRANCH" = 0 ]; then
|
|
75
|
+
echo "==> Deleting local branch $BRANCH ..."
|
|
76
|
+
git --git-dir="$GIT_DIR" branch -D "$BRANCH" 2>&1 || true
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if [ "$KEEP_REMOTE" = 0 ]; then
|
|
80
|
+
if git --git-dir="$GIT_DIR" remote get-url origin >/dev/null 2>&1; then
|
|
81
|
+
if git --git-dir="$GIT_DIR" ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
|
|
82
|
+
echo "==> Deleting remote branch origin/$BRANCH ..."
|
|
83
|
+
git --git-dir="$GIT_DIR" push origin --delete "$BRANCH" 2>&1 || true
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
echo "Done."
|
package/bin/lathe-init
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# lathe init — initialize a Lathe project in the current directory.
|
|
3
3
|
#
|
|
4
|
-
# Layout produced (
|
|
4
|
+
# Layout produced (v1.2):
|
|
5
5
|
# ./
|
|
6
|
-
# ├── .git/
|
|
7
|
-
# ├──
|
|
8
|
-
# ├──
|
|
9
|
-
#
|
|
6
|
+
# ├── .git/ bare repo, shared by all worktrees
|
|
7
|
+
# ├── .claude/ project-root helper config (if chosen)
|
|
8
|
+
# ├── CLAUDE.md project-root helper brief (if chosen)
|
|
9
|
+
# ├── main/ worktree on 'main' branch — your app code
|
|
10
|
+
# ├── develop/ worktree on 'develop' — target agent's runtime
|
|
11
|
+
# └── meta/ worktree on 'meta' — meta agent's runtime
|
|
10
12
|
#
|
|
11
|
-
#
|
|
13
|
+
# develop tracks harness/ (incl. harness/meta/) as the canonical agent spec.
|
|
14
|
+
# bin/sync.sh on each side regenerates the gitignored runtime files at the
|
|
15
|
+
# worktree root (CLAUDE.md, .claude/, etc.) from harness/. meta inherits
|
|
16
|
+
# develop's harness/, so meta's spec lives at harness/meta/ on the develop
|
|
17
|
+
# branch (and propagates to meta via cut/merge).
|
|
12
18
|
|
|
13
19
|
set -euo pipefail
|
|
14
20
|
|
|
@@ -18,40 +24,36 @@ PROJECT_ROOT="$(pwd)"
|
|
|
18
24
|
PROJECT_NAME="$(basename "$PROJECT_ROOT")"
|
|
19
25
|
|
|
20
26
|
# --- Validation ---
|
|
27
|
+
err=0
|
|
21
28
|
if [ -e "$PROJECT_ROOT/.git" ]; then
|
|
22
|
-
echo "lathe init: $PROJECT_ROOT/.git already exists.
|
|
23
|
-
exit 1
|
|
29
|
+
echo "lathe init: $PROJECT_ROOT/.git already exists." >&2; err=1
|
|
24
30
|
fi
|
|
25
31
|
for d in main develop meta; do
|
|
26
32
|
if [ -e "$PROJECT_ROOT/$d" ]; then
|
|
27
|
-
echo "lathe init: $PROJECT_ROOT/$d already exists.
|
|
28
|
-
exit 1
|
|
33
|
+
echo "lathe init: $PROJECT_ROOT/$d already exists." >&2; err=1
|
|
29
34
|
fi
|
|
30
35
|
done
|
|
36
|
+
[ "$err" = 1 ] && exit 1
|
|
31
37
|
|
|
32
|
-
# Warn (not error) if cwd has any other content.
|
|
33
38
|
EXTRA="$(ls -A "$PROJECT_ROOT" 2>/dev/null | grep -vE '^(\.|\.\.)$' || true)"
|
|
34
39
|
if [ -n "$EXTRA" ]; then
|
|
35
|
-
echo "Note: $PROJECT_ROOT is not empty. Existing files will remain at the project root
|
|
36
|
-
echo " (Lathe v1 doesn't auto-migrate existing repos. Move files into main/ manually if needed.)"
|
|
40
|
+
echo "Note: $PROJECT_ROOT is not empty. Existing files will remain at the project root."
|
|
37
41
|
fi
|
|
38
42
|
|
|
39
43
|
GIT_DIR="$PROJECT_ROOT/.git"
|
|
40
44
|
|
|
41
|
-
echo "==> [1/
|
|
45
|
+
echo "==> [1/6] Initializing bare repo at $GIT_DIR ..."
|
|
42
46
|
git init --bare --quiet "$GIT_DIR"
|
|
43
47
|
|
|
44
|
-
echo "==> [2/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
48
|
+
echo "==> [2/6] Creating main worktree with initial commit (template/main)..."
|
|
49
|
+
# Bootstrap an initial commit so develop/meta have a base.
|
|
50
|
+
EMPTY_TREE="$(git --git-dir="$GIT_DIR" mktree </dev/null)"
|
|
51
|
+
INIT_COMMIT="$(printf 'lathe: empty initial\n' | git --git-dir="$GIT_DIR" commit-tree "$EMPTY_TREE")"
|
|
52
|
+
git --git-dir="$GIT_DIR" update-ref refs/heads/main "$INIT_COMMIT"
|
|
53
|
+
git --git-dir="$GIT_DIR" symbolic-ref HEAD refs/heads/main
|
|
54
|
+
git --git-dir="$GIT_DIR" worktree add --quiet "$PROJECT_ROOT/main" main
|
|
55
|
+
|
|
53
56
|
cp -R "$LATHE_HOME/template/main/." "$PROJECT_ROOT/main/"
|
|
54
|
-
# Replace placeholder in README
|
|
55
57
|
if [ -f "$PROJECT_ROOT/main/README.md" ]; then
|
|
56
58
|
sed -i.bak "s/{{project_name}}/$PROJECT_NAME/g" "$PROJECT_ROOT/main/README.md"
|
|
57
59
|
rm -f "$PROJECT_ROOT/main/README.md.bak"
|
|
@@ -59,43 +61,110 @@ fi
|
|
|
59
61
|
git -C "$PROJECT_ROOT/main" add -A
|
|
60
62
|
git -C "$PROJECT_ROOT/main" \
|
|
61
63
|
-c user.email="lathe@local" -c user.name="lathe" \
|
|
62
|
-
commit --quiet
|
|
64
|
+
commit --quiet -m "lathe: init main"
|
|
63
65
|
|
|
64
|
-
echo "==> [3/
|
|
66
|
+
echo "==> [3/6] Creating develop worktree from main (template/develop)..."
|
|
65
67
|
git --git-dir="$GIT_DIR" worktree add --quiet -b develop "$PROJECT_ROOT/develop" main
|
|
66
68
|
cp -R "$LATHE_HOME/template/develop/." "$PROJECT_ROOT/develop/"
|
|
69
|
+
# Initial sync writes gitignored runtime files to the develop worktree root.
|
|
67
70
|
"$PROJECT_ROOT/develop/bin/sync.sh"
|
|
68
|
-
mkdir -p "$PROJECT_ROOT/develop/runs" "$PROJECT_ROOT/develop/
|
|
69
|
-
touch "$PROJECT_ROOT/develop/runs/.gitkeep" "$PROJECT_ROOT/develop/
|
|
71
|
+
mkdir -p "$PROJECT_ROOT/develop/runs" "$PROJECT_ROOT/develop/plans"
|
|
72
|
+
touch "$PROJECT_ROOT/develop/runs/.gitkeep" "$PROJECT_ROOT/develop/plans/.gitkeep"
|
|
70
73
|
git -C "$PROJECT_ROOT/develop" add -A
|
|
71
74
|
git -C "$PROJECT_ROOT/develop" \
|
|
72
75
|
-c user.email="lathe@local" -c user.name="lathe" \
|
|
73
76
|
commit --quiet -m "lathe: target harness on develop"
|
|
74
77
|
|
|
75
|
-
echo "==> [4/
|
|
78
|
+
echo "==> [4/6] Creating meta worktree from develop..."
|
|
76
79
|
git --git-dir="$GIT_DIR" worktree add --quiet -b meta "$PROJECT_ROOT/meta" develop
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
# Run sync on the meta worktree so meta's runtime files (gitignored)
|
|
81
|
+
# get written from harness/meta/.
|
|
82
|
+
"$PROJECT_ROOT/meta/bin/sync.sh"
|
|
83
|
+
# No commits needed on meta branch here — it inherits develop's tracked
|
|
84
|
+
# content, and runtime files are gitignored.
|
|
85
|
+
|
|
86
|
+
echo "==> [5/6] Installing post-merge hook (auto-sync on develop/meta merges)..."
|
|
87
|
+
COMMON_HOOKS="$(git --git-dir="$GIT_DIR" rev-parse --git-common-dir)/hooks"
|
|
88
|
+
mkdir -p "$COMMON_HOOKS"
|
|
89
|
+
cp "$LATHE_HOME/template/git-hooks/post-merge" "$COMMON_HOOKS/post-merge"
|
|
90
|
+
chmod +x "$COMMON_HOOKS/post-merge"
|
|
91
|
+
|
|
92
|
+
echo "==> [6/6] Helper agent setup ..."
|
|
93
|
+
echo ""
|
|
94
|
+
echo "Which CLI agent will you use as the project-root helper?"
|
|
95
|
+
echo "(Helper sits at the project root and assists with Lathe commands. Doesn't"
|
|
96
|
+
echo " participate in implementation — that's target/meta's job.)"
|
|
97
|
+
echo ""
|
|
98
|
+
echo " 1) Claude Code (recommended)"
|
|
99
|
+
echo " 2) Codex CLI (WIP — falls back to Claude Code template for now)"
|
|
100
|
+
echo " 3) skip (no helper config)"
|
|
101
|
+
echo ""
|
|
102
|
+
HELPER_CHOICE=""
|
|
103
|
+
if [ -t 0 ]; then
|
|
104
|
+
printf "Choice [1]: "
|
|
105
|
+
read -r HELPER_CHOICE
|
|
106
|
+
fi
|
|
107
|
+
case "${HELPER_CHOICE:-1}" in
|
|
108
|
+
1|"") HELPER_KIND="claude" ;;
|
|
109
|
+
2)
|
|
110
|
+
echo "(Codex helper template not yet implemented; using Claude Code template)"
|
|
111
|
+
HELPER_KIND="claude"
|
|
112
|
+
;;
|
|
113
|
+
3) HELPER_KIND="" ;;
|
|
114
|
+
*)
|
|
115
|
+
echo "(unrecognized choice; using Claude Code template)"
|
|
116
|
+
HELPER_KIND="claude"
|
|
117
|
+
;;
|
|
118
|
+
esac
|
|
119
|
+
|
|
120
|
+
if [ -n "$HELPER_KIND" ]; then
|
|
121
|
+
HELPER_SRC="$LATHE_HOME/template/helper-${HELPER_KIND}"
|
|
122
|
+
if [ -d "$HELPER_SRC" ]; then
|
|
123
|
+
cp -R "$HELPER_SRC/." "$PROJECT_ROOT/"
|
|
124
|
+
echo "Helper config installed at $PROJECT_ROOT/.claude/"
|
|
125
|
+
else
|
|
126
|
+
echo "Warning: $HELPER_SRC not found, skipping helper install"
|
|
127
|
+
fi
|
|
128
|
+
fi
|
|
82
129
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
130
|
+
# If LATHE_HOME is nested inside the user repo (cloned as ./.lathe), remind
|
|
131
|
+
# about .gitignore. Canonicalize for macOS /tmp -> /private/tmp.
|
|
132
|
+
LATHE_HOME_CANON="$(cd "$LATHE_HOME" && pwd -P)"
|
|
133
|
+
PROJECT_ROOT_CANON="$(cd "$PROJECT_ROOT" && pwd -P)"
|
|
134
|
+
case "$LATHE_HOME_CANON" in
|
|
135
|
+
"$PROJECT_ROOT_CANON"/*)
|
|
136
|
+
REL="${LATHE_HOME_CANON#$PROJECT_ROOT_CANON/}"
|
|
137
|
+
cat <<EOF
|
|
87
138
|
|
|
139
|
+
NOTE: Lathe is installed at \`$REL/\`. To keep it out of git, add to .gitignore:
|
|
140
|
+
/$REL/
|
|
141
|
+
EOF
|
|
142
|
+
;;
|
|
143
|
+
esac
|
|
144
|
+
|
|
145
|
+
LATHE_BIN="$LATHE_HOME/bin/lathe"
|
|
88
146
|
cat <<EOF
|
|
89
147
|
|
|
90
148
|
Lathe initialized at $PROJECT_ROOT/
|
|
91
149
|
|
|
92
|
-
main/
|
|
93
|
-
develop/
|
|
94
|
-
meta/
|
|
95
|
-
.git/
|
|
150
|
+
main/ your app code (or branch base)
|
|
151
|
+
develop/ target agent runtime, runs/ auto-commit here
|
|
152
|
+
meta/ meta agent runtime
|
|
153
|
+
.git/ shared bare repo (don't touch)
|
|
154
|
+
EOF
|
|
155
|
+
if [ -n "$HELPER_KIND" ]; then
|
|
156
|
+
echo " .claude/ project-root helper (skill: lathe-cli)"
|
|
157
|
+
fi
|
|
158
|
+
cat <<EOF
|
|
96
159
|
|
|
97
|
-
Next:
|
|
98
|
-
cd $PROJECT_ROOT
|
|
99
|
-
|
|
100
|
-
|
|
160
|
+
Next (replace 'lathe' with '$LATHE_BIN' or an alias):
|
|
161
|
+
cd $PROJECT_ROOT
|
|
162
|
+
EOF
|
|
163
|
+
if [ -n "$HELPER_KIND" ]; then
|
|
164
|
+
echo " claude # ask Lathe questions; lathe-cli skill loaded"
|
|
165
|
+
fi
|
|
166
|
+
cat <<EOF
|
|
167
|
+
lathe feature <name> # start a new feature in features/<name>/
|
|
168
|
+
lathe process <pr#> # have target process a PR
|
|
169
|
+
lathe ls # list worktrees, branches, recent runs
|
|
101
170
|
EOF
|
package/bin/lathe-ls
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# lathe ls — list worktrees, branches, runs, improvements at a glance.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
: "${LATHE_HOME:?must be set by lathe dispatcher}"
|
|
6
|
+
source "$LATHE_HOME/bin/_lathe-lib.sh"
|
|
7
|
+
|
|
8
|
+
PROJECT_ROOT="$(lathe_project_root)" || {
|
|
9
|
+
echo "lathe ls: not inside a Lathe project" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
GIT_DIR="$PROJECT_ROOT/.git"
|
|
13
|
+
|
|
14
|
+
echo "=== worktrees ==="
|
|
15
|
+
git --git-dir="$GIT_DIR" worktree list
|
|
16
|
+
|
|
17
|
+
echo ""
|
|
18
|
+
echo "=== branches ==="
|
|
19
|
+
git --git-dir="$GIT_DIR" branch -a
|
|
20
|
+
|
|
21
|
+
DEVELOP_WT="$(lathe_wt_for_branch develop 2>/dev/null || true)"
|
|
22
|
+
if [ -n "$DEVELOP_WT" ] && [ -d "$DEVELOP_WT/runs" ]; then
|
|
23
|
+
echo ""
|
|
24
|
+
echo "=== recent runs (develop/runs/) ==="
|
|
25
|
+
ls -1t "$DEVELOP_WT/runs/" 2>/dev/null | grep -v gitkeep | head -10 || echo "(none)"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
META_WT="$(lathe_wt_for_branch meta 2>/dev/null || true)"
|
|
29
|
+
if [ -n "$META_WT" ] && [ -d "$META_WT/improvements" ]; then
|
|
30
|
+
echo ""
|
|
31
|
+
echo "=== recent improvements (meta/improvements/) ==="
|
|
32
|
+
ls -1t "$META_WT/improvements/" 2>/dev/null | grep -v gitkeep | head -10 || echo "(none)"
|
|
33
|
+
fi
|
package/bin/lathe-meta
CHANGED
package/bin/lathe-process
CHANGED
package/bin/lathe-target
CHANGED
package/package.json
CHANGED
|
@@ -1,50 +1,80 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Sync harness/
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# Sync harness/ → worktree root (gitignored runtime files).
|
|
3
|
+
# Branch-aware:
|
|
4
|
+
# develop branch → sync target part (everything in harness/ except harness/meta/)
|
|
5
|
+
# meta branch → sync meta part (harness/meta/ only)
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# Cleans stale runtime files first (rm before cp), so renames/removals on the
|
|
8
|
+
# harness side propagate.
|
|
9
|
+
#
|
|
10
|
+
# Run when:
|
|
11
|
+
# - Manually after editing harness/ (rare; usually meta does this via PR)
|
|
12
|
+
# - Automatically by the post-merge git hook on merges into develop or meta
|
|
13
|
+
# - Once at lathe init for the initial population
|
|
10
14
|
|
|
11
15
|
set -euo pipefail
|
|
12
16
|
|
|
13
17
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
14
18
|
HARNESS="$REPO/harness"
|
|
15
|
-
TARGET="$REPO/target"
|
|
16
19
|
|
|
17
20
|
if [ ! -d "$HARNESS" ]; then
|
|
18
|
-
echo "sync
|
|
21
|
+
echo "sync.sh: $HARNESS does not exist" >&2
|
|
19
22
|
exit 1
|
|
20
23
|
fi
|
|
21
24
|
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
cp -
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
cp -R "$HARNESS/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
25
|
+
# Branch detection. Detached HEAD = abort with no-op (don't mangle anything).
|
|
26
|
+
BRANCH="$(git -C "$REPO" symbolic-ref --short HEAD 2>/dev/null || true)"
|
|
27
|
+
if [ -z "$BRANCH" ]; then
|
|
28
|
+
echo "sync.sh: HEAD is detached (no branch). Skipping sync." >&2
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
case "$BRANCH" in
|
|
33
|
+
develop)
|
|
34
|
+
# ---- target side: harness/* (excluding harness/meta/) → worktree root ----
|
|
35
|
+
rm -f "$REPO/CLAUDE.md" "$REPO/plan_template.html"
|
|
36
|
+
rm -rf "$REPO/.claude" "$REPO/workflow" "$REPO/hooks"
|
|
37
|
+
|
|
38
|
+
cp -f "$HARNESS/CLAUDE.md" "$REPO/CLAUDE.md"
|
|
39
|
+
cp -f "$HARNESS/plan_template.html" "$REPO/plan_template.html"
|
|
40
|
+
|
|
41
|
+
mkdir -p "$REPO/.claude/skills" "$REPO/.claude/agents"
|
|
42
|
+
cp -f "$HARNESS/settings.json" "$REPO/.claude/settings.json"
|
|
43
|
+
cp -R "$HARNESS/skills/." "$REPO/.claude/skills/"
|
|
44
|
+
cp -R "$HARNESS/agents/." "$REPO/.claude/agents/"
|
|
45
|
+
|
|
46
|
+
mkdir -p "$REPO/workflow"
|
|
47
|
+
cp -R "$HARNESS/workflow/." "$REPO/workflow/"
|
|
48
|
+
|
|
49
|
+
mkdir -p "$REPO/hooks"
|
|
50
|
+
cp -R "$HARNESS/hooks/." "$REPO/hooks/"
|
|
51
|
+
chmod +x "$REPO/hooks"/*.sh
|
|
52
|
+
|
|
53
|
+
mkdir -p "$REPO/plans"
|
|
54
|
+
echo "sync.sh: develop runtime rebuilt from harness/"
|
|
55
|
+
;;
|
|
56
|
+
|
|
57
|
+
meta)
|
|
58
|
+
# ---- meta side: harness/meta/* → worktree root ----
|
|
59
|
+
if [ ! -d "$HARNESS/meta" ]; then
|
|
60
|
+
echo "sync.sh: $HARNESS/meta does not exist (this lathe install may be older than v1.2)" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
rm -f "$REPO/CLAUDE.md"
|
|
65
|
+
rm -rf "$REPO/.claude"
|
|
66
|
+
|
|
67
|
+
cp -f "$HARNESS/meta/CLAUDE.md" "$REPO/CLAUDE.md"
|
|
68
|
+
|
|
69
|
+
mkdir -p "$REPO/.claude/skills"
|
|
70
|
+
cp -f "$HARNESS/meta/settings.json" "$REPO/.claude/settings.json"
|
|
71
|
+
cp -R "$HARNESS/meta/skills/." "$REPO/.claude/skills/"
|
|
72
|
+
|
|
73
|
+
echo "sync.sh: meta runtime rebuilt from harness/meta/"
|
|
74
|
+
;;
|
|
75
|
+
|
|
76
|
+
*)
|
|
77
|
+
echo "sync.sh: branch '$BRANCH' is neither develop nor meta. Skipping." >&2
|
|
78
|
+
exit 0
|
|
79
|
+
;;
|
|
80
|
+
esac
|
|
@@ -14,9 +14,9 @@ INPUT="$(cat)"
|
|
|
14
14
|
SESSION_ID="$(printf '%s' "$INPUT" | jq -r '.session_id // empty')"
|
|
15
15
|
[ -z "$SESSION_ID" ] && exit 0
|
|
16
16
|
|
|
17
|
+
# Sync'd to <develop_wt>/hooks/, parent is the develop worktree root.
|
|
17
18
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
-
|
|
19
|
-
REPO_ROOT="$(cd "$TARGET_DIR/.." && pwd)"
|
|
19
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
20
20
|
|
|
21
21
|
cd "$REPO_ROOT" || exit 0
|
|
22
22
|
RUN_DIR="runs/$SESSION_ID"
|
|
@@ -21,9 +21,9 @@ set -uo pipefail
|
|
|
21
21
|
|
|
22
22
|
INPUT="$(cat)"
|
|
23
23
|
|
|
24
|
+
# Sync'd to <develop_wt>/hooks/, so parent is the develop worktree root.
|
|
24
25
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
25
|
-
|
|
26
|
-
REPO_ROOT="$(cd "$TARGET_ROOT/.." && pwd)"
|
|
26
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
27
27
|
|
|
28
28
|
SESSION_ID="$(printf '%s' "$INPUT" | jq -r '.session_id // empty')"
|
|
29
29
|
HOOK_EVENT="$(printf '%s' "$INPUT" | jq -r '.hook_event_name // empty')"
|
|
@@ -17,10 +17,10 @@ set -euo pipefail
|
|
|
17
17
|
EVENT="${1:?event name required}"
|
|
18
18
|
INPUT="$(cat)"
|
|
19
19
|
|
|
20
|
-
#
|
|
20
|
+
# This script is sync'd to <develop_wt>/hooks/log.sh, so its parent dir is
|
|
21
|
+
# the develop worktree root (where runs/ lives).
|
|
21
22
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
22
|
-
|
|
23
|
-
REPO_ROOT="$(cd "$TARGET_ROOT/.." && pwd)"
|
|
23
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
24
24
|
|
|
25
25
|
SESSION_ID="$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"')"
|
|
26
26
|
TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# post-merge — auto-run sync.sh
|
|
2
|
+
# post-merge — auto-run sync.sh whenever develop or meta absorbs a merge.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# Both worktrees host gitignored runtime files (`.claude/`, `CLAUDE.md`, ...)
|
|
5
|
+
# generated by sync.sh from `harness/`. After any merge that brings in new
|
|
6
|
+
# harness content, those runtime files must be regenerated. sync.sh itself
|
|
7
|
+
# is branch-aware (develop → target part, meta → meta part).
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
9
|
+
# Hooks for linked worktrees fire from the common .git/hooks/ dir, so this
|
|
10
|
+
# single hook handles both worktrees.
|
|
11
|
+
#
|
|
12
|
+
# UI-side merges (GitHub web) do NOT fire this. Run `lathe sync` manually
|
|
13
|
+
# after `git pull` in those cases.
|
|
10
14
|
|
|
11
15
|
set -uo pipefail
|
|
12
16
|
|
|
13
17
|
BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || true)"
|
|
14
|
-
|
|
18
|
+
case "$BRANCH" in
|
|
19
|
+
develop|meta) ;;
|
|
20
|
+
*) exit 0 ;;
|
|
21
|
+
esac
|
|
15
22
|
|
|
16
23
|
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
|
|
17
24
|
SYNC="$REPO_ROOT/bin/sync.sh"
|
|
18
25
|
[ -x "$SYNC" ] || exit 0
|
|
19
26
|
|
|
20
|
-
echo "[lathe post-merge] running sync.sh on
|
|
27
|
+
echo "[lathe post-merge] running sync.sh on $BRANCH..."
|
|
21
28
|
"$SYNC"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Lathe Helper
|
|
2
|
+
|
|
3
|
+
あなたはこの Lathe project の **operator assistant** です。
|
|
4
|
+
|
|
5
|
+
cwd は project root(共有 bare repo `.git/` と worktree `main/`、`develop/`、`meta/` が並ぶ場所)。worktree の中で起動した別 claude session(target / meta agent / user の vibe coding session)とは **別の存在**で、それらの仕事を取らない。
|
|
6
|
+
|
|
7
|
+
`develop/` で起動された claude は target、`meta/` で起動された claude は meta agent、それぞれ自分の `CLAUDE.md`(gitignored、`harness/` から sync.sh で生成)を読み込む。あなたの role はここ project root にだけ効き、worktree 境界で claude のスコープは止まる。
|
|
8
|
+
|
|
9
|
+
## 役割
|
|
10
|
+
|
|
11
|
+
- ユーザーが Lathe コマンドや構造で迷ったら案内する
|
|
12
|
+
- 求められれば Bash でコマンドを代行実行する
|
|
13
|
+
- worktree / branch / runs / improvements の現状を git 経由で答える
|
|
14
|
+
- target / meta が何をしているかは、`develop/CLAUDE.md` や `meta/meta/CLAUDE.md` を Read してから答える
|
|
15
|
+
|
|
16
|
+
詳細は `lathe-cli` skill を参照(`description` がマッチすれば自動で load される)。
|
|
17
|
+
|
|
18
|
+
## やらない
|
|
19
|
+
|
|
20
|
+
- **user の app コードを実装しない**。実装は user 自身が `features/<name>/` で vibe coding するか、target agent が `lathe process <pr#>` で polish する仕事
|
|
21
|
+
- worktree や branch を勝手に作らない(user に提案して、user が `lathe feature` 等で実行)
|
|
22
|
+
- `develop/` や `meta/` の runtime ファイル(CLAUDE.md, .claude/, hooks/, workflow/ 等)を直接編集しない(gitignored、sync.sh で `harness/` から regenerate されるため)。改善が必要なら meta worktree で `harness/` を編集 → develop に PR → post-merge hook で sync
|
|
23
|
+
|
|
24
|
+
## なぜ project root にいるか
|
|
25
|
+
|
|
26
|
+
worktree 境界で claude の CLAUDE.md 探索は止まる(main/.git の linked-worktree marker で boundary)ため、ここに role-prescriptive な記述を置いても main/develop/meta の session には伝播しない。あなたの role はあくまで「project root にいる時だけ」効く。
|
|
27
|
+
|
|
28
|
+
worktree 内で claude を起動した時はそれぞれの CLAUDE.md(target なら orchestrator、meta なら meta agent)が支配する。あなたはその外側のレイヤー。
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lathe-cli
|
|
3
|
+
description: ユーザーが Lathe project(main/develop/meta worktree + bare .git の構成)の操作で詰まったときに参照する。コマンド一覧、branch / worktree モデル、典型操作(feature 作成・PR 処理・harness 改善・cleanup)、トラブル時の復旧手順を扱う。"lathe", "feature branch", "worktree", "develop", "meta", "PR を処理" 等の言葉が出たら起動する。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lathe CLI 操作リファレンス
|
|
7
|
+
|
|
8
|
+
このプロジェクトは Lathe で初期化された agent harness。あなたはユーザーの **Lathe 操作のアシスタント**。実装そのものは target / meta agent が別 worktree で行うので、あなたは「コマンドを案内する / 代行する / 状態を説明する」役。
|
|
9
|
+
|
|
10
|
+
## 構成(`lathe init` 直後の姿、v1.2 layout)
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
project_root/
|
|
14
|
+
├── .git/ 共有 bare repo(worktree 全部がここを参照)
|
|
15
|
+
├── .claude/ この skill とユーザーの helper 設定(filesystem only at root)
|
|
16
|
+
├── CLAUDE.md helper の役割記述
|
|
17
|
+
├── main/ worktree on main 枝(user の app code)
|
|
18
|
+
├── develop/ worktree on develop 枝
|
|
19
|
+
│ ├── harness/ tracked(target + meta 両方の agent spec の正、harness/meta/ も含む)
|
|
20
|
+
│ ├── bin/sync.sh tracked(branch 判定で target or meta runtime に展開)
|
|
21
|
+
│ ├── runs/, improvements/, plans/ tracked
|
|
22
|
+
│ ├── .gitignore tracked(CLAUDE.md, .claude/, hooks/, workflow/ などを ignore)
|
|
23
|
+
│ └── (CLAUDE.md, .claude/, hooks/, workflow/, plan_template.html) gitignored sync output
|
|
24
|
+
└── meta/ worktree on meta 枝
|
|
25
|
+
├── harness/, bin/, runs/, improvements/, .gitignore tracked(develop から inherit)
|
|
26
|
+
└── (CLAUDE.md, .claude/) gitignored sync output(harness/meta/ から)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
加えて、運用中に動的に増えるもの:
|
|
30
|
+
|
|
31
|
+
- `features/<name>/` — `lathe feature <name>` で作る、user の vibe coding 用 worktree
|
|
32
|
+
- `tasks/<pr#>/` — `lathe process <pr#>` で作る、target が PR を polish する用 worktree
|
|
33
|
+
|
|
34
|
+
## branch モデル
|
|
35
|
+
|
|
36
|
+
| branch | 役割 | 誰が触る |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `main` | release stable | 普段は user、最終的に develop からの PR で更新 |
|
|
39
|
+
| `develop` | integration、target の住処、runs/ の auto-commit 先 | target session、meta からの PR が merge される |
|
|
40
|
+
| `meta` | harness 改善(含む harness/meta/)と improvements/ 蓄積 | meta operator + meta agent |
|
|
41
|
+
| `feature/<name>` | user の vibe code | user が `lathe feature` で生やす |
|
|
42
|
+
|
|
43
|
+
## コマンド一覧
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
lathe init ← 既に走った前提
|
|
47
|
+
lathe target [args...] develop worktree で claude 起動(debug or 直接 task)
|
|
48
|
+
lathe meta [args...] meta worktree で claude 起動
|
|
49
|
+
lathe sync develop の bin/sync.sh 手動実行(post-merge hook が動かない時)
|
|
50
|
+
lathe process <pr#> PR pickup → tasks/<pr#>/ worktree 作成 → target 起動
|
|
51
|
+
lathe feature <name> [--from main|develop]
|
|
52
|
+
features/<name>/ worktree 作成、新 feature/<name> 枝
|
|
53
|
+
lathe feature-done <name> [--keep-branch] [--keep-remote] [--force]
|
|
54
|
+
feature 終了処理(worktree 削除、branch 削除、remote push :branch)
|
|
55
|
+
lathe ls worktree / branch / runs / improvements を一覧
|
|
56
|
+
lathe help help
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 典型操作
|
|
60
|
+
|
|
61
|
+
### 新 feature を始める
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
cd project_root
|
|
65
|
+
lathe feature <name> # features/<name>/ ができる
|
|
66
|
+
cd features/<name>
|
|
67
|
+
# vibe code(claude を別 session で立ち上げて自由に)
|
|
68
|
+
git add . && git commit -m "WIP: vibe ..."
|
|
69
|
+
git push -u origin feature/<name>
|
|
70
|
+
gh pr create --base develop --title "..." --body "..."
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### PR を target に処理させる
|
|
74
|
+
|
|
75
|
+
PR が立ったら(overseer 役):
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
cd project_root
|
|
79
|
+
lathe process <pr#> # tasks/<pr#>/ worktree が新規作成、target が起動
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
claude TUI が立ち上がるので、表示された prompt:「Read .lathe-task.md from the added directory and process it.」を貼る。
|
|
83
|
+
|
|
84
|
+
orchestrator が plan HTML を起こして承認待ちで止まる。承認したら coder/reviewer に dispatch、PR branch に commit/push されて PR が更新される。
|
|
85
|
+
|
|
86
|
+
### feature を終わらせる
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
cd project_root
|
|
90
|
+
gh pr merge <pr#> # GitHub 側で merge
|
|
91
|
+
lathe feature-done <name> # local worktree + branch + remote branch を一掃
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### meta で harness を改善する
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
cd project_root/meta
|
|
98
|
+
git fetch && git merge --no-edit develop # 最新 runs/ を取り込み
|
|
99
|
+
lathe meta # meta agent 起動
|
|
100
|
+
# meta が runs/ 観察 → harness/ 編集 → improvements/<id>/ 記録 → commit
|
|
101
|
+
git push -u origin meta
|
|
102
|
+
gh pr create --base develop --head meta --title "harness: ..."
|
|
103
|
+
gh pr merge <meta pr#>
|
|
104
|
+
# → develop 側 post-merge hook が sync.sh 自動実行 → target/.claude/ 更新
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### release(develop → main)
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
cd project_root/main
|
|
111
|
+
git pull
|
|
112
|
+
git merge develop
|
|
113
|
+
git push origin main
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 全体俯瞰
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
lathe ls # worktree, branch, recent runs/improvements
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## やってはいけない / 詰まりやすい点
|
|
123
|
+
|
|
124
|
+
1. **`main/`, `develop/`, `meta/` の中で `git checkout` で別 branch に切り替えない**
|
|
125
|
+
- それぞれの worktree は固定の枝。別枝は別 worktree。switch すると `fatal: 'X' is already used by worktree at '...'`
|
|
126
|
+
- feature を始めたいなら `lathe feature <name>` を使う
|
|
127
|
+
|
|
128
|
+
2. **`develop/.claude/`、`develop/CLAUDE.md`、`meta/.claude/`、`meta/CLAUDE.md` などを直接編集しない**
|
|
129
|
+
- これは `harness/`(meta 用は `harness/meta/`)から sync.sh で生成された runtime コピー。次回 sync で上書きされる
|
|
130
|
+
- 改善は `harness/` 配下を編集(meta worktree 内で。target 改善は `harness/`、meta 自身の改善は `harness/meta/`)→ develop に PR → post-merge hook で sync 自動実行 → 反映
|
|
131
|
+
|
|
132
|
+
3. **`features/<name>/` を `rm -rf` で消すと metadata が残る**
|
|
133
|
+
- `git worktree list` にゾンビが出る
|
|
134
|
+
- 正しい手順:`lathe feature-done <name>`(または `git --git-dir=.git worktree remove features/<name>`)
|
|
135
|
+
|
|
136
|
+
4. **branch だけ消そうとして `git branch -D feature/X` でエラー**
|
|
137
|
+
- その branch を worktree が checkout 中だから。先に worktree を消す
|
|
138
|
+
- `lathe feature-done` は両方やる
|
|
139
|
+
|
|
140
|
+
5. **post-merge hook は local merge のみ発火**
|
|
141
|
+
- GitHub UI で merge した場合は hook 走らない。`cd develop && git pull && lathe sync` で手動
|
|
142
|
+
|
|
143
|
+
6. **runs/ の auto-commit は local のみ(remote push しない)**
|
|
144
|
+
- 別 machine の meta から見たいなら、`cd develop && git push origin develop` を手動 or 自動化要
|
|
145
|
+
|
|
146
|
+
## トラブルシュート
|
|
147
|
+
|
|
148
|
+
| 症状 | 対処 |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `lathe target` が "develop worktree not found" | `git --git-dir=.git worktree list` で確認、抜けてたら `git worktree add` で復活 |
|
|
151
|
+
| `git worktree list` にゾンビ entry | `git --git-dir=.git worktree prune` |
|
|
152
|
+
| `git branch -D` で "checked out at" エラー | 該当 worktree を先に remove |
|
|
153
|
+
| post-merge hook が走らない | `.git/hooks/post-merge` の存在・実行ビット確認、無ければ template から copy |
|
|
154
|
+
| PR にコードが上がらない | task worktree から `git push` 忘れ、target session 内で確認 |
|
|
155
|
+
|
|
156
|
+
## あなたの責任範囲
|
|
157
|
+
|
|
158
|
+
- ユーザーが Lathe 操作で迷ったら **このコマンド使え** と案内
|
|
159
|
+
- 求められれば Bash で代行実行
|
|
160
|
+
- 構造(worktree / branch / 状態)の質問には git 直接叩いて答える
|
|
161
|
+
- target / meta が何をしているかの質問には、各 worktree の CLAUDE.md(develop の harness/CLAUDE.md、meta の meta/CLAUDE.md)を Read してから答える
|
|
162
|
+
|
|
163
|
+
実装そのもの(user の app コードを書くなど)は **しない**。それは feature worktree で user 自身か、target agent の仕事。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/template/{meta-overlay/meta/.claude → develop/harness/meta}/skills/log-reading/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|