Scaffold: PLAN.md, tasks/INDEX.md, tasks/board.md

Initial project structure documentation and task breakdown for Multi-Agent Dev Orchestrator (Temporal + Go).
This commit is contained in:
Test
2026-08-20 22:10:14 -07:00
commit 3a8f946105
3 changed files with 500 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
# Poimen Workflows — Development Guidelines
This project orchestrates multi-agent software development tasks using Temporal + Go. The repo is organized as:
- `statemachine/` — Temporal workflow definitions (deterministic state machines)
- `action/` — Temporal activity definitions (units of work / LLM calls)
- `cmd/` — CLI entry points (worker registration, workflow starter)
- `prompts/` — LLM prompt templates (Go-embedded, live-updatable)
- `internal/` — Shared config/locking utilities
- `tests/` — Unit tests via `go.temporal.io/sdk/testsuite`
## Code Standards
### Go Style
Follow `golang-skills` conventions from `~/.claude/skills/golang-skills/`:
- Error handling mandatory; no naked `_ =` discards.
- Idiomatic naming: `ctx` for context, `err` for error returns.
- Interfaces kept narrow; one struct per concern.
- No over-generalization for hypothetical use.
- Documentation via comments only where the WHY is non-obvious.
### Testing
- Every `statemachine/*` change ships with a `testsuite`-based test in `tests/`.
- Unit tests use `go.temporal.io/sdk/testsuite.WorkflowTestEnvironment` with mocked activities.
- Activities are tested in isolation before integrating into workflows.
- No literal timeout/retry values in `action/*` code — all come from `OrchestratorConfig.Tuning` at runtime.
### Activity Design
Activities stay side-effect-isolated (one concern per file) so they remain independently reusable across projects.
- `action/git.go` — all git operations
- `action/skills.go` — skill prep / pi command
- `action/planner.go` — Planner LLM call
- `action/judge.go` — Judge LLM call
- `action/implementer.go` — Implementer LLM + tool-call loop
- `action/lessons.go` — Lessons store read/write
No composite activities like `PrepareAndImplement`; that's a workflow's job, not an activity's.
### Config as Data
**No hardcoded numbers.** Every timeout, retry count, backoff coefficient, stream timeout — all come from `OrchestratorConfig.Tuning` (or role-specific `PromptSpec.Model`), read at execution time. This lets:
- `update-tuning` signal to dynamically adjust timeouts without redeployment
- Planner activity to recommend per-task overrides
- Pi 504 handler to learn and persist `StreamTimeout` across `ContinueAsNew` cycles
**No LLM model hardcoded.** Every model ID comes from `ModelSpec.ModelID`, passed as data.
### Concurrency & Locking
Target repo sits on shared filesystem. Git concurrency is safe by construction:
- Task units use isolated worktrees (`git worktree add -b task/T0.x ...`)
- Commits within a worktree don't need a lock; git serializes object writes
- Only `CloneRepoActivity`, `GitPushActivity`, `GitSquashMergeActivity` need the `orchestrator.lock`, since they mutate the main working tree / refs
Monitor for deadlocks: if two workflows try to push simultaneously, the lock will serialize them. Test with concurrent tasks enabled.
## Task Board Format
Each task row in the board specifies:
- **ID**: `T0.1`, `T0.2`, etc.
- **Description**: One-line scope
- **Status**: `[ ]` (todo), `[x]` (done)
- **Branch**: `task/T0.x` (created when task starts, merged to main on submilestone complete)
- **Verification**: Specific criterion that marks it done (e.g. "Unit test passes", "E2E run completes")
A task is NOT marked done until its verification step passes. This mirrors the Judge role's own job: no hallucinated completion.
## Submilestones & Merges
When all tasks in `T0` (`T0.1` through `T0.9`) pass their verification:
1. Orchestrator calls `GitSquashMergeActivity` to merge all `task/T0.*` branches into `main` as a single squashed commit
2. All `task/T0.*` branches and worktrees are cleaned up
3. Main branch is the canonical history; the 9 subtask commits are compacted into one
This demonstrates the very mechanism the system orchestrates: a working software dev pipeline with multiple agents collaborating on a shared codebase, guarded by state checks (Judge), and landing changes via deterministic git workflow.
## Historical Lessons
Lessons live at `tasks/.orchestrator/lessons/<TaskID>.jsonl` — per-task file of failed attempts. When a Judge calls a task failure, the `UpdateLessonsActivity` appends `{Attempt, Critique, FailedApproachSummary, Timestamp}`. On retry, `ReadLessonsActivity` injects the last N entries into the Implementer's prompt as "known errors — do not repeat this time".
Lessons flush to git only as part of the Planner's board commit, not on every retry — keeps history clean.
## Skills & Preparation
Required skill sources are listed in `OrchestratorConfig.Skills` as a list of references (e.g. `["~/.claude/skills/golang-skills", "custom-skill-repo"]`). `PrepareSkillsActivity` runs once per config change, cloning/fetching them onto the shared FS via the `pi` command. All retry/backoff/timeout is delegated to Temporal's retry machinery, with special handling for 504 (stream timeout learning).
## Environment & Secrets
All external system access is via environment variables, loaded at worker startup:
- `TEMPORAL_NAMESPACE`, `TEMPORAL_TLS_CERT`, `TEMPORAL_TLS_KEY` — Temporal cluster connection
- `ANTHROPIC_API_KEY` — LLM API key
- Any target-repo-specific credentials (e.g. git SSH key) are assumed already available on the shared FS (e.g. via Kubernetes secret mount)
Use homelab's `vsource .env` pattern to load from a `.env` file during local development.
## Observability
- Temporal Web UI (`temporal.riotpiao.com:8080` or similar) shows workflow execution, signal delivery, activity retries
- Workflow `current-config` query returns live `OrchestratorConfig` (useful for debugging which tuning values are in effect)
- Activity heartbeats (`activity.RecordHeartbeat`) are sent after each tool-call iteration, visible in Temporal's activity details
- Lessons file grows as retries happen; inspect it on failure to understand what the Implementer is learning
## Deployment & Homelab Integration
This repo is application-layer code against the homelab's Temporal cluster. The orchestrator runs as a Kubernetes pod with:
- Persistent volume (PVC) for the shared FS where target repos are cloned
- Network access to Temporal + Anthropic APIs
- Git SSH key mounted for cloning target repos
The Kubernetes manifests + Helm charts live in the homelab repo under `k8s/` and follow homelab's GitOps workflow (commit → ArgoCD sync). This repo's CI/CD (GitHub Actions or Forgejo Actions) builds and pushes the Docker image; the homelab repo triggers a new pod deploy on image push.
## Questions & Debugging
If a task is marked done but you suspect it's wrong:
1. Re-run its verification step manually
2. Check the unit test against the latest code
3. For e2e tasks, review Temporal Web UI logs + board file + lessons file on the target repo
4. Update the board and task description if the criterion was misunderstood
If code doesn't compile or tests fail:
1. Check Go version and Temporal SDK version match
2. Run `go mod tidy` and `go mod vendor` if dependencies drift
3. Look for hardcoded values or model IDs that should be config instead
+38
View File
@@ -0,0 +1,38 @@
# Task Board — Milestone T0
**Submilestone:** T0 (Multi-Agent Dev Orchestrator Temporal system)
| ID | Scope | Status | Branch | Verification | Notes |
|----|-------|--------|--------|--------------|-------|
| T0.1 | Repo scaffold: go.mod, statemachine/, action/, cmd/, prompts/, internal/, tests/ | [ ] | `task/T0.1` | `go build ./...` succeeds; layout matches PLAN.md | Foundation |
| T0.2 | Shared types: ModelSpec, PromptSpec, OrchestratorConfig, ActivityTuning, PiRetryPolicy | [ ] | `task/T0.2` | Unit test asserts all defaults (5m/2s/30s/2.0/30s stream/2m stream-max) | Config data model |
| T0.3 | Git & locking: CloneRepoActivity, worktrees, squash-merge, orchestrator.lock | [ ] | `task/T0.3` | Test vs local scratch repo: clone-if-empty vs fetch, worktree lifecycle, squash-merge produces 1 commit | Concurrency safety |
| T0.4 | PrepareSkillsActivity, classifyPiErr (4xx/5xx/504), stream timeout learning | [ ] | `task/T0.4` | Unit tests: all 3 error buckets against mocked pi HTTP client | Pi integration |
| T0.5 | Planner/Judge/Implementer activities, LLM client, prompt templates | [ ] | `task/T0.5` | Unit test: PromptSpec renders with system prompt + template override + raw template | LLM orchestration |
| T0.6 | TaskUnitWorkflow: retry loops (timeout/judge-fail split), lessons injection, escalation | [ ] | `task/T0.6` | Testsuite: pass-first-try, fail-then-pass-after-lesson, retries-exhausted, timeout-escalation | Task execution core |
| T0.7 | OrchestratorWorkflow: config state, signals, fan-out/fan-in, continue-as-new, 504 learning | [ ] | `task/T0.7` | Testsuite: fan-out/fan-in, squash-merge on complete, continue-as-new carries config, signals mutate config, 504 doubles StreamTimeout | Orchestration core |
| T0.8 | cmd/worker, cmd/starter, internal/config (env/vsource loading) | [ ] | `task/T0.8` | `go run ./cmd/worker` connects to temporal.riotpiao.com; `go run ./cmd/starter --dry-run` visible in Web UI | CLI integration |
| T0.9 | End-to-end: real temporal.riotpiao.com + disposable forgejo scratch repo, all 7 verification items | [ ] | `task/T0.9` | Clone bootstrap, full cycle, live signal updates, 5xx retry+exhaust, 504 stream-timeout learning, continue-as-new bounded, squash-merge result | System validation |
## Submission Criteria
All T0.1T0.9 marked `[x]` → submilestone complete.
At that point:
1. `git -C /workspace/Poimen/workflows checkout main && git pull`
2. `git merge --squash task/T0.1 task/T0.2 ... task/T0.9`
3. `git commit -m "T0: multi-agent orchestrator initial implementation"`
4. `git push origin main`
5. Delete all `task/T0.*` branches and worktrees
This merge is the first real dogfood of the system's own git workflow: squashing 9 subtask branches into main as a single milestone commit.
---
## Notes
- **Lessons file location:** `tasks/.orchestrator/lessons/<TaskID>.jsonl` (created on first failure, not committed until Planner's board commit)
- **Branch naming:** Strict `task/T0.x` format; Orchestrator expects this pattern
- **Dry-run vs real:** T0.8 tests with `--dry-run` (no real push); T0.9 removes flag (real remote operations)
- **Temporal Web UI:** Monitor at `http://temporal.riotpiao.com:8080` (adjust port/host as needed)
- **E2E fixture:** Disposable forgejo repo (deleted post-run); confirm it's not a production repo before starting T0.9