Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .agents/scripts/commands/full-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,49 @@ result=$(verify_operation "terraform destroy" "$risk") # Returns: verified, con
| `VERIFY_TIMEOUT` | `30` | Seconds to wait for verifier response |
| `VERIFY_MODEL` | `haiku` | Model tier for verification (cheapest sufficient) |

### Step 1.7: Parse Lineage Context (t1408.3)

If the dispatch prompt contains a `TASK LINEAGE:` block (injected by the pulse or interactive dispatcher for subtasks), parse it at session start. This block tells you your place in a task hierarchy — what the parent task is, what sibling tasks exist, and what your specific scope is.

**Detection:**

```bash
# Check if the dispatch arguments contain lineage context
if echo "$ARGUMENTS" | grep -q "TASK LINEAGE:"; then
HAS_LINEAGE=true
fi
```
Comment on lines +418 to +427
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Accept the helper’s current marker or this parser won’t fire.

Line 424 only detects TASK LINEAGE:, but the current task-decompose-helper.sh format-lineage output uses PROJECT CONTEXT: and <-- (this task). A dispatcher following the documented helper path will never set HAS_LINEAGE, so the new lineage rules are skipped entirely. Please either parse both formats here or align the helper/docs to one canonical block shape.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/commands/full-loop.md around lines 418 - 427, The detection
only looks for "TASK LINEAGE:" so the helper's output ("PROJECT CONTEXT:" and
the marker "<-- (this task)") is never recognized; update the session-start
detection that examines ARGUMENTS and sets HAS_LINEAGE to accept both formats
(e.g., look for "TASK LINEAGE:" OR "PROJECT CONTEXT:" or the "<-- (this task)"
marker) or else standardize the helper output (task-decompose-helper.sh
format-lineage) to emit the documented "TASK LINEAGE:" block; modify the logic
that inspects ARGUMENTS and sets HAS_LINEAGE accordingly so downstream lineage
parsing runs for either format.


**Worker rules when lineage is present:**

1. **Scope boundary** — Only implement what's marked with `<-- THIS TASK`. If you find yourself implementing functionality described in a sibling task's description, stop and refocus.

2. **Stub dependencies** — If your task needs types, APIs, or interfaces that a sibling task will create, define minimal stubs (e.g., a TypeScript interface, a function signature with `TODO` body). Document these stubs in the PR body under a "Cross-task stubs" section so the sibling worker knows to replace them.

3. **No sibling work** — Do not implement features described in sibling task descriptions, even if they seem easy or closely related. Each sibling has its own worker, branch, and PR. Overlapping implementations cause merge conflicts.

4. **PR body lineage section** — When creating the PR, include a "Task Lineage" section:

```markdown
## Task Lineage

This task is part of a decomposed parent task:
- **Parent:** t1408 — Recursive task decomposition for dispatch
- **This task:** t1408.3 — Add lineage context to worker dispatch prompts
- **Siblings:** t1408.1 (classify/decompose helper), t1408.2 (dispatch integration), t1408.4 (batch strategies), t1408.5 (testing)

### Cross-task stubs
- None (this task is documentation-only)
```

5. **Blocked by sibling** — If you discover a hard dependency on a sibling task (not just a stub-able interface, but a fundamental prerequisite like "the database table doesn't exist yet"), exit cleanly:

```text
BLOCKED: This task (t1408.3) requires task-decompose-helper.sh from sibling t1408.1,
which has not been merged yet. Cannot test lineage formatting without the helper.
Partial work committed on branch feature/t1408.3-lineage-context.
```

### Step 2: Start Full Loop

**Supervisor dispatch** (headless mode - t174):
Expand Down
52 changes: 52 additions & 0 deletions .agents/scripts/commands/pulse.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,36 @@ sleep 2
- Route non-code tasks with `--agent`: SEO, Content, Marketing, Business, Research (see AGENTS.md "Agent Routing")
- **Bundle-aware agent routing (t1364.6):** Before dispatching, check if the target repo has a bundle with `agent_routing` overrides. Run `bundle-helper.sh get agent_routing <repo-path>` — if the task domain (code, seo, content, marketing) has a non-default agent, use `--agent <name>`. Example: a content-site bundle routes `marketing` tasks to the Marketing agent instead of Build+. Explicit `--agent` flags in the issue body always override bundle defaults.
- **Scope boundary (t1405, GH#2928):** ONLY dispatch workers for repos in the pre-fetched state (i.e., repos with `pulse: true` in repos.json). The `PULSE_SCOPE_REPOS` env var (set by `pulse-wrapper.sh`) contains the comma-separated list of in-scope repo slugs. Workers inherit this env var and use it to restrict code changes (branches, PRs) to scoped repos. Workers CAN still file issues on any repo (cross-repo self-improvement), but the pulse must NEVER dispatch a worker to implement a fix on a repo outside this scope — even if an issue exists there. Issues on non-pulse repos enter that repo's queue for their own maintainers to handle.
- **Lineage context for subtasks (t1408.3):** When dispatching a subtask (task ID contains a dot, e.g., `t1408.3`), include a lineage context block in the dispatch prompt. This tells the worker what the parent task is, what sibling tasks exist, and to focus only on its specific scope. See `tools/ai-assistants/headless-dispatch.md` "Lineage Context for Subtask Workers" for the full format and assembly instructions. Example dispatch with lineage:

```bash
# Subtask dispatch with lineage context
PARENT_ID="${TASK_ID%.*}"
PARENT_DESC=$(grep -E "^- \[.\] ${PARENT_ID} " TODO.md | head -1 \
| sed -E 's/^- \[.\] [^ ]+ //' | sed -E 's/ #[^ ]+//g' | cut -c1-120)
SIBLINGS=$(grep -E "^ - \[.\] ${PARENT_ID}\.[0-9]+" TODO.md \
| sed -E 's/^ - \[.\] ([^ ]+) (.*)/\1: \2/' | sed -E 's/ #[^ ]+//g')
Comment on lines +326 to +330
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Build lineage from the target repo, not the supervisor cwd.

This example runs in the pulse supervisor, which dispatches across many repos. Grepping bare TODO.md will read whichever directory the pulse happens to be in, so parent/sibling lineage can come back empty or from the wrong repo. Point the example at "$path/TODO.md" (or use git -C "$path" for the lookup) so the lineage block is assembled from the repo being dispatched.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/commands/pulse.md around lines 326 - 330, The grep/sed/cut
lines that compute PARENT_DESC and SIBLINGS currently read a bare TODO.md which
uses the supervisor CWD; update these commands to reference the target
repository path (e.g., "$path/TODO.md" or use git -C "$path" for lookups) so
PARENT_ID, PARENT_DESC and SIBLINGS are built from the dispatched repo’s TODO.md
rather than the supervisor’s working directory.


# Build lineage block (see headless-dispatch.md for full assembly)
# Or use: LINEAGE_BLOCK=$(task-decompose-helper.sh format-lineage "$TASK_ID")

opencode run --dir <path> --title "Issue #<number>: <title>" \
"/full-loop Implement issue #<number> (<url>) -- <brief description>

TASK LINEAGE:
0. [parent] ${PARENT_DESC} (${PARENT_ID})
1. <sibling 1 desc> (${PARENT_ID}.1)
2. <sibling 2 desc> (${PARENT_ID}.2) <-- THIS TASK
3. <sibling 3 desc> (${PARENT_ID}.3)

LINEAGE RULES:
- You are one of several agents working in parallel on sibling tasks under the same parent.
- Focus ONLY on your specific task (marked with '<-- THIS TASK').
- Do NOT duplicate work that sibling tasks would handle.
- If your task depends on interfaces or APIs from sibling tasks, define reasonable stubs.
- If blocked by a sibling task, exit with BLOCKED and specify which sibling." &
sleep 2
```

### Batch execution strategies for decomposed tasks (t1408.4)

Expand Down Expand Up @@ -506,6 +536,28 @@ opencode run --dir <repo_path> --title "Mission <mission_id> - <feature_title>"
sleep 2
```

- **Lineage context for mission features (t1408.3):** When dispatching mission features that are part of a milestone with multiple features, include lineage context so each worker knows what sibling features exist. The milestone is the "parent" and features are "siblings":

```bash
# Mission dispatch with lineage — milestone as parent, features as siblings
opencode run --dir <repo_path> --title "Mission <mission_id> - <feature_title>" \
"/full-loop Implement <task_id> -- <feature_description>. Mission context: <mission_goal>.

TASK LINEAGE:
0. [milestone] <milestone_name>: <milestone_description> (mission:<mission_id>)
1. <feature_1_title> (<feature_1_task_id>)
2. <feature_2_title> (<feature_2_task_id>) <-- THIS TASK
3. <feature_3_title> (<feature_3_task_id>)

LINEAGE RULES:
- You are one of several agents working in parallel on sibling features within the same milestone.
- Focus ONLY on your specific feature (marked with '<-- THIS TASK').
- Do NOT duplicate work that sibling features would handle.
- If your feature depends on interfaces or APIs from sibling features, define reasonable stubs.
- If blocked by a sibling feature, exit with BLOCKED and specify which sibling." &
sleep 2
```

- Update the feature status to `dispatched` in the mission state file
- Mission feature dispatches count against the same `MAX_WORKERS` limit as regular dispatches
- Respect the mission's `max_parallel_workers` setting if present (default: same as `MAX_WORKERS`)
Expand Down
127 changes: 102 additions & 25 deletions .agents/tools/ai-assistants/headless-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,43 +556,120 @@ The supervisor uses worker exit behavior to drive the self-improvement loop:

This framework reduces wasted retries by giving workers clear criteria for when to attempt vs when to bail. Over time, task descriptions improve because the supervisor learns which ambiguities cause exits.

## Lineage Context for Decomposed Tasks (t1408)
## Lineage Context for Subtask Workers

When dispatching a worker for a task that was decomposed from a parent task (i.e., it has parent and/or sibling tasks), include lineage context in the dispatch prompt. This prevents workers from duplicating sibling work or drifting off-scope.
When dispatching a worker for a task that has parent or sibling tasks (e.g., `t1408.3` under `t1408`), include a **lineage context block** in the dispatch prompt. This prevents scope drift and duplicate work across parallel workers.

**When to include lineage context:**
### When to Include Lineage Context

- The task has a parent task ID (e.g., `t1408.2` is a child of `t1408`)
- The task was created by `task-decompose-helper.sh decompose`
- Multiple workers are being dispatched for sibling tasks under the same parent
Include lineage context when ALL of these are true:

**How to generate lineage context:**
- The task ID contains a dot (e.g., `t1408.3`) — indicating it's a subtask
- The parent task and/or sibling tasks exist in TODO.md or the issue body
- Multiple sibling tasks may be dispatched in parallel

```bash
# Generate lineage block for worker prompt
task-decompose-helper.sh format-lineage \
--parent "Build a CRM with contacts, deals, and email" \
--children '[{"description": "Implement contact management"}, {"description": "Implement deal pipeline"}, {"description": "Implement email integration"}]' \
--current 1
```
Skip lineage context for top-level tasks (e.g., `t1408`) or tasks with no siblings.

### Lineage Block Format

**Output (injected into worker prompt):**
Insert the lineage block between the task description and any other dispatch context (mission context, etc.):

```text
PROJECT CONTEXT:
0. Build a CRM with contacts, deals, and email
1. Implement contact management
2. Implement deal pipeline <-- (this task)
3. Implement email integration
TASK LINEAGE:
0. [parent] Build a CRM with contacts, deals, and email (t1408)
1. Implement contact management module (t1408.1)
2. Implement deal pipeline module (t1408.2) <-- THIS TASK
3. Implement email integration module (t1408.3)

You are one of several agents working in parallel on sibling tasks under the same parent.
Do not duplicate work that sibling tasks would handle -- focus only on your specific task.
If this task depends on interfaces/types from sibling tasks, define reasonable stubs.
LINEAGE RULES:
- You are one of several agents working in parallel on sibling tasks under the same parent.
- Focus ONLY on your specific task (marked with "<-- THIS TASK").
- Do NOT duplicate work that sibling tasks would handle.
- If your task depends on interfaces, types, or APIs from sibling tasks, define reasonable stubs
and document them in the PR body so the sibling worker can replace them.
- If you discover your task is blocked by a sibling task that hasn't been completed yet,
exit with BLOCKED and specify which sibling task you need.
```

**Integration with dispatch:**
### Assembling Lineage Context

The dispatcher (pulse or interactive session) assembles lineage from TODO.md:

```bash
# Given a subtask ID like t1408.3, extract lineage from TODO.md
TASK_ID="t1408.3"
PARENT_ID="${TASK_ID%.*}" # t1408

# Get parent task description
PARENT_DESC=$(grep -E "^- \[.\] ${PARENT_ID} " TODO.md | head -1 \
| sed -E 's/^- \[.\] [^ ]+ //' | sed -E 's/ #[^ ]+//g' | cut -c1-120)

# Get all sibling tasks (indented under parent)
SIBLINGS=$(grep -E "^ - \[.\] ${PARENT_ID}\.[0-9]+" TODO.md \
| sed -E 's/^ - \[.\] ([^ ]+) (.*)/\1: \2/' | sed -E 's/ #[^ ]+//g' | cut -c1-120)

# Format lineage block
LINEAGE_BLOCK="TASK LINEAGE:
0. [parent] ${PARENT_DESC} (${PARENT_ID})"

INDEX=1
while IFS= read -r sibling; do
SIB_ID=$(echo "$sibling" | cut -d: -f1)
SIB_DESC=$(echo "$sibling" | cut -d: -f2- | sed 's/^ //')
if [[ "$SIB_ID" == "$TASK_ID" ]]; then
LINEAGE_BLOCK+="
${INDEX}. ${SIB_DESC} (${SIB_ID}) <-- THIS TASK"
else
LINEAGE_BLOCK+="
${INDEX}. ${SIB_DESC} (${SIB_ID})"
fi
INDEX=$((INDEX + 1))
done <<< "$SIBLINGS"

LINEAGE_BLOCK+="

LINEAGE RULES:
- You are one of several agents working in parallel on sibling tasks under the same parent.
- Focus ONLY on your specific task (marked with \"<-- THIS TASK\").
- Do NOT duplicate work that sibling tasks would handle.
- If your task depends on interfaces, types, or APIs from sibling tasks, define reasonable stubs.
- If blocked by a sibling task, exit with BLOCKED and specify which sibling."
```

### Dispatch Prompt Template with Lineage

```bash
# Standard dispatch (no lineage — top-level task)
opencode run --dir <path> --title "Issue #<number>: <title>" \
"/full-loop Implement issue #<number> (<url>) -- <brief description>" &

When the pulse or `/full-loop` dispatches a worker for a decomposed subtask, prepend the lineage block to the worker's prompt. The lineage context is generated by `task-decompose-helper.sh format-lineage` and costs zero API calls (pure formatting).
# Subtask dispatch (with lineage context)
opencode run --dir <path> --title "Issue #<number>: <title>" \
"/full-loop Implement issue #<number> (<url>) -- <brief description>

${LINEAGE_BLOCK}" &
```

### Worker Behavior with Lineage Context

Workers that receive lineage context should:

1. **Read the lineage block** at session start to understand their scope boundaries
2. **Check sibling task descriptions** before implementing — if a function or module is described in a sibling task, don't implement it
3. **Create stub interfaces** for cross-sibling dependencies (e.g., if task 2 needs a type defined by task 1, create a minimal stub type and note it in the PR)
4. **Reference lineage in PR body** — include a "Lineage" section listing parent and sibling tasks so reviewers understand the decomposition
5. **Exit with BLOCKED** if a hard dependency on a sibling task prevents progress (don't work around it with hacks)

### Integration with task-decompose-helper.sh

When `task-decompose-helper.sh` (t1408.1) is available, use its `format-lineage` subcommand instead of manual assembly:

```bash
# Preferred: use helper for consistent formatting
LINEAGE_BLOCK=$(task-decompose-helper.sh format-lineage "$TASK_ID")

# Fallback: manual assembly from TODO.md (see above)
```
Comment on lines +665 to +672
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Document the helper exactly as it exists today.

The “preferred” command here does not match the current helper API: task-decompose-helper.sh format-lineage "$TASK_ID" is unsupported, and the helper still emits PROJECT CONTEXT: rather than the TASK LINEAGE: block described above. As written, this path can’t produce the documented format. Please either keep the manual TODO.md assembly as the only supported path for now, or update this section after the helper accepts task-id-based lookup and emits the same block shape.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/tools/ai-assistants/headless-dispatch.md around lines 665 - 672, The
preferred command shown (`task-decompose-helper.sh format-lineage "$TASK_ID"`)
is incorrect for the current helper (it doesn't accept a task-id and emits
"PROJECT CONTEXT:" not "TASK LINEAGE:"), so revert this section to use the
manual TODO.md assembly as the only supported path for now (remove or replace
the "Preferred" snippet that references format-lineage) and add a short note
saying the helper will be documented here once it accepts task-id lookup and
emits the "TASK LINEAGE:" block; reference the helper script name
(task-decompose-helper.sh), the nonexistent subcommand (format-lineage), and the
manual TODO.md assembly in the doc to make locating the change easy.


## Pre-Dispatch Task Decomposition (t1408.2)

Expand Down
Loading