feat: track orchestration workspace roots
This commit is contained in:
parent
95fb8340eb
commit
e7c78f96df
|
|
@ -64,7 +64,7 @@ reviewer Pod
|
|||
- Ticket lifecycle を使う場合、対象はすでに `inprogress` であるか、worktree 作成・Pod spawn・coder routing の前に Orchestrator が個別に `queued -> inprogress` acceptance を記録できる `queued` Ticket に限る。unqueued Ticket は capacity 埋めの対象にしない。
|
||||
- ticket の背景・意図・制約・受け入れ条件から、実装調査と局所 tactic 選択を coder に委ねても product / API / UX / authority / design-boundary decision を silently 固定しないと判断できる。
|
||||
- worktree 作成と git 書き込み操作について、人間の許可がある。
|
||||
- main workspace の unrelated dirty changes を把握している。
|
||||
- merge target workspace の unrelated dirty changes を把握している。
|
||||
- 下位 orchestrator に渡す binding decisions / invariants、implementation latitude、escalation conditions を短く書ける。
|
||||
- 設計境界・仕様・authority boundary に不確定要素があり、bounded project-context checks 後も concrete missing decision / information が残る場合、planning/requirements sync 互換入口 `ticket-preflight-workflow` の結果が ticket thread に記録されている。
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ reviewer には coder の実装方針ではなく、この intent packet と dif
|
|||
下位 orchestrator を挟まない場合は、以下を最上位 orchestrator が行う。下位 orchestrator を挟む場合は、最上位は intent packet を渡し、以下の実務を下位に委譲する。
|
||||
|
||||
1. 状態確認
|
||||
- `git state --short --branch`
|
||||
- `git status --short --branch`
|
||||
- 対象 ticket / ticket 群
|
||||
- relation metadata / OrchestrationPlan records / do_not_parallelize / conflict or dependency notes
|
||||
- visible Pods、既存 worktree/branch、coder/reviewer follow-up capacity
|
||||
|
|
@ -117,27 +117,29 @@ reviewer には coder の実装方針ではなく、この intent packet と dif
|
|||
|
||||
2. worktree 作成
|
||||
- 対象 Ticket が `queued` なら、この step の前に typed Ticket backend/tool path で `queued -> inprogress` を記録する。これより前に branch 作成、worktree 作成、Pod spawn、実装調査依頼などの implementation side effect を行わない。
|
||||
- `$user/worktree-workflow` に従い `./.worktree/<task-name>` を作る。
|
||||
- Orchestrator が dedicated orchestration worktree で動く場合でも、implementation worktree は Orchestrator cwd ではなく recorded original workspace root の `.worktree` 配下に作る。
|
||||
- merge-completion は recorded merge target workspace で行い、Orchestrator cwd を merge target とみなさない。
|
||||
- `$user/worktree-workflow` に従い `<original-workspace-root>/.worktree/<task-name>` を作る。
|
||||
- `.yoi` 自体は除外しない。tracked project records は child worktree に存在してよく、`.yoi/memory` と local/runtime/log/lock/secret-like paths だけを sparse checkout で除外する。
|
||||
|
||||
3. coder Pod spawn
|
||||
- read scope: main workspace 全体。
|
||||
- read scope: original workspace root 全体、または実装に必要な bounded read scope。
|
||||
- write scope: child worktree、または必要最小 directory。
|
||||
- task には以下を明示する。
|
||||
- child worktree path / branch
|
||||
- 対象 ticket path
|
||||
- intent packet
|
||||
- SpawnPod の `cwd` は child worktree に設定すること(`cwd` は process/tool default cwd であり、scope/authority ではない)
|
||||
- main workspace の `TODO.md` / `tickets/` / `docs/report/` / `.yoi` は編集しないこと
|
||||
- Orchestrator workspace / recorded Ticket backend の `TODO.md` / Ticket records / `docs/report/` / `.yoi` は編集しないこと
|
||||
- child worktree 内の tracked `.yoi` project records は実装対象に必要な branch-local artifacts/dossiers として編集してよいが、`.yoi/memory` や local/runtime/secret-like files は作らないこと
|
||||
- active orchestration progress と最終 review/approval/close は main workspace の責任として残すこと
|
||||
- active orchestration progress と最終 review/approval/close は Orchestrator workspace または recorded Ticket backend の責任として残すこと
|
||||
- 遵守すべき binding decisions / invariants と escalation conditions
|
||||
- 実行すべき build / test / format
|
||||
- 完了報告項目
|
||||
|
||||
4. coder 完了確認
|
||||
- `ReadPodOutput` で報告を読む。
|
||||
- 通知が来ない場合でも、worktree の `git state` / `git diff` / test で完了状態を確認する。
|
||||
- 通知が来ない場合でも、worktree の `git status` / `git diff` / test で完了状態を確認する。
|
||||
- coder が止まった場合、worktree 状態を見て再 spawn / rollback / 親 escalation を判断する。
|
||||
|
||||
5. reviewer Pod spawn
|
||||
|
|
@ -161,9 +163,9 @@ reviewer には coder の実装方針ではなく、この intent packet と dif
|
|||
- 親がコードを直接理解しなくても判断できるよう、変更の概念的説明と evidence をまとめる。
|
||||
|
||||
8. merge / lifecycle
|
||||
- 最上位 orchestrator または人間の許可を持つ orchestrator が main workspace へ merge する。
|
||||
- `TODO.md` から該当行を削除し、ticket を完了処理して commit する。
|
||||
- main workspace で必要な test / `cargo check --workspace` / `cargo fmt --check` を再実行する。
|
||||
- 最上位 orchestrator または人間の許可を持つ orchestrator が recorded merge target workspace へ merge する。
|
||||
- Ticket を完了処理して commit する。TODO cleanup が対象 Ticket の明示要件なら recorded merge target workspace で行う。
|
||||
- recorded merge target workspace で必要な test / `cargo check --workspace` / `cargo fmt --check` を再実行する。
|
||||
|
||||
## coder Pod の責務
|
||||
|
||||
|
|
@ -208,7 +210,7 @@ coder Pod には child worktree 内での commit を許可してよい。
|
|||
- commit は ticket 内で意味のある粒度にする。
|
||||
- 例: `feat: ...`、`fix: ...`、`test: ...`、`docs: ...`
|
||||
- coder Pod は merge / push / branch deletion / worktree remove をしない。
|
||||
- coder Pod は main workspace の Ticket 完了処理 commit、最終 review/approval/close をしない。child worktree 側には branch-local dossier や実装証跡を残してよい。
|
||||
- coder Pod は recorded Ticket backend の Ticket 完了処理 commit、最終 review/approval/close をしない。child worktree 側には branch-local dossier や実装証跡を残してよい。
|
||||
- orchestrator は review 時に commit 粒度も確認する。
|
||||
- 必要な修正は、原則追加 commit として積む。履歴改変や squash は人間の明示指示がある時だけ行う。
|
||||
|
||||
|
|
@ -221,9 +223,9 @@ reviewer が approve し blocker が残っていない場合、明示的な stan
|
|||
1. coder Pod / reviewer Pod を停止し、scope を回収する。
|
||||
2. orchestrator が merge-ready dossier を確認する。
|
||||
3. 最上位 orchestrator が必要最小限の spot check を行う。
|
||||
4. main workspace で `git merge --no-ff <branch>` する。
|
||||
5. `TODO.md` と ticket を完了処理して commit する。
|
||||
6. main workspace で検証コマンドを再実行する。
|
||||
4. recorded merge target workspace で `git merge --no-ff <branch>` する。
|
||||
5. Ticket を完了処理して commit する。TODO cleanup が対象 Ticket の明示要件なら同じ merge target workspace で行う。
|
||||
6. recorded merge target workspace で検証コマンドを再実行する。
|
||||
7. 変更内容・commit・検証結果・残 dirty changes を報告する。
|
||||
|
||||
### Request changes
|
||||
|
|
|
|||
|
|
@ -1,34 +1,34 @@
|
|||
---
|
||||
description: yoi プロジェクトで child git worktree を作成・管理するための機械的手順。coder Pod に作らせず、orchestrator Pod が main workspace で実行する。
|
||||
description: yoi プロジェクトで child git worktree を作成・管理するための機械的手順。coder Pod に作らせず、orchestrator Pod が original workspace root に対して実行する。
|
||||
model_invokation: true
|
||||
user_invocable: true
|
||||
requires: []
|
||||
---
|
||||
# Worktree Workflow
|
||||
|
||||
yoi プロジェクトで実装差分を main workspace から分離するため、`./.worktree/<task-name>` に child git worktree を作る。これは **worktree の扱い方だけ** を定める Workflow であり、ticket 選定、coder / reviewer sibling の起動、外部レビュー、merge の運用は `$user/multi-agent-workflow` 側で扱う。
|
||||
yoi プロジェクトで実装差分を main workspace から分離するため、`<original-workspace-root>/.worktree/<task-name>` に child git worktree を作る。これは **worktree の扱い方だけ** を定める Workflow であり、ticket 選定、coder / reviewer sibling の起動、外部レビュー、merge の運用は `$user/multi-agent-workflow` 側で扱う。
|
||||
|
||||
yoi では Pod の write scope が排他的に委譲されるため、child Pod の write scope は child worktree に限定する。child worktree は Yoi project records marker として tracked `.yoi` records を含んでよいが、generated/personal memory root `.yoi/memory`、local override、runtime state、logs、locks、secret-like files は出さない。main workspace は active orchestration progress と最終 review/approval/close の authority として残す。
|
||||
yoi では Pod の write scope が排他的に委譲されるため、child Pod の write scope は child worktree に限定する。child worktree は Yoi project records marker として tracked `.yoi` records を含んでよいが、generated/personal memory root `.yoi/memory`、local override、runtime state、logs、locks、secret-like files は出さない。Orchestrator workspace or recorded Ticket backend remains the authority for active orchestration progress and final review/approval/close.
|
||||
|
||||
## 適用範囲
|
||||
|
||||
この Workflow は親 Pod / 下位 orchestrator が main workspace で実行する。
|
||||
この Workflow は親 Pod / 下位 orchestrator が original workspace root に対して実行する。Orchestrator が専用 worktree で動く場合でも、implementation worktree は Orchestrator cwd ではなく original workspace root 側で作成する。
|
||||
|
||||
- coder Pod にこの Workflow を渡して worktree を作らせない。
|
||||
- coder Pod は、orchestrator が作成済みの child worktree を受け取り、その中で実装・build・test・報告を行う。
|
||||
- reviewer Pod は、coder Pod の子ではなく orchestrator 配下の sibling として、原則 read-only で main workspace と child worktree を読む。
|
||||
- ticket 作成、active orchestration progress、最終 review/approval/close は main workspace 側で扱う。
|
||||
- ticket 作成、active orchestration progress、最終 review/approval/close は Orchestrator workspace または記録済み Ticket backend 側で扱う。
|
||||
- branch-local artifacts / dossiers / docs/report / tracked `.yoi` project records は、実装対象に必要なら child worktree 内で扱ってよい。
|
||||
|
||||
## 原則
|
||||
|
||||
- 1 ticket / 1 実装 task につき 1 worktree を作る。
|
||||
- 複数 ticket を下位 orchestrator に任せる場合も、実装差分は ticket / bounded task ごとに worktree を分ける。
|
||||
- worktree path は `./.worktree/<task-name>`。
|
||||
- worktree path は `<original-workspace-root>/.worktree/<task-name>`。
|
||||
- branch 名は原則 `<task-name>` と同じ kebab-case。
|
||||
- child worktree には `.yoi` project records を出してよい。
|
||||
- child worktree では `.yoi/memory`、local/runtime/log/lock/secret-like paths を sparse checkout で除外する。
|
||||
- active orchestration progress と最終 review/approval/close は main workspace 側で扱う。branch-local artifacts/dossiers は child worktree 内に置いてよい。
|
||||
- active orchestration progress と最終 review/approval/close は Orchestrator workspace または記録済み Ticket backend 側で扱う。branch-local artifacts/dossiers は child worktree 内に置いてよい。
|
||||
- push はしない。
|
||||
|
||||
## 事前確認
|
||||
|
|
@ -46,13 +46,13 @@ yoi では Pod の write scope が排他的に委譲されるため、child Pod
|
|||
|
||||
## 作成手順
|
||||
|
||||
main workspace で実行する。
|
||||
original workspace root で実行する。Orchestrator が別 worktree で動く場合は `git -C <original-workspace-root> ...` を使う。
|
||||
|
||||
```bash
|
||||
git worktree add .worktree/<task-name> -b <task-name>
|
||||
git -C <original-workspace-root> worktree add .worktree/<task-name> -b <task-name>
|
||||
|
||||
git -C .worktree/<task-name> sparse-checkout init --no-cone
|
||||
git -C .worktree/<task-name> sparse-checkout set --no-cone \
|
||||
git -C <original-workspace-root>/.worktree/<task-name> sparse-checkout init --no-cone
|
||||
git -C <original-workspace-root>/.worktree/<task-name> sparse-checkout set --no-cone \
|
||||
'/*' \
|
||||
'!/.yoi/memory/' \
|
||||
'!/.yoi/memory/**' \
|
||||
|
|
@ -95,11 +95,11 @@ git -C .worktree/<task-name> sparse-checkout set --no-cone \
|
|||
確認する。
|
||||
|
||||
```bash
|
||||
git -C .worktree/<task-name> state --short --branch
|
||||
test ! -e .worktree/<task-name>/.yoi/memory
|
||||
if test -d .worktree/<task-name>/.yoi; then
|
||||
test ! -e .worktree/<task-name>/.yoi/override.local.toml
|
||||
test -z "$(find .worktree/<task-name>/.yoi \
|
||||
git -C <original-workspace-root>/.worktree/<task-name> status --short --branch
|
||||
test ! -e <original-workspace-root>/.worktree/<task-name>/.yoi/memory
|
||||
if test -d <original-workspace-root>/.worktree/<task-name>/.yoi; then
|
||||
test ! -e <original-workspace-root>/.worktree/<task-name>/.yoi/override.local.toml
|
||||
test -z "$(find <original-workspace-root>/.worktree/<task-name>/.yoi \
|
||||
\( -path '*/_logs' -o -path '*/logs' -o -path '*/locks' \
|
||||
-o -path '*/local' -o -path '*/runtime' -o -path '*/pods' \
|
||||
-o -path '*/sessions' -o -path '*/sockets' -o -path '*/tmp' \
|
||||
|
|
@ -148,7 +148,7 @@ reviewer は原則 write scope を持たない。review artifact を書かせる
|
|||
|
||||
## 完了時の扱い
|
||||
|
||||
worktree 作成 Workflow としては、完了時に merge しない。merge、ticket 完了、TODO 削除は `$user/multi-agent-workflow` または人間の明示指示で行う。
|
||||
worktree 作成 Workflow としては、完了時に merge しない。merge、ticket 完了、worktree cleanup は記録済み merge target workspace に対して行う。merge-completion は `/multi-agent-workflow` または明示された上位 Orchestrator の権限で扱う。
|
||||
|
||||
coder Pod へ渡す完了報告項目の標準形:
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ impl TicketIntakeHandoff {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TicketRoleLaunchContext {
|
||||
pub workspace_root: PathBuf,
|
||||
pub original_workspace_root: Option<PathBuf>,
|
||||
pub target_workspace_root: Option<PathBuf>,
|
||||
pub role: TicketRole,
|
||||
pub pod_name: Option<String>,
|
||||
pub ticket: Option<TicketRef>,
|
||||
|
|
@ -95,6 +97,8 @@ impl TicketRoleLaunchContext {
|
|||
pub fn new(workspace_root: impl Into<PathBuf>, role: TicketRole) -> Self {
|
||||
Self {
|
||||
workspace_root: workspace_root.into(),
|
||||
original_workspace_root: None,
|
||||
target_workspace_root: None,
|
||||
role,
|
||||
pod_name: None,
|
||||
ticket: None,
|
||||
|
|
@ -108,12 +112,41 @@ impl TicketRoleLaunchContext {
|
|||
report_expectations: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_original_workspace_root(mut self, root: impl Into<PathBuf>) -> Self {
|
||||
self.original_workspace_root = Some(root.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_target_workspace_root(mut self, root: impl Into<PathBuf>) -> Self {
|
||||
self.target_workspace_root = Some(root.into());
|
||||
self
|
||||
}
|
||||
|
||||
fn original_workspace_root(&self) -> &Path {
|
||||
self.original_workspace_root
|
||||
.as_deref()
|
||||
.unwrap_or(&self.workspace_root)
|
||||
}
|
||||
|
||||
fn target_workspace_root(&self) -> &Path {
|
||||
self.target_workspace_root
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| self.original_workspace_root())
|
||||
}
|
||||
|
||||
fn implementation_worktree_root(&self) -> PathBuf {
|
||||
self.original_workspace_root().join(".worktree")
|
||||
}
|
||||
}
|
||||
|
||||
/// Pure launch plan usable by TUI/CLI surfaces before executing the launch.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TicketRoleLaunchPlan {
|
||||
pub workspace_root: PathBuf,
|
||||
pub original_workspace_root: PathBuf,
|
||||
pub target_workspace_root: PathBuf,
|
||||
pub implementation_worktree_root: PathBuf,
|
||||
pub role: TicketRole,
|
||||
pub pod_name: String,
|
||||
pub profile: String,
|
||||
|
|
@ -246,8 +279,15 @@ pub fn plan_ticket_role_launch_with_config(
|
|||
validate_ticket_role_profile(context.role, &profile, &context.workspace_root, &pod_name)?;
|
||||
let prompt = build_launch_prompt(&context, &profile, &workflow, launch_prompt_ref.as_deref());
|
||||
|
||||
let original_workspace_root = context.original_workspace_root().to_path_buf();
|
||||
let target_workspace_root = context.target_workspace_root().to_path_buf();
|
||||
let implementation_worktree_root = context.implementation_worktree_root();
|
||||
|
||||
Ok(TicketRoleLaunchPlan {
|
||||
workspace_root: context.workspace_root,
|
||||
original_workspace_root,
|
||||
target_workspace_root,
|
||||
implementation_worktree_root,
|
||||
role: context.role,
|
||||
pod_name,
|
||||
profile,
|
||||
|
|
@ -580,6 +620,8 @@ fn build_launch_prompt(
|
|||
out.push_str("Target Ticket: not specified\n");
|
||||
}
|
||||
|
||||
append_workspace_routing_context(&mut out, context);
|
||||
|
||||
match non_empty(context.user_instruction.as_deref()) {
|
||||
Some(instruction) => push_bounded_section(&mut out, "User/action instruction", instruction),
|
||||
None => out.push_str("\nUser/action instruction: not specified\n"),
|
||||
|
|
@ -619,6 +661,43 @@ fn build_launch_prompt(
|
|||
out
|
||||
}
|
||||
|
||||
fn append_workspace_routing_context(out: &mut String, context: &TicketRoleLaunchContext) {
|
||||
let original_workspace_root = context.original_workspace_root();
|
||||
let target_workspace_root = context.target_workspace_root();
|
||||
let implementation_worktree_root = context.implementation_worktree_root();
|
||||
let should_emit = context.original_workspace_root.is_some()
|
||||
|| context.target_workspace_root.is_some()
|
||||
|| context.role == TicketRole::Orchestrator;
|
||||
if !should_emit {
|
||||
return;
|
||||
}
|
||||
|
||||
out.push_str("\nWorkspace routing context:\n");
|
||||
push_bounded_bullet(
|
||||
out,
|
||||
"role_workspace_root",
|
||||
&context.workspace_root.display().to_string(),
|
||||
);
|
||||
push_bounded_bullet(
|
||||
out,
|
||||
"original_workspace_root",
|
||||
&original_workspace_root.display().to_string(),
|
||||
);
|
||||
push_bounded_bullet(
|
||||
out,
|
||||
"implementation_worktree_root",
|
||||
&implementation_worktree_root.display().to_string(),
|
||||
);
|
||||
push_bounded_bullet(
|
||||
out,
|
||||
"merge_target_workspace_root",
|
||||
&target_workspace_root.display().to_string(),
|
||||
);
|
||||
out.push_str(
|
||||
"- Treat `role_workspace_root` as the launched role runtime workspace/Ticket backend root. Create implementation worktrees under `implementation_worktree_root`, not relative to the role cwd, and run merge-completion against `merge_target_workspace_root`.\n",
|
||||
);
|
||||
}
|
||||
|
||||
fn append_role_execution_guidance(
|
||||
out: &mut String,
|
||||
role: TicketRole,
|
||||
|
|
@ -796,6 +875,9 @@ mod tests {
|
|||
fn test_launch_plan(workspace: &std::path::Path) -> TicketRoleLaunchPlan {
|
||||
TicketRoleLaunchPlan {
|
||||
workspace_root: workspace.to_path_buf(),
|
||||
original_workspace_root: workspace.to_path_buf(),
|
||||
target_workspace_root: workspace.to_path_buf(),
|
||||
implementation_worktree_root: workspace.join(".worktree"),
|
||||
role: TicketRole::Intake,
|
||||
pod_name: "ticket-intake".to_string(),
|
||||
profile: "project:intake".to_string(),
|
||||
|
|
@ -1179,7 +1261,10 @@ workflow = "ticket-review-workflow"
|
|||
assert!(orchestrator_text.contains("binding decisions/invariants"));
|
||||
assert!(orchestrator_text.contains("not unrecorded preferred tactics"));
|
||||
assert!(orchestrator_text.contains("merge-ready dossier"));
|
||||
assert!(orchestrator_text.contains("do not merge, close, or record final main approval"));
|
||||
assert!(orchestrator_text.contains(
|
||||
"Stop at a merge-ready dossier only when merge-completion authority is absent"
|
||||
));
|
||||
assert!(orchestrator_text.contains("continue through merge, validation, Ticket close"));
|
||||
|
||||
let mut coder = TicketRoleLaunchContext::new(temp.path(), TicketRole::Coder);
|
||||
coder.ticket = Some(TicketRef::id("20260605-190330-ticket-role-pod-launcher"));
|
||||
|
|
@ -1228,18 +1313,37 @@ workflow = "ticket-review-workflow"
|
|||
orchestrator.intent_packet =
|
||||
Some("Complete an already-reviewed merge-ready Ticket.".into());
|
||||
orchestrator.validation = vec!["cargo test -p client ticket_role --lib".into()];
|
||||
orchestrator = orchestrator
|
||||
.with_original_workspace_root(temp.path().join("original"))
|
||||
.with_target_workspace_root(temp.path().join("target"));
|
||||
|
||||
let plan = plan_ticket_role_launch(orchestrator).unwrap();
|
||||
let text = text_segment(&plan);
|
||||
assert_eq!(plan.workspace_root, temp.path());
|
||||
assert_eq!(plan.original_workspace_root, temp.path().join("original"));
|
||||
assert_eq!(
|
||||
plan.implementation_worktree_root,
|
||||
temp.path().join("original").join(".worktree")
|
||||
);
|
||||
assert_eq!(plan.target_workspace_root, temp.path().join("target"));
|
||||
let spawn_config = plan
|
||||
.spawn_config(PodRuntimeCommand::for_executable("/bin/yoi"))
|
||||
.unwrap();
|
||||
assert_eq!(spawn_config.workspace_root, temp.path());
|
||||
|
||||
assert!(text.contains("Workspace routing context:"));
|
||||
assert!(text.contains("role_workspace_root"));
|
||||
assert!(text.contains("implementation_worktree_root"));
|
||||
assert!(text.contains("merge_target_workspace_root"));
|
||||
assert!(text.contains("not relative to the role cwd"));
|
||||
assert!(text.contains("Orchestrator merge-completion guidance"));
|
||||
assert!(text.contains("`inprogress` Ticket with a merge-ready dossier"));
|
||||
assert!(text.contains("Conservative or missing authorization mode stops at the dossier"));
|
||||
assert!(text.contains("do not infer merge authority"));
|
||||
assert!(text.contains("explicit user/standing policy may authorize continuing"));
|
||||
assert!(text.contains("dossier branch/worktree/commits match the branch to merge"));
|
||||
assert!(text.contains("independent reviewer approval exists in the dossier"));
|
||||
assert!(text.contains("explicit human override decision is recorded"));
|
||||
assert!(text.contains("the main workspace is safe"));
|
||||
assert!(text.contains("the merge target workspace is safe"));
|
||||
assert!(text.contains("unrelated dirty changes are understood"));
|
||||
assert!(text.contains("dogfooding/workspace policy grants merge authority"));
|
||||
assert!(text.contains("branch-local reviewer verdicts are dossier evidence"));
|
||||
|
|
|
|||
33
docs/design/orchestrator-worktree-layout.md
Normal file
33
docs/design/orchestrator-worktree-layout.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Orchestrator worktree and implementation worktree layout
|
||||
|
||||
Yoi can run an Orchestrator from a dedicated orchestration worktree while implementation worktrees still belong under the original workspace root. The runtime must therefore distinguish role execution cwd/workspace from the target repository root used for implementation branches and merge-completion.
|
||||
|
||||
This decision records the layout policy for Ticket `00001KTTB479X`.
|
||||
|
||||
## Roots
|
||||
|
||||
- `role_workspace_root`: the launched role runtime workspace root and Ticket backend context.
|
||||
- `original_workspace_root`: the repository root from which implementation worktrees should be created.
|
||||
- `implementation_worktree_root`: `<original_workspace_root>/.worktree`.
|
||||
- `merge_target_workspace_root`: the workspace/branch where merge-completion validates and merges.
|
||||
|
||||
When these roots differ, implementation worktrees must be created under `implementation_worktree_root`, not under the Orchestrator process cwd. Merge-completion must run against `merge_target_workspace_root`, not whichever worktree happens to host the Orchestrator.
|
||||
|
||||
## Policy
|
||||
|
||||
- The filesystem Ticket backend remains authoritative for project records; this design does not introduce a Git-external Ticket store.
|
||||
- Main-workspace draft Tickets are not an implicit Orchestrator queue. Queue acceptance still requires explicit Ticket state and routing checks.
|
||||
- Implementation branches should not include unrelated Orchestrator Ticket churn. Orchestration progress stays in the Orchestrator workspace/Ticket backend; child implementation worktrees contain implementation diffs and branch-local artifacts only when needed.
|
||||
- Prompt and workflow guidance must treat merge-ready dossier as a checkpoint. If reviewer approval, clean/safe target workspace, and standing/user merge authority are present, Orchestrator should continue through merge, validation, Ticket close, and cleanup instead of stopping solely because a dossier exists.
|
||||
|
||||
## Implemented in this branch
|
||||
|
||||
- Ticket role launch prompts now emit a `Workspace routing context` section for Orchestrator launches, and for any launch that explicitly provides original/target roots.
|
||||
- `TicketRoleLaunchPlan` carries `original_workspace_root`, `implementation_worktree_root`, and `target_workspace_root` as explicit plan fields for callers/tests.
|
||||
- Orchestrator role prompt resources now say to create implementation worktrees under the original workspace root and to run merge-completion against the recorded target workspace.
|
||||
- `worktree-workflow` now describes `<original-workspace-root>/.worktree/<task-name>` and `git -C <original-workspace-root> ...` instead of assuming the Orchestrator cwd is the repository root.
|
||||
|
||||
## Follow-up boundaries
|
||||
|
||||
- Panel/workspace orchestration can later populate `original_workspace_root` and `target_workspace_root` when launching Orchestrator from a dedicated worktree.
|
||||
- A future implementation can add a first-class orchestration-worktree launcher and cleanup policy, but it must keep the four-root distinction above visible in launch diagnostics and tests.
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
Orchestrator merge-completion guidance:
|
||||
- Enter merge-completion only for an `inprogress` Ticket with a merge-ready dossier. Conservative or missing authorization mode stops at the dossier; do not infer merge authority from public/default configuration.
|
||||
- Enter merge-completion only for an `inprogress` Ticket with a merge-ready dossier. Conservative or missing authorization mode stops at the dossier; explicit user/standing policy may authorize continuing without an extra approval stop.
|
||||
- Required dossier fields before merge: Ticket id; branch/worktree; commits; intent/invariant check; implementation summary; coder/reviewer Pods; blockers fixed or rejected findings with reasons; validation performed; residual risks; dirty state; parent/human decision needs if any.
|
||||
- Before merging, verify the dossier branch/worktree/commits match the branch to merge, independent reviewer approval exists in the dossier or an explicit human override decision is recorded, the main workspace is safe, and unrelated dirty changes are understood.
|
||||
- Before merging, verify the dossier branch/worktree/commits match the branch to merge, independent reviewer approval exists in the dossier or an explicit human override decision is recorded, the merge target workspace is safe, and unrelated dirty changes are understood.
|
||||
- If the Orchestrator is running from a dedicated orchestration worktree, do not infer the merge target from process cwd. Use the recorded `merge_target_workspace_root` / original workspace root, and ensure cleanup removes only the child implementation worktree/branch intended by the dossier.
|
||||
- Merge only when dogfooding/workspace policy grants merge authority. If authority is unavailable, record/return the dossier and stop without merge, close, final main Ticket approval, or cleanup.
|
||||
- Preserve the boundary: branch-local reviewer verdicts are dossier evidence; final main-branch Ticket approval or close happens only during authorized merge-completion after merge and validation evidence.
|
||||
- Authorized sequence: stop/reclaim coder and reviewer Pods where appropriate; merge with `git merge --no-ff <branch>` or the project-agreed method; run post-merge validation appropriate to the change; record review, merge, and validation outcomes in the Ticket thread during merge-completion; transition `inprogress -> done` or close according to typed Ticket workflow rules; then remove the merged child worktree and delete the merged branch unless explicitly kept.
|
||||
- Authorized sequence: stop/reclaim coder and reviewer Pods where appropriate; merge with `git merge --no-ff <branch>` or the project-agreed method from the target workspace; run post-merge validation appropriate to the change; record review, merge, and validation outcomes in the Ticket thread during merge-completion; transition `inprogress -> done` or close according to typed Ticket workflow rules; then remove the merged child worktree and delete the merged branch unless explicitly kept.
|
||||
- Post-merge validation baseline: run focused tests from the Ticket/dossier, `cargo fmt --check`, `git diff --check`, and `target/debug/yoi ticket doctor` where applicable; add broader validation such as `cargo check --workspace --all-targets`, `nix build .#yoi`, or equivalent when risk, API surface, packaging, runtime resources, prompts, or touched files warrant it.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
Orchestrator worktree + agent routing guidance:
|
||||
- Treat `ticket-orchestrator-routing` as the routing gate. Read the Ticket and workspace state first; `ready -> queued` authorizes routing, not implementation side effects.
|
||||
- Keep the launched Orchestrator runtime workspace/Ticket backend root distinct from the original/merge-target workspace root. If the launch context includes `original_workspace_root` or `implementation_worktree_root`, create implementation worktrees under that original root (for example `<original_workspace_root>/.worktree/<task-name>`), not under the Orchestrator's current working directory.
|
||||
- Create worktrees or spawn coder/reviewer Pods only after `state = inprogress` is already recorded and accepted. If the Ticket is still queued and unblocked, record `queued -> inprogress` before any worktree/SpawnPod side effect.
|
||||
- Use `worktree-workflow` for the mechanical worktree plan: create `.worktree/<task-name>`, keep tracked `.yoi` project records visible in the child worktree, exclude `.yoi/memory` plus local/runtime/log/lock/secret-like `.yoi` paths, and keep active orchestration progress plus final review/approval/close in the main workspace unless explicitly designed otherwise.
|
||||
- Use `worktree-workflow` for the mechanical worktree plan: create the child implementation worktree under the recorded original workspace root, keep tracked `.yoi` project records visible in the child worktree, exclude `.yoi/memory` plus local/runtime/log/lock/secret-like `.yoi` paths, and keep active orchestration progress plus final review/approval/close in the Orchestrator workspace unless explicitly designed otherwise.
|
||||
- Use `multi-agent-workflow` for the sibling loop: coder and reviewer are siblings under this Orchestrator; coder gets narrow write scope to the child worktree; reviewer is read-only by default.
|
||||
- Give the coder an intent packet that distinguishes binding decisions/invariants, implementation latitude, escalation conditions, child worktree/branch, validation commands, and report expectations; set SpawnPod `cwd` to the child worktree while delegating explicit scope separately, prohibit editing main-workspace `.yoi`/Ticket/workflow/docs records, and prohibit creating generated memory/local/runtime/secret-like files in the child worktree.
|
||||
- Give the coder an intent packet that distinguishes binding decisions/invariants, implementation latitude, escalation conditions, child worktree/branch, validation commands, and report expectations; set SpawnPod `cwd` to the child worktree while delegating explicit scope separately, prohibit editing the Orchestrator/main `.yoi`/Ticket/workflow/docs records unless explicitly delegated, and prohibit creating generated memory/local/runtime/secret-like files in the child worktree.
|
||||
- Give the reviewer the recorded Ticket intent, binding decisions/invariants, implementation latitude, acceptance criteria, explicit escalation conditions, diff/commits, validation evidence, and blocker/non-blocker criteria; reviewer judgment is against recorded requirements and decisions, not unrecorded preferred tactics. Keep branch-local reviewer verdicts in the review report or merge-ready dossier rather than recording them as final main-branch Ticket approval.
|
||||
- Ticket thread progress may record worktree plan, coder delegated/completed/blocked, reviewer delegated, blocker/fix-loop summaries, and merge-ready dossier pointer; do not merge, close, or record final main approval in this routing/branch-review phase.
|
||||
- Stop at a merge-ready dossier for `orchestrator-merge-completion` containing Ticket id, branch/worktree, commits, intent/invariant check, implementation summary, coder/reviewer Pods, blockers fixed or rejected findings with reasons, validation performed, residual risks, dirty state, and parent/human decision needs if any.
|
||||
- Ticket thread progress may record worktree plan, coder delegated/completed/blocked, reviewer delegated, blocker/fix-loop summaries, and merge-ready dossier pointer.
|
||||
- Stop at a merge-ready dossier only when merge-completion authority is absent or the launch explicitly requires a human stop. If reviewer approval exists, there are no blockers, the target workspace is safe, and standing/user policy authorizes merge-completion, continue through merge, validation, Ticket close, and worktree/branch cleanup rather than stopping at the dossier.
|
||||
- Merge/cleanup must operate on the recorded merge target workspace/branch, not accidentally on the Orchestrator worktree if those roots differ.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user