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
27 changes: 26 additions & 1 deletion skills/worklog/bin/_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ def parse_task_file(text: str) -> tuple[dict, str]:
return fm if isinstance(fm, dict) else {}, match.group(2)


def next_section(body: str) -> str:
"""Return the current top-level `## Next` section body.

Older checkpoint notes can contain historical `## Next` headings and
checkboxes. Tracker hydration should mirror only the durable current plan,
not every stale checklist ever written into the task body.
"""
lines = body.splitlines()
collected = []
in_next = False

for line in lines:
if re.match(r"^##\s+Next\b", line):
if in_next:
break
in_next = True
continue
if in_next and re.match(r"^##\s+", line):
break
if in_next:
collected.append(line)

return "\n".join(collected)


def parse_work_items(body: str) -> list[dict]:
"""Parse `- [ ]` / `- [x]` checkboxes, folding soft-wrapped continuation
lines into the same bullet. A continuation line is indented further than
Expand All @@ -42,7 +67,7 @@ def parse_work_items(body: str) -> list[dict]:
current = None
bullet_re = re.compile(r"^(\s*)-\s*\[([ xX])\]\s+(.+?)\s*$")
new_block_re = re.compile(r"^\s*(?:[-*#]|\d+\.)\s")
for line in body.splitlines():
for line in next_section(body).splitlines():
m = bullet_re.match(line)
if m:
current = {
Expand Down
16 changes: 14 additions & 2 deletions skills/worklog/bin/context.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,20 @@ LDAP="$(resolve_ldap)"
FILE="people/$LDAP/active/$SLUG.md"
[[ -f "$FILE" ]] || FILE="people/$LDAP/archive/$SLUG.md"
if [[ ! -f "$FILE" ]]; then
echo "context: $SLUG not found under people/$LDAP/{active,archive}/" >&2
exit 1
matches=()
while IFS= read -r match; do
matches+=("$match")
done < <(find people -path "*/active/$SLUG.md" -o -path "*/archive/$SLUG.md" | sort)
if [[ ${#matches[@]} -eq 1 ]]; then
FILE="${matches[0]}"
elif [[ ${#matches[@]} -gt 1 ]]; then
echo "context: $SLUG is ambiguous across namespaces:" >&2
printf ' %s\n' "${matches[@]}" >&2
exit 1
else
echo "context: $SLUG not found under people/*/{active,archive}/" >&2
exit 1
fi
fi

# Commit history for this slug (follows renames via Worklog-Previous-Slug).
Expand Down
1 change: 0 additions & 1 deletion skills/worklog/bin/okf.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ def cmd_doctor(args: argparse.Namespace) -> int:
if local_noise:
warnings.append(f"local/generated files are visible to git status: {', '.join(local_noise[:5])}")

dry_args = argparse.Namespace(repo=str(root), apply=False, check=False)
pending: list[str] = []
for path in _tracked_markdown(root):
updated, did_change = sync_source_text(root, path, _read(path))
Expand Down
85 changes: 85 additions & 0 deletions skills/worklog/tests/context/test_context.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
set -euo pipefail

WORKLOG_BIN="${WORKLOG_BIN:-$(cd "$(dirname "$0")/../../bin" && pwd)}"
SCRATCH_ROOT="$(mktemp -d -t worklog-context-test-XXXXXX)"
SCRATCH="$SCRATCH_ROOT/repo"
export TMPDIR="$SCRATCH_ROOT/tmp"
mkdir -p "$TMPDIR"
trap 'rm -rf "$SCRATCH_ROOT"' EXIT

git init -q "$SCRATCH"
cd "$SCRATCH"
git config user.email "tester@example.com"
git config user.name "Tester"
export WORKLOG_REPO="$SCRATCH"
export WORKLOG_LDAP="tester"

mkdir -p people/tester/active people/peer/active

cat > people/tester/active/current-next.md <<'EOF'
---
slug: current-next
kind: impl
status: in-progress
project: context-test
last_updated: 2026-06-29
next_action: "Use only the current Next section"
repos: [context-test]
---

## Context

This task has a historical checklist that should not hydrate the tracker.

## Next

- [ ] Current item one
- [ ] Current item two

## Notes from older session

## Next

- [ ] Stale item from old notes
EOF

cat > people/peer/active/peer-only.md <<'EOF'
---
slug: peer-only
kind: impl
status: in-progress
project: context-test
last_updated: 2026-06-29
next_action: "Read-only peer lookup"
repos: [context-test]
---

## Context

Peer-owned task used to prove unique read-only slug lookup.

## Next

- [ ] Peer item
EOF

git add people/
git commit -q -m "context-test: seed tasks" --no-verify

json="$(WORKLOG_LDAP=tester "$WORKLOG_BIN/context.sh" current-next --format=json)"
CONTEXT_JSON="$json" python3 - <<'PY'
import json
import os
import sys

data = json.loads(os.environ["CONTEXT_JSON"])
items = [item["text"] for item in data["work_items"] if item["status"] == "open"]
assert items == ["Current item one", "Current item two"], items
PY

out="$(WORKLOG_LDAP=tester "$WORKLOG_BIN/context.sh" peer-only --for=compact)"
printf '%s\n' "$out" | grep -q '^slug: peer-only$'
printf '%s\n' "$out" | grep -q 'Read-only peer lookup'

echo "ok: context current-next hydration and unique peer lookup"
6 changes: 6 additions & 0 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,12 @@ test_worklog_skill() {
fail "worklog-manager poll fixture"
fi

if bash "$skill/tests/context/test_context.sh" >/dev/null 2>&1; then
ok "context current Next + unique slug fixture"
else
fail "context current Next + unique slug fixture"
fi

rm -rf "$(dirname "$vault")"
}

Expand Down
Loading