Summary
Continuation after the CONV-30 Cloudflare-deploy compaction earlier this morning. Wove together three threads on top of the Cloudflare loop the previous session closed: turning preview.offplan.online from a basic file listing into a stakeholder-ready surface (per-card author metadata, grouped iterations, two-axis filter row, 6-state lifecycle model, 14 files flipped to draft baseline, nested-anchor card-duplicate fix), capturing the per-artefact about-page UX as P11e in the vault workstream so the next /build there has the IA brief in hand, and migrating memory from per-machine ~/.claude/projects/.../memory/ into .claude/memory/ inside the repo so Roman and Sergei share identical context via git pull. Closing commit added the project banner spec (๐ offplan.online ยท <slug> ยท <session-id> ยท branch:<branch>) to /resume + /handoff โ the parallel session also added their own banner work at 9cfbc87 (16:28) after my 6d61aee (16:19); both layers coexist for now and want a reconcile pass in vault P11b.
What I Did
f936f72โ Per-card creator + last-updater on the index. Extendedscripts/build-rendered-index.pyto extract both first-commit and last-commit author/timestamp viagit log --follow. Cards now show "Updated <when> ยท by <author>" and "Created <when> ยท by <author>" so collaborator context is visible at a glance.ca31b12โ fix(deploy): drop--commit-messageflag from the Cloudflare Pages GitHub Action.${{ github.event.head_commit.message }}was splatting unquoted into the wrangler command line, breaking every push-triggered deploy since the workflow landed. Manualworkflow_dispatchruns had been succeeding becausehead_commitis empty for those โ masking the bug. Drop and rely on--commit-hash.acfcc38โ feat(index): grouped iterations + kind filter chip bar + status pills. Cards now group by<meta name="group">; latest visible, older siblings fold into "Earlier iterations (N)"<details>. Sticky filter chip bar at the top, one chip per kind that has entries. URL hash (#kind=design) syncs both ways; deep-links work on cold load.8ecb600โ feat(index): 6-state status model. Review axis (draft โ in_review โ approved) ร lifecycle axis (superseded ยท parked ยท archived).currentaliased toapprovedfor back-compat with Roman's earlier backfill. "Show archived (N)" toggle appears only when archived entries exist. CLAUDE.md "Live preview" section expanded with the full convention;docs/conventions/lifecycle.mdrow added for Rendered HTML status. The vocabulary explicitly avoidsdeclined/rejectedโparkedkeeps the framing about relevance, not quality.554061cโ feat(index): status filter row (second axis) AND-composes with kind. All 14status=currentHTMLs flipped tostatus=draftper Roman's call ("nothing is approved yet"); the 2 superseded landing pages stay superseded. Fix nested-anchor duplicate card: card now an<article>with inner<a class="card-link">wrapping the main content; the<meta name="supersedes">"Replaced โ see X" link sits as a sibling, outside the clickable area, with a dashed top-border footer band.f7a534fโ workstream(vault): P11e about-page brief. Captured the IA + layout sketch inworkstreams/repo-as-canonical-store-vault.md: page placement between index and full render, 8 sections (status pill + summary + "How it evolved" + "Sessions that contributed" + "Earlier iterations" + "Related" + CTA + footer), data sources (frontmatter + reverse-scanplans_touched/workstreams_touched+ .md changelog), URL structure open call, index-link migration, out-of-scope items.6d61aeeโ memory: move offplan-online memory into the repo..claude/memory/directory committed (5 entries migrated verbatim from Roman's personal directory). NewMEMORY.mdindex without the GUPPI-leaked "Session Pointer" / "Recent Sessions" block. CLAUDE.mdยง "Shared memory (committed)"directive instructs every offplan session to use the in-repo store.docs/conventions/memory.md(101 lines) documents the layered model (memory entries โ ADRs / conventions / learnings) + cross-machine sync mechanics./resume+/handoffget the project banner spec. Un-gitignored.claude/memory/(was added by flip P1 thinking it was per-machine state โ reversed with an explanatory comment).
Decisions Made
- Memory becomes shared-by-default via git. Personal
~/.claude/projects/<repo>/memory/is bypassed by CLAUDE.md directive for offplan sessions. Alternative: keep two layers + a manual/share-memorypromotion command. Rejected because friction-of-promotion fails in practice and Roman explicitly asked for "no manual tasks". The friction is the bottleneck, not the safeguard. - Status vocabulary uses
parked, notdeclinedorrejected. The work is real; the direction shifted.parkedkeeps the framing about relevance rather than quality.archivedis hidden by default behind a toggle so day-to-day views stay clean. - About-page becomes the canonical landing for each artefact. Index cards'
hrefmigrates from<slug>.htmlโ<slug>/when vault P11e ships. The full render moves one click further behind an explicit "Open the full document โ" CTA. The about-page is where "is this the thing I want?" gets answered before the full document loads. - Per-card filtering with
:has()over group-level filtering. Mixed-kind groups (launch-plan contains 4 plan-kind + 2 reference-kind cards) need card-level decisions; group-level CSS hides reference cards nested under a plan-flavoured group when filtering Reference. Auto-expand<details>when filter is active so nested matches show inline. - Card structure is
<article>not<a>. Anchor-in-anchor (the<meta name="supersedes">link inside<a class="card">) triggers browser parse-and-split producing an orphan duplicate card. Restructured: outer<article class="card">+ inner<a class="card-link">wrapping main content + the supersede note as a sibling. - The CONV-30 cross-project leak was the global Notion Sessions DB, not isolation failure. The leaked CONV-8000-range GUPPI entries in offplan's personal MEMORY.md came from a pre-flip
/resumequerying the shared Notion Sessions DB with no project filter. Once flip's Notion-silent/resume(already shipped today by the parallel session) is in use, the leak is impossible by construction. So we did NOT rename/resumeโ/oo-resumedespite Roman initially proposing it. The rename would have changed the COMMAND name but not the underlying query. - Two-axis filter row beats single combined filter. Kind + Status as separate rows, AND-composed, makes intent explicit. URL hash carries both (
#kind=plan&status=draft&archived=1). scripts/build-rendered-index.pyis a known stopgap. Will be partially or fully subsumed when vault'srender_md.py(P11b) +render_about.py(P11e, new) ship together. Documented inline so the next refactor knows what to retire.
For Future Me
- The 14 draft renders are the baseline. Flip individual files
status: draft โ in_review โ approvedas work matures. The pill colours track the state automatically: tan border for draft, rust border + bold pill for in_review, moss pill for approved. .claude/memory/is committed; do NOT re-gitignore it. The flip workstream added that line during P1 setup, presuming personal-by-default. We reversed the decision after Roman and I re-litigated. A.gitignorecomment explains why so the next operator doesn't re-add it.- About-page (P11e) brief lives in vault. See
workstreams/repo-as-canonical-store-vault.mdยง "About-page brief (P11e, surfaced 2026-05-11)". URL structure (<slug>/vs<slug>.about.html) is an open call left to the P11e implementer; both are valid. - Parallel session added their own banner work at
9cfbc87("adopt GUPPI-style closing banners", 16:28) AFTER my6d61aee(16:19, project banner spec). Both layers coexist in the command files; diff-check next session and reconcile if duplication appeared. - The
/handoffthat loaded mid-session was GUPPI's, not offplan's. Worth investigating why user-level slash commands shadowed the project-scoped versions in Roman's terminal โ project-scope should win by Claude Code precedence. The banner shipped today is exactly the visual signal that catches this; expect๐ offplan.online ยท ...as the first line of any/resumeor/handoffoutput here from now on. - The parallel session's RT-260511-02 already shipped (
60b7bc8). They started onforge-vault-setup.md(untracked in working tree as of this handoff). That's their workstream; don't touch it from this session.
Learnings
- Anchor-in-anchor is HTML-parser-fail. When a card has any inner clickable element, the card itself must NOT be an
<a>. Restructure to<article>+ inner<a class="card-link">+ sibling inner links. Browsers silently split otherwise, producing orphan duplicate fragments that look like real cards in querySelector counts. :has()CSS pseudo-class is baseline-supported (2023+). Lets you hide/show group containers based on inner-content matches without JS. Powerful for filter UIs that need "hide group if no child matches".- YAML interpolation in GitHub Actions splats unquoted.
${{ github.event.head_commit.message }}placed in acommand:field becomes positional arguments split on whitespace. If the value contains spaces, downstream CLI breaks. Avoid putting any free-form text into command interpolations; pass viaenv:instead, or drop the flag. - Friction-of-promotion (personal โ shared) fails in practice. Personal memory entries get written hot, never reviewed, never promoted. Shared-by-default beats "discipline" every time. Generalises beyond memory: anywhere a system has a "promote when ready" gate, the gate becomes a bottleneck rather than a safeguard.
Open Questions
- [OPEN] About-page URL structure:
<slug>/(directory) vs<slug>.about.html(flat). Tradeoff documented in vault's P11e brief. Defer to the P11e implementer. - [OPEN] Why did GUPPI's
/handoffslash command shadow offplan's project-scoped/handoff.md? Project-scoped should win by Claude Code precedence rules. Investigate next session โ likely a user-level setting or shell alias. - [OPEN] Does the parallel session's
9cfbc87banner work conflict with6d61aee's banner spec? Diff-check next session and reconcile if duplication appeared.
Resume Prompt
Verify on next /resume that the project banner
๐ offplan.online ยท <slug> ยท <session-id> ยท branch:<branch>prints as line 1 โ if not, project-scoped command preference is broken and GUPPI's user-level commands are shadowing; investigate command resolution. Diff9cfbc87(parallel session's banner work) against6d61aee(my banner spec) for conflicts or duplication and reconcile if needed. The 14 draft renders await review โ flip individual ones toin_reviewthenapprovedas you read them, watching for the pill colour change as visual confirmation. The parallel session has moved on toforge-vault-setup(their next workstream after vault P11) โ that's theirs to drive, not yours. My contribution closes at 7 commits +.claude/memory/shared store + P11e brief; nothing pending from this session. Confidence: H โ all commits pushed, Cloudflare deploy verified end-to-end this morning, memory share survives the next /pull on either machine.