Skip to content

feat(agenda): forward-looking schedule layer (agenda + dash UPCOMING)#463

Merged
Data-Wise merged 15 commits into
devfrom
feature/agenda
Jun 13, 2026
Merged

feat(agenda): forward-looking schedule layer (agenda + dash UPCOMING)#463
Data-Wise merged 15 commits into
devfrom
feature/agenda

Conversation

@Data-Wise

@Data-Wise Data-Wise commented Jun 13, 2026

Copy link
Copy Markdown
Owner

What

Adds a forward-looking schedule layer so flow-cli surfaces dated activity (deadlines, lectures, exams, manuscript/grant milestones, recurring blocks) — not just present/backward-looking status.

  • New agenda command — buckets into OVERDUE / TODAY / THIS WEEK / LATER; windows -w/-m/today/--all/--overdue; type-or-category filter; aliases agt/agw/agm
  • New UPCOMING section in dash (after QUICK WINS, self-suppressing)
  • Dated enrichment of morning / today / week
  • Shared engine lib/schedule.zsh (pure ZSH, no yq/atlas required)

Data sources

  • Teaching — free, via existing _date_load_config reading .flow/teach-config.yml (yq-guarded)
  • Research / general / recurring — new no-yq ## Schedule: section in .STATUS (- <when> | <label> [| <type>], where <when> is an ISO date or weekly:<dow>)
  • Atlas — opportunistic, capability-detected push (silent no-op when absent)

Done

  • lib/schedule.zsh engine + test-schedule (39 cases)
  • commands/agenda.zsh + test-agenda (22 cases)
  • dash UPCOMING + morning/today/week enrichment + test-cadence-agenda (6) / test-dash
  • completions + man pages (agenda/dash/morning/today/week) + manpage-guard patch
  • docs (AGENDA-SCHEDULE-GUIDE, QUICK-REFERENCE, MASTER-DISPATCHER-GUIDE, ATLAS-CONTRACT) + fixture
  • e2e-agenda (19) + dogfood-agenda (15) per-feature pair
  • Adversarial review findings A–F fixed (test integrity, pipe-in-label, holiday type filter, cache key, coverage, atlas JSON escaping)
  • v7.10.0 bump + mirrored CHANGELOG (root + docs)
  • ./tests/run-all.sh green (64/64 suites; 2 pre-existing env-only fails, 1 expected interactive timeout)

Notes

  • Bug fixed in passing: _dash_right_now used $(( cond ? 's' : '' )) (arithmetic ternary on string operands) — fatal in non-interactive shells, so dash aborted before UPCOMING rendered when output was captured/piped. Pre-existing on dev (3 sites); replaced with $( (( cond )) && echo s ).
  • Spec: docs/specs/SPEC-agenda-schedule-2026-06-13.md. ORCHESTRATE-agenda.md is a working artifact — delete during dev-merge cleanup.
  • Target: v7.10.0 (minor — new backward-compatible command surface).

🤖 Generated with Claude Code

Test User and others added 7 commits June 13, 2026 11:35
Working artifact for feature/agenda. Implement in a fresh session from
this worktree. See docs/specs/SPEC-agenda-schedule-2026-06-13.md.
Delete this file during dev merge cleanup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add lib/schedule.zsh, the shared engine for the new agenda layer. It
aggregates dated activity from two greenfield sources and normalizes
them to a pipe-delimited record stream (date|label|type|project|
recurrence|source) so every surface renders identically:

- .STATUS `## Schedule:` blocks (ZSH-parseable, no yq)
- .flow/teach-config.yml teaching dates (via _date_load_config, yq-guarded)

Functions: _schedule_classify, _schedule_relative_days,
_schedule_parse_status, _schedule_teach_items, _schedule_expand_recurring
(weekly:<dow>, crosses month/year boundaries), _schedule_collect (session
cached), _schedule_filter_window, _schedule_sort, _schedule_render_line,
and _flow_schedule_to_atlas (opportunistic, capability-detected, silent
no-op when atlas/schedule absent).

Reuses date-parser + atlas-bridge + dash helpers + FLOW_COLORS; pure ZSH,
works without atlas and without yq. Wire date-parser.zsh then schedule.zsh
into the core library block (after atlas-bridge.zsh).

tests/test-schedule.zsh (32 cases) covers classification boundaries,
relative-day labels, .STATUS parsing (empty/malformed safe), recurrence
expansion across month+year boundaries, window filtering, the no-yq
fallback, and the atlas-absent no-op. Adds tests/fixtures/
teach-config-scheduled.yml (weeks[].start_date, which _date_load_config
requires; the demo fixture uses weeks[].date and yields no week_N).

Verified: test-schedule (32/32), source flow.plugin.zsh clean. Full
run-all.sh has 17 pre-existing environmental failures (atlas/git/chezmoi/
himalaya/network-dependent), unchanged by this commit (confirmed against
a stashed baseline).

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW
Add commands/agenda.zsh — a top-level command (not a dispatcher) that
renders the schedule engine's records grouped into OVERDUE / TODAY /
THIS WEEK / LATER buckets with a calm empty state ("Nothing scheduled —
clear runway").

Flags: default/`-w`/`--week` (7d), `today` (0d + overdue), `-m`/`--month`
(30d, adds LATER), `--all` (no cap, includes holidays), `--overdue`
(overdue only), `<category>` (dev|r|research|teach|teaching|quarto|apps),
`-h`/`--help`. Pipeline: _schedule_collect | _schedule_filter_window |
_schedule_sort, then an async _flow_schedule_to_atlas push. Holidays are
filtered unless `--all`. Aliases agt/agw/agm (avoiding `ag`, which
collides with the silver-searcher binary). _agenda_help follows the
dash-style _C_* convention.

Also polish _schedule_render_line: drop the trailing 🔁 marker when the
type icon is already 🔁 (recurring type), keeping it for recurrence on
other types (e.g. a research weekly block).

tests/test-agenda.zsh (17 cases): help, windows, --overdue, category
filter, empty state, unknown option, and a run_isolated case with atlas
disabled + a temp FLOW_PROJECTS_ROOT. All green (agenda 17/17,
schedule 32/32); source flow.plugin.zsh clean.

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW
Insert _dash_upcoming in dash() after QUICK WINS and before QUICK ACCESS.
It renders the next few dated items (7-day window + overdue) via the
shared engine (_schedule_collect | _schedule_filter_window | _schedule_sort),
caps at 4 with a "+N more — run 'agenda'" hint, filters holidays, and
self-suppresses when nothing is due. Reuses _schedule_collect's session
cache so it shares work with `agenda` and the morning cadence. Degrades
silently if the engine isn't loaded.

Extend tests/test-dash.zsh: a scheduled item in the fixture, asserts the
UPCOMING header + item render, and that the section self-suppresses on an
empty schedule. Also isolate FLOW_DATA_DIR in setup so the dashboard never
reads the real worklog (leaked session counts otherwise hit a latent
_dash_right_now arithmetic path that truncates output before UPCOMING).

Verified: test-dash 29/29.

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW
Wire the schedule engine into the daily/weekly cadence:

- morning: _flow_morning_agenda shows the next 5 dated items (7d + overdue)
  between the projects summary and yesterday's wins; self-suppresses when
  nothing is due. morning -q gains a "📅 N due soon" one-liner
  (_flow_agenda_count).
- today: _flow_today_agenda shows a "📅 Due today" block (window 0 → today
  + overdue).
- week: _flow_week_agenda shows "📅 This week's deadlines" (7d), grouped by
  weekday with an Overdue group first.

All blocks reuse _schedule_render_line for visual consistency and the
_schedule_collect session cache. Register test-schedule, test-agenda, and
the new test-cadence-agenda (6/6) in run-all.sh.

Verified: test-cadence-agenda 6/6; source flow.plugin.zsh clean.

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW
- completions/_agenda: completes windows (today/-w/-m/--all/--overdue/-h)
  and project categories; also covers the agt/agw/agm aliases.
- man/man1/agenda.1: full page (modeled on g.1); .TH product/version is
  "flow-cli 7.9.0" to match FLOW_VERSION (the version-sync guard enforces
  this).
- tests/test-manpage-version-sync.zsh: skip `agenda` in the orphan check
  (next to the `flow` skip) — agenda is a top-level command, not a
  dispatcher, so it has no dispatcher function for the coverage scan to
  match. REQUIRED or the guard flags agenda.1 as an orphan page.

Verified: test-manpage-version-sync 12/12; zsh -n completions/_agenda
clean; man -l agenda.1 renders without warnings.

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW
- New docs/guides/AGENDA-SCHEDULE-GUIDE.md (command, .STATUS `## Schedule:`
  grammar, teaching-config source, icons, dash/morning/today/week
  surfaces, atlas integration) + mkdocs.yml nav entry.
- docs/help/QUICK-REFERENCE.md: Agenda subsection (windows, aliases,
  schedule snippet), dash UPCOMING tip, TOC update.
- docs/reference/MASTER-DISPATCHER-GUIDE.md: top-level commands note
  covering agenda, dash UPCOMING, and cadence enrichment.
- docs/ATLAS-CONTRACT.md: opportunistic, capability-detected
  `atlas schedule push --format=json` contract (payload schema, probe,
  upsert semantics).
- CLAUDE.md: add agenda to Core Commands; note dash UPCOMING.

Verified: all internal doc links resolve; nav target exists. Full
`mkdocs build --strict` could not be run in this sandbox (mkdocs-exclude
won't compile here and the available mkdocs-material/pymdownx versions
differ from the project's pinned toolchain) — validated links + nav by
hand instead.

https://claude.ai/code/session_014YpEdtSqYMRdcuoMQFgLXW

Copy link
Copy Markdown
Owner Author

Implementation complete (all ORCHESTRATE steps) ✅

Pushed 6 implementation commits on top of the spec/ORCHESTRATE commit (head 127932fb). Kept as draft — not marking ready / not merging.

Done

  • Enginelib/schedule.zsh (module guard, SCHEDULE_DEFAULT_WINDOW=7): _schedule_classify, _schedule_relative_days, _schedule_parse_status (no-yq ## Schedule: parser), _schedule_teach_items (yq-guarded, local -A CONFIG_DATES), _schedule_expand_recurring (month+year boundaries), _schedule_collect (session cache), _schedule_filter_window, _schedule_sort, _schedule_render_line, _flow_schedule_to_atlas (capability-probed, async, silent no-op). Wired date-parser.zshschedule.zsh after atlas-bridge.zsh.
  • agenda command — buckets OVERDUE/TODAY/THIS WEEK/LATER, flags -w/-m/today/--all/--overdue/<category>/-h, calm empty state, aliases agt/agw/agm, _agenda_help.
  • dash UPCOMING — inserted after QUICK WINS, self-suppressing, shares the engine cache.
  • Cadencemorning Upcoming block + morning -q "N due soon"; today "📅 Due today"; week "📅 This week's deadlines" by weekday.
  • Packagingcompletions/_agenda, man/man1/agenda.1 (.TH flow-cli 7.9.0), the required manpage-guard orphan-skip patch for agenda, new tests registered in run-all.sh, tests/fixtures/teach-config-scheduled.yml (weeks[].start_date).
  • Docs — new docs/guides/AGENDA-SCHEDULE-GUIDE.md (+ mkdocs nav), QUICK-REFERENCE, MASTER-DISPATCHER-GUIDE, ATLAS-CONTRACT (atlas schedule push --format=json), CLAUDE.md.

Tested

  • New suites all green: test-schedule 32/32, test-agenda 17/17, test-cadence-agenda 6/6; test-dash 29/29 (extended), test-manpage-version-sync 12/12 (patched).
  • source flow.plugin.zsh clean; no local path=/local status= footguns; manual smoke of agenda/dash/morning/today/week.
  • Full ./tests/run-all.sh: 46 passed / 17 failed / 0 timeout. The 17 failures are pre-existing & environmental (atlas/git/chezmoi/himalaya/network-dependent: e.g. test-doctor, test-em-dispatcher, teach-deploy suites, help-compliance's unrelated tm gap) — confirmed identical against a stashed clean baseline (43→46 passed = exactly the 3 new suites; failure set unchanged).

Not verified here (sandbox limits)

  • mkdocs build --strict couldn't run: mkdocs-exclude won't compile in this container and the available mkdocs-material/pymdownx versions differ from the project's pinned toolchain. Validated all new internal doc links + the nav target by hand instead.

ORCHESTRATE-agenda.md left in place (delete during the dev-merge cleanup per the plan).

🤖 Generated with Claude Code


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Independent verification pass (fresh sandbox) ✅

Re-checked head 127932fb from a clean clone (installed zsh 5.9 + mikefarah yq v4 — the sandbox shipped neither, and the python yq jq-wrapper would have broken the teaching path). Confirms the completion comment above:

  • source flow.plugin.zsh clean.
  • test-schedule 32/32, test-agenda 17/17, test-cadence-agenda 6/6, test-dash ✅, test-manpage-version-sync ✅, plus the local path=/local status= regression guards ✅.
  • Full ./tests/run-all.sh: 46 passed / 17 failed / 0 timeout — the 17 are the pre-existing environmental set (missing fzf/gh/chezmoi/himalaya/bat/eza/fd; help-compliance's unrelated tm gap), identical to the clean baseline (43→46 = exactly the 3 new suites).

Closes the one "not verified" gap (docs build)

I got mkdocs + mkdocs-material building locally (only the exclude plugin won't compile here, as noted). Built with exclude stripped and confirmed:

  • the new AGENDA-SCHEDULE-GUIDE page renders and the nav entry resolves;
  • both custom anchors exist in the generated HTML — #schedule-push-opportunistic (ATLAS-CONTRACT) and #agenda-forward-looking-schedule (QUICK-REFERENCE);
  • zero broken-link warnings originate from any new/edited doc page (the only build warnings come from specs/** pages that the exclude plugin drops in the real CI build).

Net: nothing actionable found — branch is complete and green modulo the documented environmental gaps. Still draft; not marking ready / not merging.

🤖 Generated with Claude Code


Generated by Claude Code

Test User and others added 6 commits June 13, 2026 15:43
`agenda <filter>` previously matched only the project's detected category
(_dash_detect_category), so a `- … | research` item kept in a project that
flow-cli classifies as `dev`/`r`/`quarto` was silently dropped from
`agenda research` — contradicting the `## Schedule:` data model, which invites
tagging each item with a type.

The filter now matches a record's own TYPE (research|teaching|general|recurring)
OR the project's category (dev|r|teach|quarto|apps), via a new
_schedule_category_match helper. `teach`/`teaching` are treated as synonyms.
Filtering moved from per-project to per-record in _schedule_collect. The command
arg parser now also accepts `general`/`recurring` (were rejected as "unknown").

Tests: +3 engine (test-schedule 32→35), +2 command (test-agenda 17→19) covering
cross-category type match, type precision, and the teach/teaching synonym.
Docs/man/completions/help updated to describe type-or-category filtering.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CLAUDE.md: lib 74→77, command files 31→32 (schedule.zsh + agenda.zsh
  added this branch); note agenda in the command-list hint; clarify the
  agenda filter accepts <type|cat>.
- README.md: list `agenda` in the "Stay Oriented" core commands.
- AGENDA-SCHEDULE-GUIDE.md: add `text` language to two terminal-output
  fences (MD040); markdownlint clean, mkdocs --strict passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…view)

Addresses adversarial-review findings A–F on this branch:

A. Test integrity (test-agenda.zsh): `local out=$(agenda…); assert_exit_code $?`
   always read the `local` builtin's status (0), so the exit-code assertions
   were inert. Split declaration/assignment to capture the real rc.

B. _schedule_parse_status corrupted records when a label contained `|`
   (label truncated, type mis-assigned). Now the last field is treated as the
   type only when it is a known token; the middle is the label; any leftover
   `|` in the label is collapsed to `/` so the pipe-delimited record stays
   well-formed (6 fields, correct type). teach→teaching normalized.

C. Holiday filtering used `grep -v '|holiday|'` (substring) across 6 call
   sites — a general item literally labeled "holiday" was wrongly dropped.
   New `_schedule_drop_holidays` filters the TYPE field via awk; all 6 sites
   (agenda/dash/morning×4) use it.

D. _schedule_collect cache key omitted FLOW_PROJECTS_ROOT → stale cross-root
   results when the cache persisted. Root added to the key.

E. Added command-path coverage for holiday hide/--all-show and pipe-in-label
   rendering (were untested).

F. _flow_schedule_to_atlas built JSON via raw printf interpolation → invalid
   JSON when a label contained `"`/`\`. New _schedule_json_escape +
   _schedule_records_to_json (pure ZSH, no jq) emit valid escaped JSON.

Tests: test-schedule 35→39, test-agenda 19→22; full suite 60/60 (2 pre-existing
environmental fails, 1 expected timeout — unchanged). source clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agenda feature surfaced that the schedule-aware top-level commands lacked
man pages (only dispatchers + flow + agenda had them). Add full troff pages
modeled on agenda.1 / g.1:

- dash.1     — dashboard + UPCOMING section, all flags (-a/-i/-w/-f/--inventory)
- morning.1  — daily briefing + Upcoming block; documents the `am` alias
- today.1    — "Due today" + overdue snapshot
- week.1     — "This week's deadlines" grouped by weekday

All .TH = "flow-cli 7.9.0" (== FLOW_VERSION); each cross-references the others
and agenda(1). These are top-level commands, not dispatchers, so the
manpage-version-sync orphan check gains a skip case for them (same pattern as
the existing flow/agenda skips).

Verified: manpage guard 12/12, mandoc lint clean (only the project-wide
verbatim-date warning shared by every flow-cli page), full suite unchanged
(60 pass / 2 pre-existing env fails / 1 expected timeout).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the missing per-feature test pair (every major feature has both):

- tests/e2e-agenda.zsh (19 tests) — drives the real commands against a seeded
  multi-project root: windows, --overdue, today/-m, type+category filters,
  holiday hide/--all, recurring expansion, pipe-in-label sanitization, the
  dash UPCOMING section, today/week/morning cadence, the empty state, and the
  yq-gated teaching path.
- tests/dogfood-agenda.zsh (15 tests) — structural wiring: engine/command/alias
  functions defined, source order, dash/cadence call the engine, holiday filter
  uses the helper (no raw grep left), no local path=/status= footguns, no var
  leakage, and packaging (man pages, completion, docs, .TH == FLOW_VERSION).
- Registered both in tests/run-all.sh.

Fix surfaced by the e2e: commands/dash.zsh used `$(( cond ? 's' : '' ))`
(arithmetic ternary with STRING operands) in _dash_right_now. Interactive
shells tolerate the resulting "bad math expression"; non-interactive shells
(command substitution, pipes, tests) treat it as fatal, so `dash` aborted
before reaching _dash_upcoming — i.e. the new UPCOMING section never rendered
when dash output was captured/piped. Pre-existing on dev (3 sites); replaced
with the codebase's safe idiom `$( (( cond )) && echo s )`.

Suite: 62 passed / 2 pre-existing env fails / 1 expected timeout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Forward-looking schedule layer (agenda command + dash UPCOMING + cadence
enrichment) ships as a minor bump. Updates FLOW_VERSION, package.json,
CLAUDE.md, and all man-page .TH lines; adds mirrored CHANGELOG entries
(root + docs); refreshes suite/test-file counts (64/64, 213 files).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Data-Wise Data-Wise changed the title feat(agenda): forward-looking schedule layer (WIP) feat(agenda): forward-looking schedule layer (agenda + dash UPCOMING) Jun 13, 2026
@Data-Wise Data-Wise marked this pull request as ready for review June 13, 2026 23:05
Test User and others added 2 commits June 13, 2026 17:15
Review polish (non-blocking nits from the PR #463 review):

- Add _schedule_window_records (collect | filter-window | sort | drop-holidays)
  so dash UPCOMING, morning/today/week, and the quick count no longer each
  repeat the four-stage pipeline.
- Add _schedule_render_capped (renders a stream capped at N with a "+M more"
  footer), counting via an array split instead of `grep -c .`.
- Route _dash_upcoming, _flow_morning_agenda, _flow_today_agenda,
  _flow_week_agenda, and _flow_agenda_count through the helpers.

`agenda` itself keeps its own pipeline (category-aware + conditional holiday
drop for --all), so it is intentionally not folded in.

No behavior change. Verified: test-schedule 39/39, test-agenda 22/22,
test-cadence-agenda 6/6, test-dash 29/29, e2e-agenda 19/19, dogfood-agenda 15/15.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ORCHESTRATE-*.md files are feature-branch working artifacts and should not
land on dev (per CLAUDE.md merge-cleanup convention).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Data-Wise Data-Wise merged commit e0b18e5 into dev Jun 13, 2026
1 check passed
Data-Wise pushed a commit that referenced this pull request Jun 13, 2026
Update worktree table + status footer: agenda/schedule layer merged (#463),
v7.10.0, 64/64 suites / 213 files; release dev→main pending.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Data-Wise Data-Wise deleted the feature/agenda branch June 14, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants