workflow: tighten orchestrator planning return policy

This commit is contained in:
Keisuke Hirata 2026-06-09 09:18:08 +09:00
parent 9f35442a41
commit 8576615f2c
No known key found for this signature in database
4 changed files with 78 additions and 28 deletions

View File

@ -61,9 +61,9 @@ reviewer Pod
- worktree 作成と git 書き込み操作について、人間の許可がある。 - worktree 作成と git 書き込み操作について、人間の許可がある。
- main workspace の unrelated dirty changes を把握している。 - main workspace の unrelated dirty changes を把握している。
- 下位 orchestrator に渡す binding decisions / invariants、implementation latitude、escalation conditions を短く書ける。 - 下位 orchestrator に渡す binding decisions / invariants、implementation latitude、escalation conditions を短く書ける。
- 設計境界・仕様・authority boundary に不確定要素がある場合、planning/requirements sync 互換入口 `ticket-preflight-workflow` の結果が ticket thread に記録されている。 - 設計境界・仕様・authority boundary に不確定要素があり、bounded project-context checks 後も concrete missing decision / information が残る場合、planning/requirements sync 互換入口 `ticket-preflight-workflow` の結果が ticket thread に記録されている。
product / API / UX / authority / design-boundary 方針が複数自然に導ける場合、protocol / scope / permission / history persistence に触れる場合、ticket 自体の再定義が必要な場合は、実装委譲前に planning/requirements sync 互換入口 `ticket-preflight-workflow` を通し、必要なら人間へ戻す。実装ファイルの探索、既存コード読解、局所的な構成選択のような bounded implementation uncertainty は、intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が明確なら coder に委ねてよい。 product / API / UX / authority / design-boundary 方針が複数自然に導ける場合、ticket 自体の再定義が必要な場合、または protocol / scope / permission / history persistence に触れる作業で bounded project-context checks 後も concrete missing decision / information が残る場合は、実装委譲前に planning/requirements sync 互換入口 `ticket-preflight-workflow` を通し、必要なら人間へ戻す。scope / Pod / permission / persistence のような authority-adjacent domain は reviewer focus と context lookup の signal であり、intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が明確なら coder に委ねてよい。実装ファイルの探索、既存コード読解、局所的な構成選択のような bounded implementation uncertainty も同様に coder に委ねてよい。
## Intent packet ## Intent packet

View File

@ -14,6 +14,8 @@ Panel Queue / queued notification は、人間が Orchestrator に routing を
`ready` は Orchestrator routing に十分な状態であり、実装戦術が事前にすべて固定されている状態ではない。Orchestrator は、recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が揃っていれば、bounded implementation uncertainty を残したまま implementation-ready と判断してよい。 `ready` は Orchestrator routing に十分な状態であり、実装戦術が事前にすべて固定されている状態ではない。Orchestrator は、recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が揃っていれば、bounded implementation uncertainty を残したまま implementation-ready と判断してよい。
`ready` / `queued``planning` に戻す判断は、Ticket text や risk flags だけで決めない。Orchestrator は、Ticket thread/artifacts、関連 Ticket / orchestration plan、関連 workflow/docs/code、durable project context、現在の repository/Pod/worktree 状態のうち relevant なものを bounded に確認し、実装前に必要な concrete missing decision / information が残っている場合だけ planning return とする。risk flags と risky domain は context lookup と reviewer focus の signal であり、automatic stop gate ではない。
## 位置づけ ## 位置づけ
```text ```text
@ -43,7 +45,7 @@ Orchestrator は以下を行う。
- routing decision を `TicketComment` で Ticket thread に記録する。 - routing decision を `TicketComment` で Ticket thread に記録する。
- implementation-ready の場合は `multi-agent-workflow` に渡す `IntentPacket` を作る。 - implementation-ready の場合は `multi-agent-workflow` に渡す `IntentPacket` を作る。
- implementation-ready かつ Ticket が `queued` の場合は、worktree 作成 / implementation Pod `SpawnPod` / coder routing などの side effect の前に、既存の typed Ticket backend/tool path で `queued -> inprogress` を記録する。 - implementation-ready かつ Ticket が `queued` の場合は、worktree 作成 / implementation Pod `SpawnPod` / coder routing などの side effect の前に、既存の typed Ticket backend/tool path で `queued -> inprogress` を記録する。
- `ready` または `queued`具体的な不足 decision / information がある場合だけ、typed state-change/routing event 付きで `planning` に戻す。 - `ready` または `queued` concrete missing decision / information がある場合だけ、typed state-change/routing event 付きで `planning` に戻す。その event/comment には missing item、checked context、implementation latitude では足りない理由、次の planning question/action を含める。
## Orchestrator がしないこと ## Orchestrator がしないこと
@ -56,6 +58,7 @@ Orchestrator は以下を行う。
- Ticket tools があるからといって arbitrary filesystem write を行わない。 - Ticket tools があるからといって arbitrary filesystem write を行わない。
- Notification だけを完了証拠にしない。Pod output / diff / validation / Ticket evidence を確認する。 - Notification だけを完了証拠にしない。Pod output / diff / validation / Ticket evidence を確認する。
- 具体的な不足項目を言語化できない場合に、単に risky という理由だけで `planning` に戻さない。その場合は IntentPacket に escalation / reviewer focus を明記して進める。 - 具体的な不足項目を言語化できない場合に、単に risky という理由だけで `planning` に戻さない。その場合は IntentPacket に escalation / reviewer focus を明記して進める。
- risk flags / risky domain / authority-adjacent domain を automatic stop gate として扱わない。これらは bounded context lookup、IntentPacket invariant、reviewer focus、escalation condition に反映する signal である。
## 使用する Ticket tools ## 使用する Ticket tools
@ -75,11 +78,12 @@ Orchestrator は以下を行う。
## Queued acceptance contract ## Queued acceptance contract
`workflow_state = queued` は、Ticket が routing 対象として人間により Orchestrator へ渡された状態である。Orchestrator は queued notification を受けたら、Ticket、workspace state、対象 Ticket の `TicketOrchestrationPlanQuery` 記録を読んで、次のどちらかを行う。 `workflow_state = queued` は、Ticket が routing 対象として人間により Orchestrator へ渡された状態である。Orchestrator は queued notification を受けたら、Ticket、workspace state、対象 Ticket の `TicketOrchestrationPlanQuery` 記録、risk domain に応じた bounded project context を読んで、次のどちらかを行う。
- unblocked と判断する場合: `queued -> inprogress` を記録してから worktree 作成、implementation/review Pod spawn、その他の implementation side effect に進む。 - unblocked と判断する場合: `queued -> inprogress` を記録してから worktree 作成、implementation/review Pod spawn、その他の implementation side effect に進む。
- `before` / `after` / `blocked_by` / `blocks` / `conflicts_with` / `do_not_parallelize` / waiting-capacity 記録がある場合、それを acceptance 判断の入力にする。記録は自動 scheduler ではないため、実際に進めるかどうかは Orchestrator が読んだうえで明示的に決める。 - `before` / `after` / `blocked_by` / `blocks` / `conflicts_with` / `do_not_parallelize` / waiting-capacity 記録がある場合、それを acceptance 判断の入力にする。記録は自動 scheduler ではないため、実際に進めるかどうかは Orchestrator が読んだうえで明示的に決める。
- concrete missing decision / information がある場合: `TicketWorkflowState``queued -> planning` を記録し、reason/body に不足項目を残す。既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。 - risk flags / risky domain がある場合は、IntentPacket に invariants / reviewer focus / escalation conditions を入れる。risk flag だけを `queued -> planning` の理由にしない。
- concrete missing decision / information がある場合: `TicketWorkflowState``queued -> planning` を記録し、reason/body と `TicketComment` に不足項目、checked context、なぜ coder の implementation latitude では解決できないか、次の planning question/action を残す。既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。
- external action 待ちなど planning では解決しない blocker の場合: concise な理由を Ticket thread に記録し、queued のまま待つか、既存の Ticket status/state mechanism で明示的に defer/block する。 - external action 待ちなど planning では解決しない blocker の場合: concise な理由を Ticket thread に記録し、queued のまま待つか、既存の Ticket status/state mechanism で明示的に defer/block する。
Invariant: Invariant:
@ -112,19 +116,25 @@ Action:
### `return_to_planning` ### `return_to_planning`
`ready` または `queued` とされているが、実装 side effect 前に具体的な不足 decision / information が見つかった状態。 `ready` または `queued` とされているが、bounded project-context checks の後でも、実装 side effect 前に解決すべき concrete missing decision / information が残っている状態。
条件: 条件:
- product / API / UX / authority boundary / storage migration / security / secrets などについて、実装前に決めなければならない具体項目がある。 - product / API / UX / authority boundary / storage migration / security / secrets などについて、実装前に決めなければならない具体項目がある。
- 複数の自然な方針があり、human / Orchestrator decision なしでは固定できない。 - 複数の自然な方針があり、human / Orchestrator decision なしでは固定できない。
- acceptance criteria、binding decisions、または escalation conditions に、実装可否を左右する具体的欠落がある。 - acceptance criteria、binding decisions、または escalation conditions に、実装可否を左右する具体的欠落がある。
- Ticket text / risk flags だけではなく、関連 Ticket/thread/artifacts、orchestration plan、関連 workflow/docs/code、durable project context、現在の workspace evidence の relevant subset を確認しても、既存 recorded decision が見つからない。
- その不足は coder の bounded implementation latitude / local tactic selection では安全に解消できない。
Action: Action:
- `TicketWorkflowState``ready -> planning` または `queued -> planning` を記録する。 - `TicketWorkflowState``ready -> planning` または `queued -> planning` を記録する。
- reason/body に具体的な不足項目を含める。 - reason/body と `TicketComment` に以下を明記する。
- `TicketComment` で routing decision と質問を記録する。 - concrete missing decision / information。
- context checkedTicket thread/artifacts、関連 Ticket/plan、docs/workflow/code/durable context/workspace state のうち実際に確認したもの)。
- why implementation latitude is insufficientなぜ coder/reviewer の local tactic や escalation condition では足りないか)。
- next planning question/action。
- risk flag / risky domain だけを return reason にしない。
- 既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。実用的な経路がない場合は follow-up として report する。 - 既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。実用的な経路がない場合は follow-up として report する。
- planning が再度 `ready` にするまで coder Pod は起動しない。 - planning が再度 `ready` にするまで coder Pod は起動しない。
@ -157,12 +167,13 @@ Action:
- reviewer が判断する basis と escalation conditions が明確。 - reviewer が判断する basis と escalation conditions が明確。
- validation が書ける。 - validation が書ける。
- design / authority boundary の未決定がない、または planning return / human decision で補われている。 - design / authority boundary の未決定がない、または planning return / human decision で補われている。
- risk flags / risky domain は context lookup と reviewer focus に反映済みで、bounded context check 後に concrete missing decision / information が残っていない。
- 残る不確実性が bounded implementation investigation / local tactic selection に閉じている。 - 残る不確実性が bounded implementation investigation / local tactic selection に閉じている。
- IntentPacket を短く書ける。 - IntentPacket を短く書ける。
Action: Action:
- `IntentPacket` を作る。 - `IntentPacket` を作る。risky-but-specified Ticket では、risk を stop reason にせず、binding invariants / implementation latitude / escalation conditions / Critical risks / reviewer focus として記録する。
- project-relevant な ordering / blocker / conflict / capacity decision や accepted work plan がある場合は、`TicketOrchestrationPlanRecord` に bounded typed record として残す。local session/socket/raw model output は入れない。 - project-relevant な ordering / blocker / conflict / capacity decision や accepted work plan がある場合は、`TicketOrchestrationPlanRecord` に bounded typed record として残す。local session/socket/raw model output は入れない。
- `TicketComment` に routing decision と IntentPacket を記録する。 - `TicketComment` に routing decision と IntentPacket を記録する。
- 許可があれば `multi-agent-workflow` に接続し、worktree + coder/reviewer sibling loop に進む。 - 許可があれば `multi-agent-workflow` に接続し、worktree + coder/reviewer sibling loop に進む。
@ -273,18 +284,39 @@ Action:
- Validation - Validation
- Thread の plan / decision / implementation_report / review - Thread の plan / decision / implementation_report / review
- Artifacts / branch / commit references - Artifacts / branch / commit references
- risk flags が示す domainauthority-boundary / scope / permission / Pod / persistence / prompt-context / public-api など)
### 3. Classification を決める ### 3. Bounded project-context checks を行う
Ticket evidence だけで planning return を決めない。risk flags や risky domain がある場合は、必要な最小限の project context を確認する。
代表的な確認先:
- Ticket thread/artifacts/resolution と関連 Ticket。
- `TicketOrchestrationPlanQuery` の accepted-plan / ordering / blocker / conflict 記録。
- 関連 workflow/docs/design/development docs。
- 現在の code map や既存 implementation pattern。
- durable memory/Knowledge/project decisions利用可能で、判断に関係する場合
- repository / branch / worktree / visible Pod state。
目的は broad repository archaeology ではなく、以下を区別できるだけの bounded check である。
- genuinely missing binding decision / requirement / invariant / acceptance criterion。
- Ticket thread、関連 Ticket、docs/workflows/code、durable context にすでに記録された decision。
- coder が implementation latitude の中で選べる local tactic / bounded investigation。
### 4. Classification を決める
例: 例:
- implementation-ready に見えるが authority boundary の explicit decision がない → concrete missing decision として `return_to_planning`; explicit decision が Ticket/thread にあるなら binding として IntentPacket に載せる。 - implementation-ready に見えるが authority boundary の explicit decision がなく、bounded context check でも recorded decision がない → concrete missing decision として `return_to_planning`; routing record に missing item / checked context / implementation latitude では足りない理由 / next question を書く
- implementation-ready に見えるが単に risk が高い → `implementation_ready` とし、IntentPacket に escalation / reviewer focus を明記する。 - implementation-ready に見えるが単に risk が高い → `implementation_ready` とし、IntentPacket に escalation / reviewer focus を明記する。
- `allow-spawnpod-child-workspace-cwd` のように scope / Pod / authority-adjacent domain に触れるが、intent、authority invariants、implementation latitude、escalation conditions が指定済み → `implementation_ready`。context check で既存 SpawnPod scope/cwd policy と workflow invariants を確認し、reviewer focus に authority leakage / workspace-cwd separation / delegation-scope preservation を入れる。risk domain だけを理由に `planning` へ戻さない。
- 実装済みだが review がない → `review_needed` - 実装済みだが review がない → `review_needed`
- 要件が曖昧で spike も必要そう → `requirements_sync_needed` を優先し、調査問いを明確化する - 要件が曖昧で spike も必要そう → `requirements_sync_needed` を優先し、調査問いを明確化する
- 完了しているが close 権限がない → `close_ready` として dossier を返す - 完了しているが close 権限がない → `close_ready` として dossier を返す
### 4. Routing decision を Ticket に記録する ### 5. Routing decision を Ticket に記録する
`TicketComment` の role は通常 `decision` または `plan` を使う。 `TicketComment` の role は通常 `decision` または `plan` を使う。
@ -298,10 +330,16 @@ Reason:
Evidence checked: Evidence checked:
- Ticket body / thread / artifacts - Ticket body / thread / artifacts
- related Ticket(s) - related Ticket(s) / orchestration plan records
- code/docs/workflow paths - code/docs/workflow paths
- branch/worktree/Pod state if relevant - branch/worktree/Pod state if relevant
If returning to planning:
- Missing decision/information: ...
- Context checked: summarize the relevant subset from Evidence checked above
- Why implementation latitude is insufficient: ...
- Next planning question/action: ...
Next action: Next action:
- ... - ...
@ -309,7 +347,7 @@ Escalate if:
- ... - ...
``` ```
### 5. IntentPacket を作るimplementation_ready の場合) ### 6. IntentPacket を作るimplementation_ready の場合)
`multi-agent-workflow` に渡す前に、以下を短くまとめる。 `multi-agent-workflow` に渡す前に、以下を短くまとめる。
@ -342,7 +380,7 @@ Critical risks / reviewer focus:
IntentPacket が短く書けない場合、`implementation_ready` ではなく `return_to_planning` または `requirements_sync_needed` に戻す。 IntentPacket が短く書けない場合、`implementation_ready` ではなく `return_to_planning` または `requirements_sync_needed` に戻す。
### 6. 後続 Workflow へ接続する ### 7. 後続 Workflow へ接続する
- `requirements_sync_needed``ticket-intake-workflow` / human / planning sync - `requirements_sync_needed``ticket-intake-workflow` / human / planning sync
- `return_to_planning``ticket-preflight-workflow`legacy compatibility slug の planning sync entry - `return_to_planning``ticket-preflight-workflow`legacy compatibility slug の planning sync entry
@ -358,7 +396,7 @@ IntentPacket が短く書けない場合、`implementation_ready` ではなく `
この Workflow の完了条件は次のいずれかである。 この Workflow の完了条件は次のいずれかである。
- routing decision が Ticket に記録され、次に接続する Workflow / human action が明確である。 - routing decision が Ticket に記録され、次に接続する Workflow / human action が明確である。
- `ready` / `queued``planning` に戻した場合、typed state-change/routing event に concrete missing decision / information reason が残っている。 - `ready` / `queued``planning` に戻した場合、typed state-change/routing event に concrete missing decision / information、checked context、implementation latitude では足りない理由、次の planning question/action が残っている。
- implementation-ready Ticket について IntentPacket が Ticket に記録され、`multi-agent-workflow` に渡せる。 - implementation-ready Ticket について IntentPacket が Ticket に記録され、`multi-agent-workflow` に渡せる。
- requirements-sync / planning return / spike / blocked / review / close-ready の理由と次 action が Ticket に記録されている。 - requirements-sync / planning return / spike / blocked / review / close-ready の理由と次 action が Ticket に記録されている。
- routing 不要と判断され、その理由が明確である。 - routing 不要と判断され、その理由が明確である。

View File

@ -11,7 +11,7 @@ requires: []
## 目的 ## 目的
実装に入る前または Orchestrator routing 中に、具体的な未決定事項が見つかった Ticket を planning に戻し、Ticket thread に監査可能な形で同期内容を残す。 実装に入る前または Orchestrator routing 中に、bounded project-context checks 後も concrete missing decision / information / acceptance condition が残る Ticket を planning に戻し、Ticket thread に監査可能な形で同期内容を残す。
この workflow は次をしてはいけない。 この workflow は次をしてはいけない。
@ -25,12 +25,12 @@ requires: []
次のいずれかを満たす場合に使う。 次のいずれかを満たす場合に使う。
- `planning` Ticket の要件・受け入れ条件・制約を明確化する。 - `planning` Ticket の要件・受け入れ条件・制約を明確化する。
- `ready` または `queued` Ticket について、Orchestrator が実装開始前に具体的な不足情報・未決定事項を特定した。 - `ready` または `queued` Ticket について、Orchestrator が Ticket/thread/artifacts、関連 Ticket/plan、関連 workflow/docs/code、durable project context、workspace evidence の relevant subset を bounded に確認したうえで、実装開始前に concrete missing decision / information を特定した。
- 既存 Ticket に obsolete state vocabulary が残っており、planning terminology へ整理する必要がある。 - 既存 Ticket に obsolete state vocabulary が残っており、planning terminology へ整理する必要がある。
適用しない条件: 適用しない条件:
- Orchestrator が具体的な不足項目を言語化できない。 - Orchestrator が具体的な不足項目、checked context、implementation latitude では足りない理由を言語化できない。
- 単に変更範囲が広い、リスクが高い、またはレビュー観点が多いだけである。 - 単に変更範囲が広い、リスクが高い、またはレビュー観点が多いだけである。
- すでに `queued -> inprogress` が記録され、実装 side effect が始まっている。 - すでに `queued -> inprogress` が記録され、実装 side effect が始まっている。
@ -39,11 +39,12 @@ requires: []
## 手順 ## 手順
1. Ticket の current frontmatter と recent thread を読む。 1. Ticket の current frontmatter と recent thread を読む。
2. 不足している decision / information / acceptance condition を箇条書きで特定する。 2. `ready` / `queued` から planning に戻す場合は、関連 Ticket/plan、docs/workflow/code、durable project context、workspace state の relevant subset を bounded に確認する。
3. `ready` または `queued` から戻す場合は、typed state change で `to = planning` を記録する。reason/body には具体的な不足項目を含める。 3. 不足している decision / information / acceptance condition を箇条書きで特定し、なぜ coder/reviewer の implementation latitude や escalation condition では足りないかを書く。
4. 既存の claimed live/restorable Intake/Planning Pod があり、利用可能な通知経路がある場合は、その Pod に同じ不足理由を通知する。実用的な経路が無い場合は follow-up として report する。 4. `ready` または `queued` から戻す場合は、typed state change で `to = planning` を記録する。reason/body には concrete missing item、checked context、implementation latitude では足りない理由、次の planning question/action を含める。
5. Ticket body または thread に requirements sync 結果を残す。 5. 既存の claimed live/restorable Intake/Planning Pod があり、利用可能な通知経路がある場合は、その Pod に同じ不足理由を通知する。実用的な経路が無い場合は follow-up として report する。
6. Ticket が queue 可能になったら `planning -> ready` を typed state change / `TicketIntakeReady` で記録する。 6. Ticket body または thread に requirements sync 結果を残す。
7. Ticket が queue 可能になったら `planning -> ready` を typed state change / `TicketIntakeReady` で記録する。
## 記録テンプレート ## 記録テンプレート
@ -53,6 +54,17 @@ requires: []
Missing decisions / information: Missing decisions / information:
- ... - ...
Context checked:
- Ticket/thread/artifacts: ...
- related Ticket/plan: ...
- docs/workflow/code/durable/workspace context: ...
Why implementation latitude is insufficient:
- ...
Next planning question/action:
- ...
Decisions made: Decisions made:
- ... - ...
@ -70,5 +82,5 @@ Readiness:
## 完了条件 ## 完了条件
- Ticket に具体的な不足項目または解決済み decision が記録されている。 - Ticket に具体的な不足項目または解決済み decision が記録されている。
- `planning` に戻した場合、state_changed event に from/to/reason/body が残っている。 - `planning` に戻した場合、state_changed event または thread に concrete missing decision / information、checked context、implementation latitude では足りない理由、次の planning question/action が残っている。
- `ready` に進める場合、未解決の blocking attention/action が残っていない。 - `ready` に進める場合、未解決の blocking attention/action が残っていない。

View File

@ -158,11 +158,11 @@ Routing classifications include:
- `defer_pending` - `defer_pending`
- `closed_or_noop` - `closed_or_noop`
Routing decisions should be recorded with `TicketComment` using `plan` or `decision` role. The decision should state the classification, evidence checked, reason, next action, and escalation conditions. Routing decisions should be recorded with `TicketComment` using `plan` or `decision` role. The decision should state the classification, evidence checked, reason, next action, and escalation conditions. For `return_to_planning`, the record must also state the concrete missing decision/information, context checked, why implementation latitude is insufficient, and the next planning question/action.
### 3. Planning/requirements sync ### 3. Planning/requirements sync
Use `ticket-preflight-workflow` only as a legacy compatibility slug for planning/requirements sync. Return `ready` or `queued` Tickets to `planning` only when the Orchestrator can name a concrete missing decision or information item. Use `ticket-preflight-workflow` only as a legacy compatibility slug for planning/requirements sync. Return `ready` or `queued` Tickets to `planning` only when the Orchestrator can name a concrete missing decision or information item after bounded project-context checks; risk flags and risky domains are context-lookup and reviewer-focus signals, not automatic stop gates.
Planning sync should resolve or record: Planning sync should resolve or record:
@ -172,7 +172,7 @@ Planning sync should resolve or record:
- critical risks and failure modes; - critical risks and failure modes;
- implementation-ready vs requirements-sync/spike/blocked classification. - implementation-ready vs requirements-sync/spike/blocked classification.
Do not send Tickets with unresolved concrete missing decisions/information directly to coder Pods. Risk alone should proceed with an IntentPacket plus escalation/reviewer focus. Do not send Tickets with unresolved concrete missing decisions/information directly to coder Pods. If no concrete missing item remains after bounded checks, risky-but-specified Tickets should proceed with an IntentPacket plus escalation conditions and reviewer focus.
### 4. Implementation assignment ### 4. Implementation assignment