Skip to content

feedback(session-plugin): session-survey TASKWARRIOR section is project-scoped, so portfolio-wide sessions report OPEN_TASKS=0 #2232

Description

@laurigates

Skill

session-plugin/scripts/session-survey.sh — TASKWARRIOR section (and, downstream, session-end's Taskwarrior-sync qualify gate)

Category

Enhancement

Description

The survey's taskwarrior query is scoped to the detected project:

# scripts/session-survey.sh:135
project_tasks_json=$("$task_bin" project:"$project" '(status:pending or +ACTIVE)' export 2>/dev/null || echo "[]")

$project comes from DETECTION=cwd-repo-basename. In a portfolio checkout that name is the container repo, not any project a task would plausibly be filed under — and a session whose work spanned many sibling repos files its tasks under those repos' project slugs. Result: OPEN_TASKS=0, so session-end's Step 2 gate (TASK_AVAILABLE=true AND OPEN_TASKS >= 1) never fires and the Taskwarrior-sync pass is silently skipped in exactly the sessions that created the most tasks.

This is the same shape as #1915 (PRS section reported PR_COUNT=0 alongside 7 open session-authored PRs, because detection was keyed to local branches rather than the remote): a survey section keyed to a local proxy for scope, reporting a confident zero.

Evidence

Session 8aa0ba6f-1ef7-4b24-94fd-56932c42d7e6 (2026-07-29/30), an ubuntu-slim runner migration spanning 25 repos under ~/repos/laurigates. session-survey.sh --with-commits --with-blueprint emitted:

=== PROJECT ===
PROJECT=repos
DETECTION=cwd-repo-basename
PROJECT_DIR=/Users/lgates/repos/laurigates
=== TASKWARRIOR ===
TASK_AVAILABLE=true
OPEN_TASKS=0
ACTIVE_TASKS=0

The session had created 5 tasks and closed 1, all under other projects:

28a8fea5  portfolio-ci  Verify ubuntu-slim works with anthropics/claude-code-action…
8854e95c  portfolio-ci  Run the ubuntu-slim runner evaluation on laurigates/dotfiles…
2731b0b2  gooho         gooho claude.yml: last 20 runs are all startup_failure…
b1c98b6c  kicad-mcp     kicad-mcp release-please.yml fails with "Bad credentials"…

task export | jq '[.[]|select(.status=="pending" and .project=="repos")]|length'0. There is no project named repos; the top pending projects are comfyui-nodes (39), skullcaps-native (29), mcu-tinkering-lab (25), dotfiles (18), claude-plugins (14). So the scoped query cannot match anything from a ~/repos-level session, and the zero is structural rather than incidental.

Nothing was actually lost here — I noticed the digest disagreed with tasks I had just created and checked the queue by hand — but the gate's whole purpose is to catch what the operator doesn't remember.

Suggested Action

Two options, roughly in preference order:

  1. Widen the query when the detected project is a container/no-match, and report both counts so the gate can use the right one:
    project_tasks_json=$("$task_bin" project:"$project" '(status:pending or +ACTIVE)' export 2>/dev/null || echo "[]")
    if [ "$(printf '%s' "$project_tasks_json" | jq 'length')" -eq 0 ]; then
      # fall back to session-recent tasks across all projects
      project_tasks_json=$("$task_bin" '(status:pending or +ACTIVE)' export 2>/dev/null || echo "[]")
      echo "TASK_SCOPE=all-projects-fallback"
    fi
  2. Emit an additional RECENT_TASKS_* block scoped by entry/modified within the session window rather than by project, and gate Taskwarrior-sync on OPEN_TASKS + RECENT_TASKS >= 1. This also covers the inverse case (a single-repo session that filed a task under a different slug).

Either way, surfacing TASK_SCOPE= in the digest would make the narrowing visible instead of indistinguishable from an empty queue — the same fix-shape as #1915's "base it on the remote, not local branches".

🤖 Generated with Claude Code

https://claude.ai/code/session_01UuZtyXzArr3RU2APRD6Q31

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions