Skip to content
Closed
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
40 changes: 21 additions & 19 deletions .claude/hooks/issues-surface.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,66 +26,68 @@ source_val="$(printf '%s' "$payload" \
| head -n1 | sed -E 's/.*"([^"]*)"$/\1/')"

# --- parse the "Open items" table only ---------------------------------------
# Emit "PRI<TAB>ID<TAB>TYPE<TAB>SUMMARY" per open row. Scoped between the
# Emit ordered universal-ledger fields per active row. Scoped between the
# "## Open items" heading and the next "## " heading so the Resolved/archive
# table (different columns) is never counted.
# and superseded historical tables are never counted.
rows="$(awk '
/^## Open items/ { inopen=1; next }
/^## / { if (inopen) inopen=0 }
inopen && /^\| #[0-9]/ {
n=split($0, c, "|")
id=c[2]; pri=c[3]; typ=c[4]; sum=c[5]
id=c[2]; pri=c[3]; typ=c[4]; sum=c[5]; order=c[9]; class=c[10]; when=c[12]; estimate=c[13]
Comment on lines 36 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Parse escaped table pipes before indexing columns

When any pre-Order cell contains a valid escaped pipe (\|), as the changed issues skill explicitly permits, split($0, c, "|") treats it as another delimiter and shifts every later index. A synthetic row with a shell pipeline in Detail made the hook print 2026-07-28 as Order, 1 as classification, Agent as When, and Now as Estimate, so the startup context can misorder and misrepresent active work; parse Markdown escapes correctly or use a delimiter-aware reader before selecting these columns.

AGENTS.md reference: AGENTS.md:L466-L468

Useful? React with 👍 / 👎.

gsub(/^[ \t]+|[ \t]+$/, "", id)
gsub(/^[ \t]+|[ \t]+$/, "", pri)
gsub(/^[ \t]+|[ \t]+$/, "", typ)
gsub(/^[ \t]+|[ \t]+$/, "", sum)
printf "%s\t%s\t%s\t%s\n", pri, id, typ, sum
gsub(/^[ \t]+|[ \t]+$/, "", order)
gsub(/^[ \t]+|[ \t]+$/, "", class)
gsub(/^[ \t]+|[ \t]+$/, "", when)
gsub(/^[ \t]+|[ \t]+$/, "", estimate)
printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", order, pri, id, typ, sum, class, when, estimate
}
' "$ledger" 2>/dev/null || true)"
' "$ledger" 2>/dev/null | sort -n -k1,1 || true)"

total="$(printf '%s' "$rows" | grep -c . || true)"
if [ "${total:-0}" -eq 0 ]; then
echo "[issues] Outstanding-work memory (docs/outstanding-issues.md): no open items. Record one with /issues add …"
exit 0
fi

group() { printf '%s\n' "$rows" | awk -F'\t' -v p="$1" '$1==p'; }
group() { printf '%s\n' "$rows" | awk -F'\t' -v p="$1" '$2==p'; }
count() { printf '%s' "$1" | grep -c . || true; }
p1="$(group P1)"; p2="$(group P2)"; p3="$(group P3)"
c1="$(count "$p1")"; c2="$(count "$p2")"; c3="$(count "$p3")"

echo "[issues] Outstanding-work memory — ${total} open (${c1}×P1, ${c2}×P2, ${c3}×P3). Source of truth: docs/outstanding-issues.md · read the full list back with /issues."
echo "[issues] Universal task ledger — ${total} recommended open (${c1}×P1, ${c2}×P2, ${c3}×P3). Source of truth: docs/outstanding-issues.md · read the full ordered list with /issues."

print_group() { # $1=rows $2=max-to-list
local data="$1" limit="$2" shown=0 more=0 pri id typ sum
print_ordered() { # $1=rows $2=max-to-list
local data="$1" limit="$2" shown=0 more=0 order pri id typ sum class when estimate
[ -z "$data" ] && return 0
while IFS=$'\t' read -r pri id typ sum; do
[ -z "$pri" ] && continue
while IFS=$'\t' read -r order pri id typ sum class when estimate; do
[ -z "$order" ] && continue
if [ "$shown" -lt "$limit" ]; then
echo " ${pri} ${id} ${typ} — ${sum}"
echo " ${order}. ${pri} ${id} ${typ} [${class}] — ${sum}; when: ${when}; estimate: ${estimate}"
shown=$((shown + 1))
else
more=$((more + 1))
fi
done <<EOF
$data
EOF
[ "$more" -gt 0 ] && echo " … +${more} more at this priority (see /issues)"
[ "$more" -gt 0 ] && echo " … +${more} more in recommended order (see /issues)"
return 0
}

# P1 = do-next, list all. P2 = should-do, list up to 8. P3 = collapse to a count.
[ "$c1" -gt 0 ] && print_group "$p1" 999
[ "$c2" -gt 0 ] && print_group "$p2" 8
[ "$c3" -gt 0 ] && echo " ${c3} × P3 (nice-to-have / revisit-when) — see /issues"
# Keep startup context compact while preserving the universal order across priorities/states.
print_ordered "$rows" 12

# --- capture reminder ---------------------------------------------------------
case "$source_val" in
compact | resume | clear)
echo "[issues] Context was just reset (${source_val}). Before this session wraps up, run /issues capture to record any new follow-ups, deferrals, or risks that surfaced so they aren't lost from memory."
echo "[issues] Context was just reset (${source_val}). Before this session wraps up, use /issues capture to reconcile only verified, recommended follow-ups into the universal ledger."
;;
*)
echo "[issues] When the work in this session wraps up, offer to run /issues capture for any new follow-ups before the context is lost."
echo "[issues] When this work wraps up, offer /issues capture for verified recommended follow-ups; do not preserve stale or speculative work."
;;
esac
exit 0
59 changes: 29 additions & 30 deletions .claude/skills/issues/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
---
name: issues
description: Track and recall all outstanding tasks, recommendations, and issues for this repo as durable cross-session memory. Use when the user types "/issues" (state the open items back), or asks to add/close/update/capture an outstanding task, recommendation, or issue. The memory lives in docs/outstanding-issues.md; a plain "/issues" is read-only.
description: Read and maintain the repository's single universal, recommended-only task ledger. Use when the user types "/issues" or asks to add, close, update, capture or prioritise repository work. The ledger lives in docs/outstanding-issues.md; a plain "/issues" is read-only.
---

# issues — the outstanding-work memory
# issues — the universal recommended-work ledger

`docs/outstanding-issues.md` is the durable, cross-session memory of everything still outstanding:
open **tasks**, **recommendations** not yet acted on, and **issues** not yet resolved. Chat context
resets; that file does not. This skill reads it back and keeps it current.
`docs/outstanding-issues.md` is the only active repository task ledger. Its **Open items** table contains
only evidence-supported work still worth doing, with recommended order, priority, classification,
executor capability, timing, estimate, dependencies/approvals, success criteria, verification and a
stopping condition. Other backlog/runbook documents are supporting evidence, not parallel queues.

**The ledger is the source of truth, not chat memory.** Never answer `/issues` from conversation
recall — always read the file first, so the answer is correct even in a fresh session.
Expand All @@ -20,9 +21,9 @@ recall — always read the file first, so the answer is correct even in a fresh
## Default: `/issues` (read-only)

1. Read `docs/outstanding-issues.md`.
2. State the **open items** back, grouped by priority (P1 → P3), each as
`#ID · type · summary — next action (source)`.
3. End with a one-line count, e.g. `5 open: 0×P1, 3×P2, 2×P3 · 0 resolved this session`.
2. State the **open items** back by numeric **Order**, each as
`Order · #ID · Pri · classification · summary — next action; when; estimate`.
3. End with a one-line count by classification and priority.
4. Do **not** mutate the file or commit on a plain read.

If a filter is given, narrow step 2: `/issues P1` (by priority), `/issues issues` / `/issues recs`
Expand All @@ -32,41 +33,39 @@ If a filter is given, narrow step 2: `/issues P1` (by priority), `/issues issues

Parse the intent from natural language too — the exact syntax is a convenience, not a requirement.

- **`/issues add <text>`** — append a row to **Open items**. Infer `Pri`/`Type` from the text
(ask only if genuinely ambiguous; default `P2`/`task`). Allocate the ID from the
`<!-- issues:next-id=NNN -->` marker, then bump that marker. Fill `Source` with
`session <today>` unless the user names one; `Added` is today's date.
- **`/issues add <text>`** — verify that the candidate is current, evidence-supported, deduplicated
and worth its cost/risk before adding it. Append a fully populated **Open items** row, allocate the
ID from `<!-- issues:next-id=NNN -->`, bump the marker, and place it at the smallest sensible
**Order** while renumbering later rows. Do not add speculative, completed, stale, duplicate,
superseded or no-longer-recommended work.
- **`/issues done <id> [outcome]`** — move that row from **Open items** to **Resolved / archive**
with today's date and a one-line outcome. Archive, never delete.
- **`/issues update <id> <text>`** — edit an open row's summary or next action in place.
- **`/issues capture`** — scan the current session for recommendations, follow-ups, deferrals, and
unfixed problems that surfaced but were not recorded. Propose them as a numbered list and add the
confirmed ones (dedupe against existing rows first — do not re-add something already tracked).
- **`/issues capture`** — scan the current session and repository evidence for genuinely retained
work. Reclassify or omit completed, stale, duplicate, superseded, speculative and uneconomic claims;
add only confirmed recommended items after deduplication.

## Capture discipline (proactive memory)

When a task in _any_ session ends with unresolved follow-ups — a deferred fix, a "revisit when X"
recommendation, a known risk, a TODO you had to leave — offer to record them here before the context
is lost. That is what makes this a memory rather than a static list. Prefer one crisp row over a
paragraph; put the smallest next action in **Detail / next action**.
When a task ends with a supported follow-up, offer to reconcile it here before context is lost. Do not
capture every suggestion: verify current source evidence, impact, existing safeguards, cost, risk,
dependencies and provider requirements first. Prefer the smallest actionable outcome.

## Writing rules

- Keep the table format and column order exactly as in `docs/outstanding-issues.md`. One row per item.
- IDs are monotonic and never reused — always allocate from the `issues:next-id` marker and bump it.
- Keep **Order** contiguous and unique. Skip blocked rows during execution; do not reorder them merely
because a dependency is temporarily unavailable.
- Use exactly one allowed **Final classification** from the ledger conventions.
- Fill every retained row's next action, executor, when, estimate, dependencies/approvals, success
criteria, local/hosted verification and stopping condition.
- Escape `|` inside cell text (write `\|`) so the markdown table stays intact.
- Respect the repo's RAG/clinical/privacy flagging rules if an item _itself_ touches a protected
surface — recording it here is fine, but acting on it later still needs the usual gate.

## Persist the memory (commit)
## Persist the ledger

After any mutation, stage and commit **only** `docs/outstanding-issues.md` so the memory survives the
ephemeral container and other worktrees:

```
git add docs/outstanding-issues.md
git commit -m "issues: <what changed>"
```

Do not stage or commit anything else, and do not push unless the user asks (or you are already in a
handoff/upload flow). A plain read-only `/issues` commits nothing.
Edit the ledger when requested. A ledger mutation does not authorize a commit, push or pull request;
follow the repository Git instructions and the user's explicit publishing scope. A plain `/issues`
mutates nothing.
35 changes: 18 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,23 +448,24 @@ Run the matching planner command in `docs/productivity-workflows.md` without sid

<!-- END:repo-productivity-skills -->

## Outstanding-work memory (`/issues`)

`docs/outstanding-issues.md` is the durable, cross-session memory of every outstanding **task**,
**recommendation**, and **issue** for this repo. Chat context resets between sessions; that file does
not, so anything worth remembering after a session ends belongs there.

- When the user types `/issues`, invoke the `issues` skill (`.claude/skills/issues/SKILL.md`): read
`docs/outstanding-issues.md` and state the open items back, grouped by priority. A plain `/issues`
is read-only — it mutates and commits nothing.
- `/issues add|done|update|capture …` mutate the ledger; each mutation commits **only**
`docs/outstanding-issues.md` (no push unless the user asks or you are already handing off).
- Proactively offer to `capture` unresolved follow-ups, deferrals, and known risks into the ledger
before a session's context is lost — that is what keeps it a memory rather than a stale list.
- A `SessionStart` hook (`.claude/hooks/issues-surface.sh`, wired in `.claude/settings.json`)
auto-surfaces the open items into context at the start of every session and, on a context reset
(`compact`/`resume`/`clear`), nudges a `/issues capture`. It is read-only — it never writes the
ledger. `/issues` is still the way to read the full list or mutate it.
## Universal repository task ledger (`/issues`)

`docs/outstanding-issues.md` is the single durable, cross-session ledger for all agents and
worktrees. Its ordered **Open items** table contains only current, evidence-supported work still
worth doing, with priority, classification, executor capability, timing, effort, dependencies,
approvals, success criteria, verification and stopping conditions. Other backlog and runbook files
are supporting evidence, not competing queues.

- Before starting or recommending repository work, read `docs/outstanding-issues.md` and revalidate
the relevant row against current `main`.
- When the user types `/issues`, invoke the `issues` skill (`.claude/skills/issues/SKILL.md`) and
state active rows in numeric **Order**. A plain `/issues` is read-only.
- `/issues add|done|update|capture …` may mutate the ledger only after removing completed, stale,
duplicate, superseded, speculative or no-longer-recommended claims. A ledger mutation does not
itself authorise a commit, push, pull request, provider call, deployment or production change.
- The read-only `SessionStart` hook (`.claude/hooks/issues-surface.sh`, wired in
`.claude/settings.json`) surfaces the ordered active work and prompts evidence-based capture after
context resets.

## Codex GitHub review behavior

Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ npm run docs:check-links

## Plans and workstreams (living)

- [maturity-backlog-workorders.md](maturity-backlog-workorders.md) — actionable work orders tracking the repository-maturity audit backlog
- [outstanding-issues.md](outstanding-issues.md) — single universal task ledger and recommended execution order
- [maturity-backlog-workorders.md](maturity-backlog-workorders.md) — historical maturity workorders; only entries promoted to the universal ledger are active tasks
- [framework-dependency-modernization-checklist.md](framework-dependency-modernization-checklist.md) — ordered Next.js 16, runtime, dependency, Turbopack, and verification migration program
- [search-rag-master-plan.md](search-rag-master-plan.md) / [search-rag-master-context.md](search-rag-master-context.md) — search/RAG roadmap and shared context
- [rag-hybrid-findings-and-todo.md](rag-hybrid-findings-and-todo.md) — hybrid retrieval findings backlog
Expand Down
Loading
Loading