← Cycles
Design · c111

Cycles by Week

activeweek detail promoted to /cycles/weeks 2026-10-05 — Phase 3 backfill, Phase 4 digest rewire, Phase 5 close nextcreated 2026-10-05· last activity 2026-11-03· mode: assemblage: the dates, commits, captures, releases and deploys are all on disk already; the week is the frame that connects them

A weekly view of the cycle atlas (started · still open · closed per week) beside the existing numerical view, plus a week details page designed as a `_meta` mock

Why

/cycles answers "what cycles exist" in numerical order, project by project. It can't answer "what happened the week of Sep 28": which cycles began, which ran through it, which closed, and what shipped. Cycles now overlap heavily (c99–c110 ran inside two weeks across design, layer and qdash), so the number order no longer tells the story in time.

Objective

  1. /cycles gets a Number ⇄ Week view switch. Number stays the default and is unchanged. Week lists each week, newest first, with three lists: Started, Still open, Closed.
  2. A week details page designed as a _meta mock (/pages/_meta/cycles-week-detail) on live data. It shows the three cycle lists plus record excerpts, commits per repo, captures, and layer releases & deploys.
  3. Missing start and close dates are filled: git fallback now (marked inferred), and the records backfilled as a follow-up.

Done = the week view is live on /cycles and the detail mock is reviewed (it gets promoted to /cycles/weeks/<week> once approved).

Scope

  • Data: server/data/cycles/buildCycles.ts + parseCycleMd.ts (closed date, date source), new server/data/cycles/weeks.ts, server/api/cycles/weeks/ (index + [week]).
  • Overview: app/pages/cycles/index.vue (view switch + week view), components under app/components/cycles/.
  • Detail mock: app/pages/pages/_meta/cycles-week-detail.vue + app/data/page-registry.ts entry.
  • Feed: server/data/cycles/window.ts (gatherWindow(from, to), shared by the week API and the digest), scripts/window-feed.mts (CLI over it).
  • Digest: .claude/skills/partner-digest/SKILL.md Step 2.
  • Records backfill: cycles/*/CYCLE.md, cycles/HISTORY.md (design; sister repos are listed only, not written).
  • Plan: plan.md

Key Changes

kick-off (2026-10-05): initial prompt plus four clarifying answers recorded above; plan written. A second round adopted the three suggested patterns (digest rewire, stale-open signal, evolution links) with their rulings; plan updated (shared window feed, digest rewire as Phase 4).

Phase 0–1 built (2026-10-05): dates, the shared window feed, and the Week view on /cycles.

  • Timeline (server/data/cycles/timeline.ts): every atlas cycle gets started / closed with a record | git source. Starts come from the record for 149 cycles and from git for 51 (first touch of the cycle dir). Closes come from the record for 78 and from git for 42 (the commit that added the cycle to HISTORY.md, else the dir's last touch). Only qpixel c3 has no date. Unindexed cycles (in neither CYCLES.md nor HISTORY.md) count as closed at their inferred date, so they don't sit in Still open forever. One git pass per repo, cached 60 s. Active weeks (for quiet) = a dated Key Changes entry, a commit touching cycles/cN.*, or a commit naming cN in its subject. Commits in qcontrol, the layer and qtap name design's cycles.
  • Weeks (weeks.ts): Monday-start weeks. bucketWindow(from, to) returns Started / Still open (carried) / Closed. Carried rows carry openWeeks, quietWeeks and stale (3+ quiet weeks, parked exempt), ordered most-recently-moved first, then parked, then stale.
  • Window feed (window.ts gatherWindow): cycles, dated record entries, commits per repo (sha, PR number), layer tags, deploys, captures with evolution links. GET /api/cycles/weeks (dictionary + per-week refs, 167 KB) and /api/cycles/weeks/<monday> (400 for anything else). The CLI npx tsx scripts/window-feed.mts --from … [--to …] [--compact] runs it in about 1.2 s without a dev server. Deploys come from the local deploy reflog, because the branch is one force-pushed commit (c49). The reflog starts 2026-09-27 and is local-only; the feed says so in notes when a window predates it (LATER: have deploy.sh append to a deploys log).
  • Week view: a UxTabGroup Number | Week on /cycles (?view=week). Number stays the default and is unchanged (8 project sections, jump pills). The week data is fetched during SSR, so the static build carries it. CyclesWeekView (project UxFilterGroup, 12 weeks a page, the order toggle applies) → CyclesWeekBand: label, range, and an activity counts line. The counts are atlas-wide and not narrowed by the filter, and a tooltip says so. Below them are three columns; a week with nothing started, closed or touched for the selected projects folds to a "quiet week" line. CyclesWeekRow meta: start or close date (≈ when inferred), carried "6 wks · quiet 2" in amber when stale, "parked". An evo link goes to the subject's evolution page when the cycle produced subject-keyed captures that week; with several subjects it goes to /cycles/evolution for now, and Phase 2 retargets it to the week detail's captures. "Gone quiet N" folds the stale ones per week.
  • Data, week of Sep 28: 11 started (c100–c110), 74 carried (57 gone quiet), 8 closed (c49, c66, c102–c104, c106, c108, c109); 245 commits, 101 record entries, 223 captures, 9 layer releases, 23 deploys. The long gone-quiet list is real: design's CYCLES.md still lists c41/c42/c44/c51/c59… ("flagged in c69 sweep") and the sister repos keep old cycles under ## Active. These are exactly the rulings the stale signal exists to surface.
  • Checked in the pane: Number ⇄ Week round-trip and the URL; the filter (Design off → design rows gone, Sep 28 folds to a quiet week); Gone quiet expands; evolution links resolve (200); no console errors; at 375 px one 343 px column with no overflow. The plain design launch config's watcher missed server and template edits, so this run uses design-polling. Committed design c222be4a4 (not pushed, not deployed).

Phase 2 built (2026-10-05): the week detail mock, /pages/_meta/cycles-week-detail/<monday>. The week is in the path because static builds prerender paths, not queries, and the prev / next links let the crawler reach every week. No week = the last full week. Registry entry under the new c111-cycles-by-week collapse; /pages/_meta gets a c111 section.

  • Top to bottom: week nav (← prev · range · next → · All weeks) → verdict + stats band ("11 started, 8 closed, 17 carried live." over a busiest-record / gone-quiet / layer-range line; 7 metrics) → the screengrab viewer → jump pills → Cycles (three columns with focus, dates, "N in the log" links, Gone quiet folded) → Log (Key Changes entries dated in the week, grouped by cycle, MDC-rendered with site links, long ones clamped with Show all) → Commits (bar per repo, expands to sha · date · subject, qcontrol PR links) → Captures (grouped by cycle cluster: newThing line, 8 shots then Show all, representative first and outlined) → Releases & deploys → feed notes.
  • Screengrab viewer (Mark, 2026-10-05: "lead with one main screenshot, then a small horizontal gallery … one representative from each cluster"; "clicking sub items should change the main display item like a slideshow instead of scrolling the window"; "show the stats above the screengrab viewer"): the captures cluster by cycle. Each cluster gets one representative, picked server-side by representative() in window.ts: its most settled thread (final / after / promoted / composed / shipped / landed, in the thread label or the file name), else its newest thread; never a before; default variant; first in program order. The cluster caption is the shot's newThing. The manifests copy newThing onto every shot of a cycle (169 of 223 that week), so it captions but can't pick. Clusters are ordered busiest record first, and the first is the opening slide. The strip, the ← / → buttons and the arrow keys change the main image; the strip scrolls itself to keep the selection in view and the page never moves. "See all N shots ↓" is the one link that jumps down to the cluster's group. Sep 28 picks: c100 mock-home (composed mocks), c102/c103/c110 -after, c109 micro-cards-b, c108 final-integration-routing-failed, c106 qdash-listing-rest, c104 band-rest, c107 new-overview (promoted app).
  • API: /api/cycles/weeks/<monday> adds prev / next / current, clusters, and entry ASTs (raw markdown dropped, a long flag kept). The busiest week is about 620 KB of JSON and about 1 MB of SSR HTML. That's acceptable for an internal mock; the page needs trimming before promotion. The week view's "Week details →" links and multi-subject evo (→ #captures) point here.
  • Checked: Sep 28 renders in 0.28 s, other weeks in under 0.25 s; a non-Monday date shows the error state; strip click, ← and the arrow key change the slide, and the page doesn't scroll; repo expand (86 qcontrol commits, 8 PR links); log Show all; Gone quiet; capture thumbnails load (0 broken). Dev-server note: neither design nor design-polling reloaded server or template edits this session, so each check ran after a restart, and the first request after a restart waits on Vite's dependency warm-up.

Pages & components section (2026-10-05): Mark, 2026-10-05: "list out the pages or components worked on if they exist, including a link to the evolution page supporting that particular page or component". The week detail gets a Pages & components section after Cycles, with its own jump pill. The source is the capture subjects in the window (window.ts subjectsOf → feed subjects): kind, label (subjectLabel), the cycles that shot it that week, the shot count, the newest shot as a thumbnail, its all-time moments and first-capture date, a new pill when it was first captured inside the week, and /cycles/evolution/<kind>/<slug> (design subjects; sister manifests have no evolution pages yet). Grouped Pages / Components / Patterns, 12 per kind, then Show all. Sep 28: 57 subjects (53 pages, 4 components), 26 new. The busiest are page/sticky-title (16 shots, c106, new) and page/users (15, c108 · c107 · c103). The evolution links resolve. Pages or components touched only in code (no capture) don't appear; commits don't name subjects. LATER if wanted: map changed files (app/pages/pages/*.vue, layer components/**) to subjects.

Promoted (2026-10-05): Mark, 2026-10-05: "let's move the commits graph just below the screenshots", then "it looks good, let's promote".

  • Commits move up: Commits now sits right under the screengrab viewer, ahead of the jump pills, and is the first pill.
  • Promotion: the mock moves (git mv) to app/pages/cycles/weeks/[[week]].vue, so /cycles/weeks opens the last full week and /cycles/weeks/<monday> opens any week. The back link goes to "Cycles by week" (/cycles/?view=week), and the mock's source line is gone.
  • Redirects: nuxt.config routeRules 301 the old /pages/_meta/cycles-week-detail[/**] URLs to the new route.
  • Repointed links: the week view's "Week details →" and multi-subject evo links, and the _meta registry entry (href: '/cycles/weeks'; the c111 section says promoted).
  • Entry point: /cycles gets a "Last week →" link under "Page evolution →". It's the visible way in, and the static crawler's: prev / next then reach every week.
  • Checked: /cycles/weeks (0.6 s) and /cycles/weeks/2026-09-28 render with sections in order (verdict, viewer, Commits, Cycles, Pages & components, Log, Captures, Releases & deploys); non-Mondays show the error state; /cycles/<project>/<id> still resolves (the static weeks dir wins over [project]); both redirects 301 with the week kept; /cycles and /pages/_meta link to /cycles/weeks; the week view's links point at /cycles/weeks/<monday>.

Number layouts + week-row cards (2026-10-05): Mark, 2026-10-05: "in the normal numeric format of the cycles page, it would be nice to have a list view and a micro card view that fits double the cycles per row"; "let's make the list a uxtable, one per section"; "in the list view, we have the dates wrapping, let's use the uxtable headers as well, including the column lines"; "in the week view, it might be nice to have a tiny card to go with the rows … maybe 30px tall".

  • Layout switch: the Number view gets a second UxTabGroup, Cards | Micro | List (?layout=micro|list; Cards stays the default and unchanged).
  • Micro (CyclesMicroCard): an 80 px thumbnail with the id badge, a two-line title, a sm status pill and the date, with the focus line in the tooltip. Columns are 2 / 4 / 6 / 8 / 10, twice the Cards grid at every breakpoint (8 a row at 1440).
  • List (CyclesList): one UxTableList per project section inside UxOverflowX, so it gets the table-list header band, column lines, no-wrap cells and a sticky header. Columns: Cycle · Title (+ focus, truncating) · Status · Started · Closed · Images; a row opens its cycle. The dates come from the cycle timeline (the weeks fetch the page already makes), so a closed cycle shows its HISTORY / git close, with ≈ when inferred. The record-only completed field is on just 7 design CYCLE.md files.
  • Week-row cards: each CyclesWeekRow leads with a 48 × 30 tile of the cycle's hero thumbnail (thumbnail now rides TimelineCycle → WindowCycle / WeekCycleInfo; 123 of 199 have one, the rest show an empty tile). At that size a white product UI reads faint; a cropped zoom (e.g. the top-left third) would read better if wanted.
  • Checked: 8 tables / 201 rows, 1312 px wide at 1440 with no overflow, dates on one line, 1 px column lines; 373 week-row tiles (217 with images, all loaded); Micro 8 a row.
  • 2026-11-02, Micro becomes the default: at Mark's request, /cycles opens in Micro. ?layout=cards and ?layout=list select the others, and old ?layout=micro links still work (app/pages/cycles/index.vue).

Outcome

(open)

Decisions (kick-off, 2026-10-05)

  • Still open = carried through the week: started before the week and not closed by its end. A long cycle appears in every week it was alive. Started and Closed are the week's events.
  • Scope: all projects the atlas reads (design, qmap, qflow, bob-wire, market-analyst, qpixel, www, app), filterable by project.
  • Date gaps: both. The CYCLE.md **Created:** / HISTORY.md **Completed:** dates win. Otherwise the git first/last-touch date of the cycle dir is used, cached and shown as inferred. After that the records are backfilled (a reviewed list, then a commit).
  • Week detail contents: commits per repo, captures from that week, layer releases & deploys, and cycle record excerpts (Key Changes entries dated inside the week).
  • Existing view kept: numerical order remains the default /cycles view (Mark, mid-prompt).
  • Ideas adopted (2026-10-05, Mark: "love your new ideas"):
    • Partner digest: /partner-digest is rewired in c111 to draft from the same feed as the week page (Phase 4).
    • Stale-open signal: carried rows show "open N wks, quiet M". A week is quiet for a cycle only when neither its record nor commits moved: no Key Changes entry dated in the week, and no commit that touches its cycle dir or names it (cN) in the subject, in any atlas repo. The row turns amber at 3+ quiet weeks in a row. Parked cycles are exempt.
    • Evolution links: on both the week detail's captures strip and the week view's cycle rows (a mark when the cycle produced subject-keyed captures that week).
  • Defaults (not asked): weeks run Monday–Sunday and are labelled "Week of Sep 28"; the view lives in the URL (?view=week).

Artifacts

Qpoint Brand Style Guide