Project History
This section documents every GSD milestone (versioned in .planning/milestones/) that has shipped on Objectuve, plus the one currently in progress. Each milestone page is a living record: what the goal was, what actually shipped, which phases delivered it, and where to find the full planning trail on GitHub.
How this differs from CHANGELOG and PRDs
- CHANGELOG.md (at repo root) tracks user-visible app releases tied to app version tags (
v3.6.6,v3.5.0, …). - Feature PRDs describe what a feature should be, before it is built.
- Project History (this section) records what each GSD milestone actually shipped — the engineering + operational diff per numbered milestone (
v1.0,v1.1, …). Milestones do not map 1:1 to app versions; they are the unit of planned work in the GSD workflow.
Status legend
| Status | Meaning |
|---|---|
| In Progress | Roadmap written, phases partially complete |
| Shipped | Every phase complete, milestone audit written (where applicable), merged to master |
| Abandoned | Milestone was started but rolled back or deferred indefinitely |
Milestones
| Milestone | Name | Status | Date | Phases | Reqs | PRD / Audit |
|---|---|---|---|---|---|---|
| v4.67 — Streak Insurance for Supporters | Streak Insurance for Supporters (closes roadmap item 48, the last open item in Phase 7 "Monetization & Teams"; planning found the source ticket's premise wrong twice — GoalTracking::UseStreakFreeze is proactive-only since v4.57 and cannot recover a broken streak at all, and recovering one was already shipped free, twice, via Gamification::RepairStreak's XP lane and AcceptStreakMercy's once-ever lane — so the real ask was a third recovery lane, free of XP cost, repeatable on a monthly allowance, reserved to Supporters, reusing Gamification::StreakGapChecker and the existing 48-hour repair window verbatim; Phase 1 shipped Gamification::ClaimStreakInsurance, deliberately leaving streak_repaired_count untouched so a claim can never consume the free XP-repair allowance (D5); Phase 2's D8 ruling resolved the insurance offer via an independent target lookup rather than widening the existing XP-lane scope, which would have changed which goal a non-Supporter is offered; Phase 3's UI-SPEC (Desi) narrowed the upgrade prompt from a planned two states to one, catching a card that would otherwise have been summoned, for the first time, for a user with no free option left; Phase 3b closed a rendering gap D8 didn't reach; Phases 4a-4b built the card and the upgrade moment, and 4c fixed a two-phase gap where Dashboard.vue never actually mounted the wiring the first two frontend phases built, despite a task package asserting it already was; Phase 5 closed on a human-escalated PBC pricing-philosophy question — streak insurance is the first Supporter perk that does something, so Josh ruled the standing commitment is "no features are ever paywalled," not "purely cosmetic," correcting docs/features/supporter.md to a testable claim rather than softening it; Phase 5 also deliberately left roadmap item 54 open against the milestone ROADMAP's own stale instruction to tick it, after verifying against source that it isn't actually shipped; ships behind streak_insurance_enabled at 0% rollout — this is complete build-out, not a launch, and no free recovery lane (use_streak_freeze.rb, repair_streak.rb, accept_streak_mercy.rb) was touched by any phase in this milestone) | Shipped | 2026-09-20 | 8 | 50/50 | Narrative · Audit |
| v4.66 — Bound-Class Guard Reach | Bound-Class Guard Reach (both contrast guards — tintInkGuard.spec.ts/plainSurfaceInkGuard.spec.ts — reached the element tree through a function reading only a static class="..." attribute, so a :class/v-bind:class binding was invisible to every tier, and had already shipped a real defect past a green build twice, TeamMemberRow.vue:35 among them; Orion's census found 776 live bindings across both apps, of which only 17 raw-ink and 69 tint-bearing bindings carried a known defect; Phase 1 built an AST census harness and ruled branch semantics — mutually exclusive branches of one binding never pair across each other; Phase 2 shipped boundClassResolver.ts, the shared resolver both guards now read through, re-expressing (not weakening) v4.40's shipped completion gate to land it; Phases 4 and 5 swept the raw-ink and tint/ink-pair survivors the widened scan surfaced, and taught the guard to recognize a token-backed bg-gradient-<hue> fill and to scope its ceiling check per element rather than per line; Phase 6 restored the completion gate to full strength with a sanity assertion that the resolver still sees real bindings, proven to fail red under a stubbed-empty resolver, and landed the DESIGN.md rule amendment; six phases were planned, five executed — Phase 3, the identifier tier, was deferred to OBJ-4030 on CENSUS-3 evidence that zero of the known defect population depended on it, so the milestone closes complete without it) | Shipped | 2026-09-20 | 5 | 28/28 | Narrative · Audit |
| v4.65 — Brand & Marketing Assets Completion | Brand & Marketing Assets Completion (closes roadmap item 46, the fifth of seven Phase 6 "Growth & Virality" items Josh greenlit sequentially on OBJ-1125; a kickoff audit found the item ~85% already shipped — V12 logo pipeline, Android adaptive icons, and an 18-competitor analysis directory all pre-existed, just not at the roadmap's named paths — so the milestone closed four verified gaps instead of rebuilding anything: marketing apple-touch-icon + web manifest parity across 11 pages, iOS 18 dark/tinted app-icon appearance variants (caught via a pre-deletion re-grep that logo.svg was still referenced by Storybook, revising a planned delete into a refresh), publishing the already-written first-person Origin Story live at /story with a dedicated OG card, and docs/product/competitive-analysis.md as the named entry point with Fabulous added to close the one missing named competitor; Phase 2's UI-SPEC settled a real narrative conflict between about.html and origin-story.md in favor of the founder's first-person account; Phase 5 found a second stale-doc instance of the milestone's own founding defect in a PRD no phase had touched and filed nine adjacent gaps as individual issues rather than leaving them in prose; one residual risk carried forward honestly — the iOS asset catalog is schema-valid but has never been compiled by a real iOS build) | Shipped | 2026-09-15 | 5 | 34/34 | Narrative · Audit |
| v4.64 — Import From Other Apps | Import From Other Apps (closes roadmap item 45 — a user switching from another habit tracker uploads a CSV of goals, habits and check-in history, previews exactly what will be created, commits it, and keeps their history with correctly recomputed streaks; kickoff found no Habit model existed (a habit is a Goal with recurrence_type), no import code anywhere in the repo, and Objectuve's own GDPR export wasn't re-importable — habit_completions absent, headers silently drifting with every migration; Phase 1 fixed both and added a |-delimited encoding rule for recurrence_days after Roy caught the original fixture skipping the one non-scalar column; Phase 2 shipped the staged preview pipeline, forcing a naming split (DataImport the model, ImportExport the namespace) every later phase inherited; Phase 3 is the milestone's integrity core — a naive loop over the existing per-goal/per-check-in interactions would enqueue ~14,400 background jobs and mint unearned XP/badges/freeze-tokens for a multi-year history, so goals and check-ins bypass the normal side-effect-heavy paths entirely and both streak recomputes run through a new award: keyword that writes the correct numbers with zero reward state; Phase 4's UI-SPEC ruled the surface its own route, ten states (not the plan's nine), and a hard no-streak-celebration policy before either Phase 3 or 5 was dispatched; Phase 5 shipped the flagged frontend and found/fixed five UI-SPEC compliance gaps mid-build, correctly routing two backend-shaped gaps to separate follow-up issues rather than absorbing or dropping them; Phase 6 answered all four stretch-goal provider integrations with a cited verdict, ruling Google Fit not viable (its API sunsets by end of 2026) rather than carrying it forward as a vague deferral; ships behind data_import_enabled at 0% rollout — this is build-out, not a launch, and no real user can import data from the app today) | Shipped | 2026-09-15 | 7 | 48/48 | Narrative · Audit |
| v4.63 — Community Discovery & Seasonal Events | Community Discovery & Seasonal Events (closes roadmap items 41 and 43, the third of seven Phase 6 "Growth & Virality" items Josh greenlit sequentially on OBJ-1125, paired because item 41's ranking formula takes item 43's seasonal-participation term as a first-class input from Phase 3; planning found recommendedCommunities { members { email } } returned real member email addresses via an undifferentiated UserType delegation — fixed unflagged in Phase 1 with an allow-listed DiscoveryMemberType — plus a matchScore field that had never once returned a real number (the underlying method didn't exist, floods Sentry, silently 0), a mutualAllies hardcoded 0 that Phase 4 (Desi) ruled stays 0 permanently as an invisible ranking weight rather than a disclosed count or name, a health_score 20% literal constant costing 4–6 uncached queries per community, and a discovery order actually decided client-side, discarding the server's answer; Phase 6 gave seasonal events their own platform-scoped SeasonalEvent/SeasonalEventParticipant pair rather than making community-scoped CommunityChallenge nullable, with badges derived from the participant's own row rather than a new entry in the append-only BadgeCatalog enum; Phase 3 survived a real merge conflict and a genuine ~66-hour stall waiting for discovery_ranking_v2 to be created in PostHog (no crew agent holds the API key), resolved by Josh directly with a durable workflow_dispatch --apply fix shipping the same day so Phase 7's identical wall didn't repeat the wait; community_insights.upcomingEvents was ruled descoped entirely, not deferred, since serving a SeasonalEvent through the community-scoped CommunityEventType would error at execution time; ships behind discovery_ranking_v2 and seasonal_events_enabled, both at 0% rollout — this is complete build-out, not yet a launch, and seasonal_events_enabled additionally cannot be raised above 0% until OBJ-3961's ordering-gap fix lands) | Shipped | 2026-09-19 | 10 | 7/7 | Narrative · Audit |
| v4.62 — Feedback Tags & Public Board | Feedback Tags & Public Board (closes roadmap items 45b and 45c, the second and third of seven Phase 6 "Growth & Virality" items Josh greenlit sequentially on OBJ-1125, bundled into one milestone because the public board renders the same post list the in-app board does — shipping tags second would build the tag chips, filter row and tag-aware query twice; planning found feedbackPosts/feedbackPost both resolve to the full Types::UserType with no field-level authorization, so de-authing them for anonymous viewing would have published every feedback author's email address — Phase 6 instead ships a separate, allow-listed PublicFeedbackPostType family that cannot structurally reach Types::UserType, proven by a schema regression spec; Phase 1 shipped FeedbackTag/FeedbackPostTag and admin CRUD; Phase 2 (Desi) specced tags on the in-app board, ruling a 3-tag cap and admin-managed-only tagging with no user proposals; Phase 3 wired tags through the authenticated API, correcting the cap from the proposed 5 to the spec's 3; Phase 4 shipped the in-app picker/chips/filter row behind feedback_tags_enabled, dispatched against Phase 2's verified-but-unmerged spec branch when a branch-staleness misdiagnosis stalled its merge for ~30h; Phase 5 (Desi) specced the public board's anonymous read experience and the private_mode attribution ruling, anonymizing to "a member" indistinguishable from a no-data author; Phase 6 shipped the public read path behind a server-side env-var kill switch, PUBLIC_FEEDBACK_READ_ENABLED, corrected from the PostHog flag planned at kickoff since FeatureFlagService.enabled? fails closed for anonymous callers; Phase 7 stood up feedback_site/, a standalone Vue app with its own Firebase Hosting target and a crawler-facing SSR path serving real post content, unlike the public_goals precedent's empty-body template; Phase 8 shipped the docs, deliberately omitting the user-facing changelog entry since nothing in this milestone is reachable by a real user at close; one milestone-level near-miss caught pre-merge — the ROADMAP's own tracking PR was contaminated by a stray git add sweeping in 136 unrelated files, 16 carrying stale content, rebuilt clean and rescued directly into this close; ships behind feedback_tags_enabled at 0% rollout and an unset PUBLIC_FEEDBACK_READ_ENABLED, with feedback.objectuve.com itself still unprovisioned in GCP — this is complete build-out, not a launch, and no real visitor can reach the public board today) | Shipped | 2026-09-16 | 8 | 76/76 | Narrative · Audit |
| v4.61 — Allies-Only Goal Visibility | Allies-Only Goal Visibility (closes roadmap item 44 — a goal's two-state public/private boolean gains a third allies tier, visible to the owner and every accepted ally, without touching the pre-existing accountability-partner overlay; kickoff found the encoding that makes this safe against the exact OBJ-1871 failure mode a prior visibility tier hit — allies mirrors private = true at the column level, so every one of the ~17 pre-existing read paths keeps hiding an allies-only goal by default, and each of Phases 2–3's "serve" decisions is a deliberate, spec-covered opt-in rather than an accident; Phase 1 added the visibility column and fixed a pre-existing private nullability bug in the same migration; Phase 2 shipped setGoalVisibility and the milestone cascade, discovering along the way that three milestone-creation call sites (not just the one the plan named) also needed to inherit visibility, and that GoalType's two new owner-only follower counts needed an explicit require_owner! since GoalType also backs the non-owner-reachable publicGoal query; Phase 3 audited all ~17 read paths plus an 18th (build_ally_activity_feed.rb's achievement mapper) the initial survey missed, and extracted the four social write gates' shared decision wrapper — not just the shared lookup underneath it — after Roy caught it copy-pasted four times; Phase 4's UI-SPEC found the ROADMAP had named the wrong existing control and ruled the partner-sharing card's ally-tier third state, the milestone's highest-risk copy decision; Phase 5 shipped GoalVisibilitySheet.vue and a third "Allies only" profile section, and Roy caught an optimistic-update race only a mounted parent+child test with a deferred promise could see; ships behind goal_allies_only_visibility at 0% rollout — this is build-out, not a launch, and no real user can reach the third state yet) | Shipped | 2026-09-15 | 6 | 45 | Narrative |
| v4.59 — Backend Concurrency Remediation | Backend Concurrency Remediation (RAILS_MAX_THREADS was set nowhere in the repo, so Puma ran its hardcoded default of 3 threads while every deploy/service.*.yaml advertised containerConcurrency: 80 — 27x real capacity — so a small burst of synchronous AI-coaching requests occupied every Puma thread and made every other request on that instance slow (Sentry OBJECTUVE-API-2Q, p95 19.5s); Phase 1 decoupled PUMA_MAX_THREADS from DB_POOL_SIZE, no behavior change; Phase 2 committed deploy/capacity-budget.json and fixed a live worker pool-starvation bug the original diagnosis missed (the worker runs Puma and Sidekiq sharing one AR pool); Phase 3 retuned staging and proved the fix with a new k6 contention load test — read p50 1.81s poisoned → 57ms fixed — though the contention window it measures closed permanently mid-phase when the concurrent v4.60 milestone finished moving AI mutations off the request thread; Phase 4 retuned production and honestly disclosed its one real shortfall — a re-measured peak of 19-20 connections exceeds what the committed 25-connection budget can fund after reserves, so CAP-16 ("size above observed peak") is explicitly waived, not met, pending a human-run Cloud SQL tier bump (+$15-20/month, with Josh since 2026-09-16); Phase 5 shipped a CI capacity guard (20/20 tests) plus the full operations write-up, including a "Known limitation" section keeping the waiver visible past close; audit passed-with-caveat — SC-7 (the 48h Sentry watch) deliberately carried open rather than ticked, since its window hadn't finished running at milestone close) | Shipped (passed-with-caveat) | 2026-09-17 | 5 | 35/37 | Narrative · Audit |
| v4.58 — Offline Capability Rebuild | Offline Capability Rebuild (scoped from a code audit, not a repro — Josh raised it as an aside while reporting an unrelated backend issue; kickoff found the offline mutation queue and the offline overlay were mutually exclusive, since the overlay blocked the UI within the same 2s window the queue needed to fire, had no native-platform gate unlike every other PWA surface, and offline check-ins were credited to the replay day rather than the tapped day; grew from 6 phases at kickoff to 14 at close as work in flight repeatedly found the scope too narrow — a same-day hotfix (Phase 0) platform-gated the overlay off native ahead of the rest of the milestone; Phase 1 shipped client_event_id idempotency on checkInHabit; Phase 2a made the queue record the tapped day, Phase 2b made queue failures reviewable (failed[], DidntSendSheet, retry/discard) instead of silently discarded; Phase 3 (Desi) specced the non-blocking offline state; Phases 4a–4d replaced the blocking overlay with ConnectionStatusBar.vue and the sync chip/sheet pair, and generalized unavailability handling across Coach/Feed/Teams; Phase 5a persisted the Apollo cache on a default-deny allowlist bounded to 2MB; Phase 5c wired honest staleness onto it so no dashboard value renders a false 0 on a stale cache; Phase 5d, inserted when Phase 5c's own scope note surfaced a gap, closed Focus mode's staleness blind spot on both the Auto and explicit-focus paths; Phase 5b promoted offline_status_bar_enabled to 100% rollout, a PostHog API write gated on two prerequisite fixes landing first; Phase 6 (Dori) reconciled docs, finding drift wider than its own four-file scope and one doc claim that had inverted the milestone's own central promise; ships live at 100% rollout since 2026-09-17, no version tag yet — rides the next release train) | Shipped | 2026-09-17 | 14 | 77/78 | Narrative · Audit |
| v4.57 — Spendable Streak Freezes | Spendable Streak Freezes (GoalTracking::UseStreakFreeze had been fully implemented, guarded, and spec-covered since v1.11 with zero frontend call sites — Dori found the gap while closing the v4.47 Concept Legibility audit, row D2; settled in planning as "ship the manual affordance," since per-goal habit streaks have no automatic forgiveness at all, unlike the separate user-level sign-in streak's soft-grace rest days the guide had wrongly contrasted them against; Phase 1 hardened the mutation with a bounded window guard and safe date parsing; Phase 2's UI-SPEC ruled a new dedicated StreakFreezeCard.vue + FreezeDaySheet.vue outside the collapsed Analytics accordion, and found a real future-date streak-decrement bug in code neither phase was scoped to touch, routed to a new Phase 2b; Phase 2b narrowed the window to proactive-only (today..+14) and fixed the streak-walk bug; Phase 3 shipped the control unflagged — live to every user on merge — surfacing and resolving three CI-tooling defects along the way, none in its own diff; Phase 4 removed the dead FreezesRow mount that had never once rendered in production, fixed two GraphQL description strings the window change had falsified, and reconciled four drifted doc claims plus both changelogs) | Shipped | 2026-09-13 | 5 | 23/23 | Narrative · Audit |
| v4.56 — Celebration Sharing Cards | Celebration Sharing Cards (the first execution slice of the Phase 6 "Growth & Virality" product phase, deliberately scoped to one roadmap item — item 39 — rather than all eight open Phase 6 items, since the eight share no common spine and item 39 is the only one whose mechanism is acquisition; generalizes the one existing Critical Path share card into a shared render kit covering four celebration variants — badge, goal completion, milestone, streak — at two aspect ratios; Phase 2's anti-vanity UI-SPEC review moved every share affordance off celebration moments onto three persistent surfaces instead, since a share prompt inside a celebration is a prompt the user didn't ask for at the moment they're least able to decline it; Phase 3 settled the raw Web Share API over Capacitor's Share.share() as the one path that can carry a card image to a native share sheet; Phase 4 reconciled a real cross-phase payload-shape conflict between Phase 1's server-authored prose and Phase 3's facts-based renderer, landing on "server owns facts, client owns strings," and found + removed a pre-existing PBC-floor violation on CelebrationCinematic.vue; Phase 5 built referral attribution from nothing — a share code reserved before the OS share sheet opens, attributed exactly once via a database unique index — and found + fixed a GDPR-erasure BLOCKER, the third recurrence of a defect class whose generalized guard covered only two of the tables that needed it; ships behind celebration_sharing_enabled at 0% rollout, so the milestone is complete build-out, not yet a launch; one criterion, the live referral-funnel number, is deliberately deferred to OBJ-3706 pending the flag ramp) | Shipped | 2026-09-13 | 6 | 47/48 | Narrative · Audit |
| v4.55 — Docs AI Assistant | Docs AI Assistant (ships a Mintlify-style "ask a question, get a synthesized answer with source citations" assistant on both doc surfaces — help.objectuve.com (public) and docs.objectuve.com (Clerk-gated) — on the retrieval architecture the OBJ-3612 spike validated, building the five production requirements the spike deferred: auth, rate limiting, a dedicated docs/assistant LiteLLM alias, the product's first enforcing cost ceiling (Ai::BudgetGuard), and CSP; Phase 2 settled the milestone's central design question by filling an existing, already-tuned row in the guide's search modal rather than adding a second entry point; Phase 3 shipped the public, unauthenticated askGuideQuestion with three abuse-defense layers plus a fourth (unbounded question length) Roy caught in review; Phase 5 shipped a Postgres-backed corpus for docs/'s 8.7 MB, chosen on measured memory numbers, beating its recall floor outright (90.9%→100% @ k=5) while leaving citation accuracy explicitly unconfirmed against a live model; Phase 6 shipped the Clerk-gated, @objectuve.com-restricted askDocsQuestion and disclosed at ship — not hid — that neither assistant reaches production yet, since no version tag has shipped since either surface merged; Phase 7 corrected the spike ADR's standing "neither has shipped" claim and found zero copy drift against the UI-SPEC; the milestone's own coordination ROADMAP was stranded twice by a merge race and rescued by cherry-pick at close, the same recurring shape v4.30/v4.35/v4.52/v4.53 hit) | Shipped | 2026-09-12 | 7 | 34/37 | Narrative · Audit |
| v4.53 — Runtime Coach Model Control | Runtime Coach Model Control (changing the Gemini model behind Coach meant editing six aliases across three LiteLLM YAML configs, hand-syncing Ai::Pricing's alias-keyed billing rates, and two deploys, with no mechanism forcing the routing target and the billing rate to agree; Phase 1 shipped Ai::ModelCatalog, a single source of truth for the allowlist and an effective-dated rate schedule, encoding the Gemini 3.8 Flash 2027-01-01 introductory-rate cliff for the first time; Phase 2 made the model an app_settings-backed runtime value resolved once per request through a 60s cache, closing a boundary-time finding (SET-05) where two independent cache reads could disagree, and gave LiteLLM a gemini/* wildcard route; Phase 3 shipped the admin-gated GraphQL surface, catching and resolving a cross-phase collision where a parallel branch had independently re-implemented the same surface at a different mutation path; Phase 4 designed the admin card, adding an unplanned "nothing to switch to right now" state that turned out load-bearing; Phase 5 shipped CoachModelPanel.vue beside the existing AI usage panel; Phase 6 documented the new procedure and caught mid-review that a concurrent correctness fix, OBJ-3392, had changed the exact semantics being described, refreshing the docs before merge rather than shipping stale claims; OBJ-3392 itself closed a gap where the original plan's allowlist-and-rate co-location didn't actually prevent a lapsed-but-allowlisted model from silently pricing at $0.00, and added a second live-priced model that made the milestone's headline "an admin has something real to switch to" claim genuinely true rather than theoretical) | Shipped | 2026-09-05 | 6 | 40/40 | Narrative · Audit |
| v4.52 — Android Widget Motif Parity | Android Widget Motif Parity (choosing Sprout, Mountain, or Waves — three of the five streak motifs, sprout free-tier — rendered as Stones on the Android home-screen widget, glyph and copy both, while iOS and in-app already rendered all five distinctly; two independent silent fall-throughs, resolveMetaphor's two-value ternary and captionWidthDp's bare default:, hid the gap from any test; confirmed Android-render-only from source, ruling out phantom JS/bridge work; Phase 1 shipped the design contract, catching that the ROADMAP's own stated interim would have shipped a visible regression; Phase 2 shipped a five-value enum StreakMetaphor and exhaustive copy switches; Phase 3 shipped nine drawables and a third icon slot, proving a stroked-form-gradient risk on one drawable before scaling to the other eight; Phase 4 killed a silent caption-width fall-through; Phase 5 shipped a deliberately-scoped coverage sweep, pinned the fail-closed contract in pixels for the first time, and reconciled a separately-queued docs ticket, OBJ-3247, whose central "must NOT be fixed to five" instruction this milestone directly falsified; zero routebacks, zero blocking findings across all five phases; the milestone's own ROADMAP-tracking branch (PR #2837) fell stale enough to threaten reverting two later milestones' ledger entries, rescued onto a fresh branch instead of merged) | Shipped | 2026-09-03 | 5 | 21/21 | Narrative · Audit |
| v4.51 — Design Convention Enforcement | Design Convention Enforcement (four already-locked design conventions — reduced-motion press feedback, the glass recipe, display type, and the 4px grid — were each expressed multiple ways in the codebase at once, with no mechanism to collapse them, and the hallmark audit tool itself reported compliance with the sanctioned 44px tap-target floor as debt against the 4px grid; Phase 1 replaced 266 per-call-site reduced-motion decorations across 116 files with one global CSS rule, reconciling a real disagreement between two locked source documents on what the rule even was, and catching a second, previously-undetected duplicate reset the existing guard test had missed; Phase 2 converged 67 glass surfaces onto .glass-card/.glass-sheet and minted leading-display/tracking-eyebrow; Phase 3, the milestone's only user-visible phase, fixed the app's own Design System showcase page contradicting its own "no AI label"/"Coach Purple not indigo" naming rules, plus two other dead affordances; Phase 4 snapped 26 hand-computed off-grid values to the token scale, including correcting a 46px tap target to the sanctioned 44px, deferring one structural fix as a recorded follow-on rather than a silent gap; Phase 5 fixed the measuring instrument last, deliberately, so its re-run would measure the first four phases rather than a stale baseline — gate A7's ionic_views hit count went 162 → 42, with the residual fully decomposed as 40 real out-of-scope findings plus 2 documented deliberate keeps) | Shipped | 2026-09-06 | 5 | 19/19 | Narrative · Audit |
| v4.50 — Community Badges Backed By Real Data | Community Badges Backed By Real Data (CommunityBadges.vue and useCommunityBadges had zero production call sites, the component's props disagreed with CommunityBadgesType on 12 of 13 names, and four of ten badges were hardcoded false — Josh chose to wire it up properly rather than delete the component; Phase 1 locked a final inventory of 4 kept / 6 dropped badges, reversing two starting recommendations after finding communities.is_verified has no production write path and topActive's activity proxy carries a second hardcoded placeholder; Phase 2 made the four survivors real behind named constants and deleted the six dropped fields, catching an undocumented fourth codegen artifact via CI; Phase 3 rewrote the component's props field-for-field and moved it to its correct directory; Phase 4 gave the composable its first production call site, correctly distinguishing a nullable "can't see this community" response from a genuinely empty one; Phase 5 documented the shipped system, recording the is_verified finding as a worked example for the next contributor) | Shipped | 2026-09-03 | 5 | 6/6 | Narrative · Audit |
| v4.49 — Storybook Component Evidence Capture | Storybook Component Evidence Capture (a prop-driven component state with no live route and no reachable smoke-account data had no scripted evidence path — OBJ-3079 hit this precisely, requiring Roy to hand-build Storybook and drive Playwright himself; Phase 1 built capture-storybook-evidence.mjs and closed the theme-forcing open question; Phase 2 wired it into a new, opt-in, non-required CI workflow; Phase 3 added the missing manual-dispatch trigger and, in the resulting live-proof exercise, surfaced and fixed a real defect — serve's default cleanUrls behavior was silently stripping the query params that select a story and force its theme, so every real-story capture had been rendering Storybook's blank placeholder; the pipeline's own fail-loud assertModesDiffer guard caught it rather than shipping a silent false pass, and one forced CI run produced the milestone's proof: 4 real screenshots of RepairConfirmationModal's stories, light and dark, genuinely diverging) | Shipped | 2026-09-01 | 3 | 5/5 | Narrative · Audit |
| v4.48 — Streak Motif Accretion Grammar | Streak Motif Accretion Grammar (only Stones actually accreted going in — Sprout/Mountain/Waves flipped once at day 14 via a single grown boolean and froze, Flame had no large-scale render at all, and RankChip/CelebrationToast/StreakRepairCard/StreakVisualization hardcoded stones-or-flame regardless of the user's real choice; kickoff resolved a reconciliation the dropped design contract didn't address — its three-state model and the app's existing tier ladder are independent axes, and building to the contract as written would have silently deleted the visual rank ladder; Phase 1 shipped the shared StreakMotif.vue renderer additively; Phase 2 rewired thirteen surfaces onto it; Phase 3 shipped day-accurate Bloom/Field for all five motifs — Flame's first-ever — and retired every grown = day > 14 boolean, including a fourth instance the plan missed; Phase 4 shipped the full motion table under prefers-reduced-motion; Phase 5 extended iOS widget snapshot coverage from two motifs to five, coverage-only; Phase 6 corrected docs that still described a two-motif world; the milestone-close PR missed its merge hop three times, the last via an orphaned background CI watch, before a synchronous re-dispatch landed it) | Shipped | 2026-09-03 | 6 | 8/8 | Narrative · Audit |
| v4.47 — Concept Legibility | Concept Legibility (the app named dozens of domain-specific concepts — rarity tiers, pace, streak freezes, six overlapping social nouns — with no explanation reachable from the screen that showed them, and guide_site/ already had accurate copy for most of it, unlinked; the app's one interactive explanation primitive, UiTooltip, never opened on a tap; Phase 1 audited 41 surfaces into wave 1/wave 2 with severity + remedy tier; Phases 2–3 repaired UiTooltip against WCAG SC 1.4.13 and extracted a shared ConceptExplainerSheet; Phases 4–5 shipped 25 of the audit's 30 H/M rows verbatim, deferring the rest with cited evidence — including WhosWhoExplainer.vue, one contrasting sheet for six colliding social nouns rather than six inline definitions; Phase 6 added the guide's first glossary and found docs/features/achievements.md's rarity table wrong on 13 of 21 rows; the rank-ladder collision the audit found was scoped T1-inline-only here, then fully resolved a day later by a separate product-call rename, OBJ-3024) | Shipped | 2026-09-02 | 6 | 6/6 | Narrative · Audit |
v4.46 — Storybook play() CI Enforcement | Storybook play() CI Enforcement (a play() function ran only when a human opened Storybook and clicked that story — test:unit, test:cov, ci.yml, and storybook.yml never touched it, so OBJ-2919's own outro-reachability fix was unenforced from the moment it shipped; storybookTest() generates a render smoke test for every story it discovers, not just play()-bearing ones, so wiring it took CI from 0 to 2,543 tests across 429 files in one commit's worth of enforcement; Phase 1 built the harness with zero CI changes and produced a counted 85-failure inventory; Phase 2 grew from a planned two waves to six as fixing one gap exposed the next — a signed-in session un-gating dozens of inert queries, exposing dead decorators, requiring attributable unhandled rejections, surfacing a residue sweep, ending in a real @ionic/core teardown-race fix — and killed all 11 structurally-unfailable Tier C play() bodies; Phase 3 made the job required with no continue-on-error, and its own re-measure on real CI hardware caught a disk-exhaustion failure mode the runtime-based sizing could never have seen, fixed via 4-way file-list sharding) | Shipped | 2026-09-05 | 3 | 5/5 | Narrative · Audit |
| v4.45 — Live Surfaces Beyond Notifications | Live Surfaces Beyond Notifications (achievement unlocks, partner request status, and the activity feed now update live over ActionCable, replacing every poll they used — the milestone's hardest requirement was that on three of five candidate surfaces the poll being deleted was the app's only reconnect catch-up, since no connection-state handler existed anywhere in the frontend; Phase 1 built a shared catch-up substrate and proved it on achievement unlocks, deleting the app's heaviest poll; Phase 2a, inserted mid-milestone, closed a cross-account subscription-leak hazard before the next two consumers could inherit it; Phase 2 fixed a real bug — declining a partner request notified nobody — without adding a topic; Phase 3 added the milestone's one new topic, feedUpdate, as an invalidation ping so the feed's own viewer-scoped filtering stays the single implementation; Phase 4 proved all three surfaces recover from a dropped WebSocket with one test on a required CI job, audited every remaining poll, and filed four scoped follow-ups) | Shipped | 2026-08-24 | 5 | 3/3 | Narrative · Audit |
| v4.44 — Gradient Stop Ink Contract | Gradient Stop Ink Contract (no guard in the tree had ever looked at a gradient token's individual stops — --gradient-gold stop B scored 3.97:1 against its own ink in all 20 theme×mode contexts, and Phase 1's census found the gap was total, not gold-shaped: 40 --gradient-* declarations across 22 token names in design_system/css/tokens.css, zero visible to the guard; Phase 1 also overturned two naming-convention assumptions in both directions — --gradient-coach pairs with literal text-white, never --coach-foreground, and --gradient-primary had four text-white outliers hitting 1.66:1 dark-mode; Phase 2 applied Desi's lightness-only repair and deleted four dead shadow declarations; Phases 3a/3b ran in parallel sweeping gold consumers and repairing coach/primary ink with deliberately asymmetric fix shapes; Phase 4 caught before implementation that the named parser fix alone would leave the guard vacuously green, and built the real scan-surface + cross-file ink model instead, proven non-vacuous with a red-then-green control; Phase 5 wrote the DESIGN.md rule and closed the milestone, naming one architectural exception — six supporter-theme pairs — as an owned, allowlisted, expiry-conditioned deferral rather than a silent gap) | Shipped | 2026-08-25 | 6 | 3/3 | Narrative · Audit |
| v4.43 — Email Delivery Canary | Email Delivery Canary (closes the gap where a positive-delivery signal for transactional email didn't exist — raise_delivery_errors only catches SMTP refusal, not a post-acceptance bounce, and Sentry had ingested zero events in 90 days; a daily Crono canary now sends a synthetic email per environment, resolves its real Mailtrap delivery status via a live-read seven-state contract, and pages Slack on a genuine bounce; a new fail-open /health check makes "canary silently died" distinguishable from "nothing to report"; live-fire gate visually confirmed a real Slack alert in #alerts; one acceptance criterion — the live happy-path resolution — is built and reviewed but not yet observed end to end, honestly recorded rather than rounded up) | Shipped (partial evidence) | 2026-08-22 | 4 | 3/4 | Narrative · Audit |
| v4.42 — Tint Alpha Governance | Tint Alpha Governance (OBJ-1986's narrow ask — nine ungoverned accent tint alphas — re-censused into two structural guard gaps: only 6 of 14 ink-bearing hues had an enforced AA ceiling, and tintInkGuard.spec.ts's allowlist held 104 entries, 78 orphaned against a closed issue; Phase 1 extended the ceiling to all 14 hues; Phases 2–3 dissolved all 78 orphaned + 19 hover-deferred entries structurally, finding one real defect; Phase 4 fixed the 3 sites the new ceiling flagged; Phase 5 widened the guard to raw-CSS alphas and two new scan roots; Phase 5b (inserted) disposed the 52 findings that surfaced, including 8 real celebration-tier fixes; Phase 5c (inserted) closed a -foreground-as-ink scanner blind spot and fixed the milestone's worst measured defect, BadgeModal.vue's Legendary badge at 1.32:1 dark mode; Phase 6 declared a 42-token per-hue-clamped --ink-safe-<hue>-<level> scale — not the flat scale § v4.36 rule 3 already rejected — migrated 50 call sites, and flipped expect(ALLOWLIST).toEqual([]) directly; allowlist arc 104 → 0) | Shipped | 2026-08-23 | 8 | 20/20 | Narrative · Audit |
| v4.40 — Plain-Surface Ink Sweep | Plain-Surface Ink Sweep (enforces DESIGN.md § v4.37 Plain-Surface Ink Floor, OBJ-2668 — every declared hue fails WCAG AA as raw plain-surface ink with no tint involved, worst case 1.62:1; Phase 1 built plainSurfaceInkGuard.spec.ts tag-aware across line breaks, since 18 of 131 hue-bearing <AppIcon> tags span lines and the existing tint guard's same-line matcher can't follow them, correcting the kickoff hand-count of 425 sites to a guard-measured 362 and retiring COACH_GOLD_ALLOWLIST; Phases 2–5 swept four guard-generated directory batches (59/69/68/81 sites), with Phase 2 settling the milestone's one design judgment — a wall of -accessible ink reads muted only in light mode, judged acceptable — before the mechanical batches ran; Phase 6 swept Storybook stories + admin_dashboard/src and flipped the completion gate to a direct expect(ALLOWLIST).toEqual([]) assertion; independently re-verified at milestone close by actually re-running the guard's test suite, 72/72 passing) | Shipped | 2026-08-19 | 6 | 7/7 | Narrative · Audit |
| v4.39 — Mutation Re-Entry Guard Sweep | Mutation Re-Entry Guard Sweep (replaces v4.37 Phase 3's unreproducible "26 unguarded mutation call sites" figure with a committed, re-runnable census script and a fully-triaged inventory; fixes 34 confirmed sites — including two shared-in-flight-flag cross-blocking traps, useCommunity.ts and MeetCoach.vue, split into per-action refs — plus a related useWhatsNew.ts epoch-seed re-entry fix whose own round-1 attempt shipped the same bug class, caught in review; adds a CI recurrence gate over a committed 6-site baseline (not yet a required check, OBJ-2708) and a live raw-dispatch-probe verification harness; promoted to master via PR #2466, a redo of PR #2463 which had squash-merged in error) | Shipped | 2026-08-19 | 7 | 6/7 | Narrative · Audit |
| v4.38 — Clerk Auth-Config Integrity | Clerk Auth-Config Integrity (restores production Clerk username.required/password.required after an out-of-band dashboard flip on 2026-08-15 traded away web username enforcement for no working fix to native Google OAuth's missing_requirements dead-end; fixes both production and staging, which the kickoff had wrongly assumed already agreed; ships the ninth *-drift* guard in this repo and the first covering the auth provider, which caught both the original incident and a second, unrelated out-of-band change live during the milestone's own run; and closes with a live-traced finding — not an assumption — that the one exposed production account signs in normally on both web and native, so the milestone's net user impact is zero) | Shipped | 2026-08-19 | 5 | 5/5 | Narrative · Audit |
| v4.37 — Flow Integrity & Interstitial Arbitration | Flow Integrity & Interstitial Arbitration (closes two contract-vs-enforcement gaps from Desi's objectuve-throughline trace-only sweep, OBJ-2589 — a client could claim onboarding finished before the server confirmed it, DoneSlide.completeOnboarding() writing the completion flag before the mutation resolved with no rollback on failure; and the v4.15 one-interstitial-per-session policy was enforced by a hand-maintained v-if chain covering 6 of ~14 surfaces that had already drifted twice in five weeks, with none of the nine App.vue global overlays route-aware; fixed via write-after-confirm plus deferred reconcile (Phase 1) and a single registration-based useInterstitialCoordinator.ts with a route predicate and a census guard (Phase 2); three durability residuals closed (re-entry guard, retry-backed dismissals, seen-set timing) and two new test journeys registered, though journey live-run coverage was not obtained and is carried forward to OBJ-2595; promotion to master (PR #2380) verified by content, not the file-presence script alone, since two of five phases only edited existing files) | Shipped | 2026-08-16 | 6 | 9 | Narrative · Audit |
| v4.36 — Tint-Ink Contrast Floor | Tint-Ink Contrast Floor (ends the same-hue-ink-on-same-hue-tint defect class after three one-at-a-time fixes — OBJ-1951, OBJ-2047 closed as a no-op, OBJ-2056 — by measuring the whole surface once across hue × alpha × mode × theme × surface instead of re-deriving a fix per site; kickoff census found 109 defects across 66 files, 3.6× the stale estimate, plus a previously-unnamed class, text-destructive at 1.77:1 in dark mode; grew from 5 to 7 phases across 3 respecs — Phase 3 split into 3a/3b when a --card-only measurement proved false over --background, Phase 6 added for coach/gold (no accessible ink token existed for either), Phase 7 added the day it shipped after Desi's own blindspot script found --rarity-epic byte-identical to --coach-interactive; promotion to master (PR #2304) required hand-resolving a contrast-critical conflict, keeping master's independently-shipped OBJ-2425 --primary-accessible values over this milestone's own slightly-less-accessible ones; a guard per-line-scan blind spot found after ship is tracked as follow-up, OBJ-2472) | Shipped | 2026-08-11 | 7 | 6 | Narrative · Audit |
| v4.35 — Teams V1.1 — Sub-communities | Teams V1.1 — Sub-communities (pays off the four sub-community-surface stubs v4.19 Phase 4 honestly gated rather than built; collapsed from a planned 3 phases to 1 after a mid-milestone census found three of the four source tickets — OBJ-1822, OBJ-1823, OBJ-1824 — had already shipped independently via PRs #2201/#2207/#2208, two of them before this milestone's own kickoff was written; ships the room feed (OBJ-1825) via an additive team-room mode on the existing /communities/:publicId route, reusing the whole feed/comment/reaction/moderation stack rather than building a parallel view; close-out reconciled a semantic conflict in TeamSubCommunitiesTab.vue's roomMenuButtons computed between Phase 1's changes and master's independently-shipped work before promoting via OBJ-2353) | Shipped | 2026-08-09 | 1 | 5 | Narrative · Audit |
| v4.33 — Primary Ink Adaptive Swap | Primary Ink Adaptive Swap (hardcoded text-white swapped for the adaptive text-primary-foreground on 41 --primary-family fill sites across admin_dashboard and ionic_frontend — closes the consumer-layer half of a defect v4.29/v4.31 already fixed at the token layer; two source-scan guards added, one a same-attribute regex, one a vue/compiler-sfc AST walk after the regex was shown to miss 10 of 21 sites; Phase 3's measurement disproved the milestone's own "no token changes" premise for 9 of 12 category-cover/tone-chip gradients, producing 12 new mode-matched token pairs instead of a swap; promoted to master via PR #2213) | Shipped | 2026-08-08 | 3 | 9 | Narrative · Audit |
| v4.32 — Marketing Landing Rebuild | Marketing Landing Rebuild (two Claude-generated design canvases with zero class names — 500 + 215 inline style= attrs — mapped onto landing-2026.css's 10-page shared stylesheet via a Desi UI-SPEC per design-bearing phase; shared header/nav/motion system across index.html/meet-coach.html; the site's first real prefers-reduced-motion contract, 16 effects; both design phases found the canvases overstated the delta — 7/9 landing sections and 126/129 Meet Coach nodes already copy-identical to master; three live WCAG AA failures found and fixed; 29-entry contrast allowlist retired outright; new referenced-but-undefined CI guard closes the defect class OBJ-2227 shipped ahead of this milestone; zero class renames; promoted to master via PR #2202) | Shipped | 2026-08-08 | 4 | 11 | Narrative · Audit |
| v4.31 — Gradient Primary Dark-Mode Redesign | Gradient Primary Dark-Mode Redesign (--gradient-primary/--primary-light/--primary-glow had no dark-mode declaration anywhere; Desi's Phase 1 real-browser check disproved the milestone's own founding premise — 9 of 10 supporter themes silently served their own light-mode gradient in dark mode, not :root's blue, and the ad-hoc from-primary to-primary-light pair collapsed to a flat fill in all 10 themes; fixed via a per-theme anchor-and-travel mechanism plus a new worst-stop static guard and real-browser Cypress proof; promoted to master via PR #2182; --gradient-accent and hardcoded text-white-on-bg-primary carved out as OBJ-2257/OBJ-2266) | Shipped (tech debt) | 2026-08-08 | 5 | 0 | Narrative · Audit |
| v4.30 — Editorial Community Curation | Editorial Community Curation (admin-gated editorial slot system for the Communities discovery surface — three named rails with ordinal position, an admin curation screen, and the consumer rails behind PostHog flag editorial-discovery; salvaged from Phase 79 of the abandoned gsd/v1.18-pre-launch-readiness branch, ported additively so master's live recommended_communities/community_suggestions/trending_communities stayed untouched; also gives is_featured its first-ever write path; promoted to master via PR #2170) | Shipped | 2026-08-07 | 3 | 14 | Narrative · Audit |
| v4.28 — Mobile Settings & Coaching Refresh | Mobile Settings & Coaching Refresh (mobile-only /settings rebuilt as a hub of priority tiles pushing ?tab= sub-pages on a shared row grammar, retiring the icon-only tab strip below lg; Coaching becomes a one-at-a-time accordion; themes/dashboard-mode/widget-row relocated to a new App & appearance destination; two honestly-disabled affordances, search pill and 2 of 4 streak metaphors; all 5 phases promoted to master via PR #2047 (OBJ-2089); the design-token conflict with the independently-shipped OBJ-2044 was resolved by Codi's reconciliation merge ahead of promotion) | Shipped | 2026-08-03 | 5 | 0 | Narrative · Audit |
| v4.29 — Primary Foreground Contrast Remediation | Primary Foreground Contrast Remediation (every --primary/--primary-foreground and --accent/--accent-foreground pair brought to WCAG AA 4.5:1 in both modes across all 10 themes, plus a static + real-browser contrast guard master never had; discovered mid-milestone that a separately-numbered milestone, v4.26 Light-Mode Contrast Floor, had independently shipped the same token values first, so v4.29 reconciled onto v4.26's values and shipped on its guard suite, consumer audit, and two new token families instead; the reconciliation merge also promoted the milestone to master ahead of its own docs, and silently reverted one Phase 2 consumer fix — caught and re-applied as OBJ-2086) | Shipped | 2026-08-03 | 5 | 11 | Narrative · Audit |
| v4.25 — Release-Build Safety Gates | Release-Build Safety Gates (three new CI boot-smoke gates — cap sync drift, Android minified-release boot, iOS Release boot + a separate plugin-registration check — closing the gap that let the OBJ-1899 release-only WorkManager startup crash ship undetected; the iOS registration check caught and fixed a real live bug, WidgetBridgePlugin compiled but never registered; retroactively closed under OBJ-2159 after OBJ-2150's ledger reconciliation found its close artifacts missing) | Shipped | 2026-07-29 | 4 | 4 | Narrative · Audit |
| v4.14 — Activity Nexus — Connected Apps | Activity Nexus — Connected Apps (Strava + Chess.com) (reusable integration framework + two live providers auto-checking matching habits via a confidence-scored, mandatory-first-review mapping engine; all 6 phases code-complete 2026-07-25 but stranded on an unmerged integration branch for a week; promotion to master took three attempts — attempt 1 broke the deploy pipeline (validate-secrets.sh never runs on pull_request), attempt 2 passed every check and still shipped a live NewHabitToast crash ~56 min later (non-throwing JSON.parse("null")), attempt 3 held clean through a 32-minute Sentry watch window; merge-only ship, connected_apps_enabled flag stays at 0% pending Josh's Strava API provisioning) | Shipped | 2026-08-03 | 6 | 0 | PRD · Narrative |
| v4.26 — Light-Mode Contrast Floor | Light-Mode Contrast Floor (WCAG AA on the primary CTA gradient, the app-wide focus indicator, the celebration card, and accent ink both as fill-ink and as page-ink, across all 10 supporter-theme presets; reordered so a preset AA clamp lands first since 8/10 presets failed a plain solid CTA and 2/10 failed the focus-ring floor even at full opacity; two mid-milestone additions from Desi's accent-ink findings; six hard rules recorded in DESIGN.md; promoted to master via PR #1995) | Shipped | 2026-08-02 | 6 | 12 | Narrative · Audit |
| v4.27 — Hallmark Design-Debt Remediation | Hallmark Design-Debt Remediation (closes design debt from Desi's 70-gate objectuve-hallmark audit across 59 view surfaces — WCAG AA contrast + tap-target fixes, the third recurrence of the OBJ-1711 query-state-fabrication bug closed with a mechanical ESLint guard, a converged .selectable-card recipe, a real blanket reduced-motion rule; teams/** pulled out mid-milestone to a gated fast-follow, shipped separately; promoted to master via PR #1987 after the Phase 2 visual-evidence hard gate cleared and a fresh alpha-modifier regression was caught and fixed) | Shipped | 2026-08-02 | 5 | 0 | Narrative · Audit |
| v4.26 — Help Site Design Overhaul | Help Site Design Overhaul (rebuilds guide_site/'s presentation layer on design direction 1b, "the live simulator" — home becomes a live phone-frame demonstration of the app driven by six mechanic rows instead of an article index; every article page gains a sticky "In the app" preview rail that swaps screenshots as you scroll; new grace-day streak simulator verified against the server's actual grace-budget math across all 16,384 fourteen-day patterns; 19 markdown content pages kept their prose; recurring pin-placement risk surfaced under three distinct root causes across three phases, caught each time by verify-against-render rather than verify-against-number) | Shipped (tech debt) | 2026-08-01 | 8 | 8 | Narrative · Audit |
| v4.24 — Dependency Convergence & Upgrade | Dependency Convergence & Upgrade (Ruby 4.0.6, Rails 8.1.3.1, Node 24, and the Vue toolchain converged across all 7 monorepo packages onto one shared version matrix; per-major cost-benefit gate — vue-router 4→5 and TypeScript 5→6 POSITIVE, Vite 7→8 NEGATIVE — kept ionic_frontend's partial convergence deliberate, not silently skipped; 5 phases shipped in ~24h with zero rollbacks) | Shipped (tech debt) | 2026-07-30 | 5 | 10 | Narrative · Audit |
| v4.23 — Guideline 1.2 User Blocking | Guideline 1.2 User Blocking (closes the App Store Guideline 1.2 Safety gap — block is now a first-class safety primitive: symmetric content filtering across every read path via a UserAlly-derived blocked-id set, Block beside Report on all 4 point-of-abuse surfaces via a shared BlockConfirmSheet, reversible from Settings → Privacy → Blocked; no schema migration) | Shipped (tech debt) | 2026-07-30 | 4 | 3 | Narrative · Audit |
| v4.22 — Widget Background Check-In Sync | Widget Background Check-In Sync (zero-app-open background delivery of widget habit check-ins to /graphql across backend + frontend + Android WorkManager + iOS BGTaskScheduler; decision gate rejected a Capacitor background-runner option and locked a durable device-scoped CheckinToken — DB-backed, ~90-day TTL, rotate-on-use, Josh sign-off; tap-time-primary + scheduler-retry-only on both platforms; Android fully-closed delivery proven on real hardware, iOS scheduler-retry live-fire accepted as an unverified, monitored risk) | Shipped (tech debt) | 2026-07-29 | 5 | 5 | Narrative · Audit |
| v4.21 — First-Class User Guide + Marketing Refresh | First-Class User Guide + Marketing Refresh (standalone public guide_site/ VitePress site at help.objectuve.com, decoupled from the staff-gated docs.objectuve.com, with real Teams walkthrough content captured against the shipped v4.19 UI; retroactive audit corrects the milestone's own inaccurate phase-status record — Phase 3's cited SHA was never a master ancestor though its content landed via a later commit, and Phase 4 was marked BACKLOG despite actually shipping; retroactively closed under OBJ-2159) | Shipped (tech debt) | 2026-07-28 | 4 | 9 | Narrative · Audit |
| v4.19 — Teams V1 Wiring Completion | Teams V1 Wiring Completion (finishes wiring Teams V1 GA surfaces that silently no-op'd — seat-cap "Add seats" + grace resubscribe billing dead-ends, in-app collective-goal creation, sub-community join/leave/switch + multi-room onboarding, fresh-member CTA + honest gating of all 8 remaining V1.1 stubs; merged to master via promotion PR #1956 (OBJ-2012)) | Shipped | 2026-07-28 | 4 | 6 | Narrative · Audit |
| v4.18 — Iconography System | Iconography System (tiered-hybrid icon system — central <AppIcon> facade over Lucide/ionicons/custom SVG-Vue, 9 pilot custom identity glyphs, design-system decoupling, docs; Option B confirmed by Josh 2026-07-26; all 4 phases merged directly to master) | Shipped (tech debt) | 2026-07-27 | 4 | 5 | Narrative · Audit |
| v4.16 — Guided Product Tour | Guided Product Tour (reusable FeatureTour engine — @floating-ui/dom-positioned spotlight/coach-mark overlay, server-authoritative UserDetail.data['feature_tours'] completion state, no migration; flagship first-run dashboard tour; full per-surface coverage on Goals/Coach/Communities/Achievements/Feed + Settings replay; re-engagement "What's New" spotlight + admin-only completion funnel; every tour skippable/replayable/non-blocking; near-miss: Phase 1 planning docs briefly stranded on a deleted branch, recovered from a dangling commit before real loss) | Shipped | 2026-07-27 | 3 | 14 | Narrative · Audit |
| v4.17 — Design System Facelift | Design System Facelift (brings the design_system app up to the admin_dashboard polish bar — new glass/elevation/motion vocabulary, BrandOverview real iconography, live-preview Components gallery, all 8 foundation pages lifted, search/filter, real DarkMode swatches; tokens.css/tailwind-tokens.cjs guardrail held throughout; frontend-only, no migration/GraphQL/mobile changes) | Shipped | 2026-07-26 | 4 | 6 | Narrative · Audit |
| v4.15 — Dashboard Hierarchy — Standard & Detailed | Dashboard Hierarchy — Standard & Detailed (replaces the 1,570-line populated-dashboard branch with one hierarchy at two densities — lean Standard default, inline-expandable Detailed; Focus card stack untouched; server-persisted density preference; habit-goal 0% metric fixed; Social/Achievements relocated with discovery hints; five phases shipped on the integration branch 2026-07-24–25, but the branch itself sat unmerged with its flag at 100% rollout for five days until a same-day hotfix landed it — a new CI guard now catches that stranded-branch pattern) | Shipped (tech debt) | 2026-07-30 | 5 | 9 | Narrative |
| v4.15 — Periodic Load Testing | Periodic Load Testing (adopts k6 OSS for staging-only load testing — 5 scripts covering goal-event writes, community/goal reads, sync-user throughput, the AI Workforce webhook, and /health; monthly cron + manual dispatch posts p95/error-rate summaries; GCS baseline storage with a non-blocking >20% regression flag, advisory only, never a deploy gate; Phase 4 blocking gate deferred pending 3+ monthly baselines; distinct milestone from v4.15 Dashboard Hierarchy above — version collision, always use the full slug; retroactively closed under OBJ-2159) | Shipped (tech debt) | 2026-07-24 | 3 | 6 | Narrative · Audit |
| v4.13 — Notification History | Notification History (standalone, date-grouped /notifications history page reviewing full acknowledged + unacknowledged notification history, deliberately kept separate from the unified /feed; also fixed a latent bug where deleteNotification was wired to the acknowledge mutation instead of the real delete mutation; the milestone's own ROADMAP file was never updated past its kickoff status — corrected retroactively under OBJ-2159) | Shipped (tech debt) | 2026-07-30 | 2 | 6 | Narrative · Audit |
| v4.12 — Zip-Style Critical Path | Zip-Style Critical Path (replaces Critical Path's daily-puzzle mechanic — Pipes rotate-to-connect — with a Zip-style Hamiltonian-path puzzle: draw one line through numbered checkpoints in order, fill every cell, respect wall barriers; frontend-only, backend untouched; Hint deferred; code-complete on the milestone integration branch, not yet merged to master — no user has played it yet) | Shipped (tech debt) | 2026-07-23 | 3 | 7 | Narrative · Audit |
| v4.11 — Kindling Widgets: Android Parity | Kindling Widgets: Android Parity (ports the v4.7 iOS Kindling refinement — stone-tower streak, earned Coach line, tap-to-check-off — to Android across Small/Medium/Large-equivalent sizes; merged to master via a separate integration PR after 21 commits of drift, staging-confirmed green; kindling_widget_enabled still 0% rollout on both platforms, no production tag yet) | Shipped | 2026-07-21 | 5 | 16 | Narrative · Audit |
| v4.10 — Accountability Partner Goal Sharing | Accountability Partner Goal Sharing (per-goal shared_with_partner opt-in, independent of a goal's public/private setting; unified Goal.partner_visible read-time scope shared by the public profile and the missed-day alert job; rejected an initial draft that leaked all private goals to any confirmed partner) | Shipped | 2026-07-21 | 3 | 8 | Narrative · Audit |
| v4.8 — AI Workforce Ops Board | AI Workforce Ops Board (replaces the agent-card grid + standalone Review Queue with a single Live Ops Board command center + Focus Detail overlay, over a new work-item view-model; new claimAiArtifact hand-off mutation; caused a cross-milestone regression in v4.9's Facebook review UI, resolved same-day) | Shipped | 2026-07-20 | 6 | 1 | Narrative · Audit |
| v4.7 — Kindling Widgets (iOS) | Kindling Widgets, iOS (refined the iOS home-screen widget to design direction "Kindling: feel it and do it" — stone-tower streak, one earned Coach line, tappable App-Intents check-off across Small/Medium/Large plus three Lock Screen accessory families, gated behind kindling_widget_enabled (0% rollout); shipped via 6 flag-gated phase PRs direct to master; open tech debt — the interactive check-off's tap→cold-kill→foreground path was verified only by code-path re-derivation + CI, no iOS device in-env; retroactively closed under OBJ-2159) | Shipped (tech debt) | 2026-07-20 | 6 | 14 | Narrative · Audit |
| v4.9 — Facebook Social Publishing (Remy) | Facebook Social Publishing (Remy) (Buffer link-preview posts for Remy's social_post artifacts; fixed a pre-existing X/LinkedIn silent delivery no-op along the way; two open follow-ups — the new 1200×630 preview card isn't wired into marketing_landing/index.html yet, and the admin review UI was unintentionally deleted by an unrelated PR) | Shipped (tech debt) | 2026-07-20 | 6 | 9 | PRD · Narrative · Audit |
| v4.6 — Intelligence & Analytics | Intelligence & Analytics (personal /analytics dashboard, mood↔goal + pace AI insights, goal-discovery quiz, admin feedback AI summary, learned notification timing, analytics instrumentation — 6 per-feature flags, all 0% rollout) | Shipped | 2026-07-20 | 5 | 28 | Narrative · Audit |
| v4.5 — Runtime Least-Privilege | Runtime Least-Privilege (moved every Cloud Run workload + the preview-db VM off the over-privileged default compute SA onto 9 dedicated least-privilege identities, then stripped roles/editor/firebase.admin/secretAccessor from it; new CI guard prevents regression) | Shipped | 2026-07-18 | 5 | 27 | Narrative · Audit |
| v4.0 — Teams V1 | Teams V1 (paid, private, multi-community workspace — billing, invites, sub-communities, leaderboards, collective goals; first B2B revenue stream) | Shipped | 2026-07-15 | 9 | 69 | PRD · Narrative · Audit |
| v4.2 — Reactive Streak Widget | Reactive Streak Widget (same-day celebratory/encouraging state, iOS + Android, flame + stones metaphors — shipped via an independent PR track after the planned integration branch was abandoned; see narrative) | Shipped | 2026-07-12 | 3 | 12 | Narrative · Audit |
| v4.3 — Keystone Architecture Sweep | Keystone Architecture Sweep (report-only objectuve-keystone audit across all 14 registry domains, 56 gates each; 9 domain reports + one consolidated triage index with an 18-item fix-before-ship shortlist; phases complete 2026-07-10, but the integration branch sat stranded — unmerged — until this milestone-close pass (2026-08-04) reconciled every report against its own fix milestone's real outcome and promoted the branch to master directly via PR #2110, merged by Josh — not the normal Riley hand-off) | Shipped | 2026-08-04 | 9 | 9 | Narrative · Findings index |
| v4.4 — Keystone Findings Remediation | Keystone Findings Remediation (v4.3 sweep fix-before-ship shortlist — atomicity, idempotency, dedup, registry fixes) | Shipped | 2026-07-11 | 16 | 16 | Narrative |
| v4.4 — Preview Smoke Lane Isolation | Preview Smoke Lane Isolation (per-PR smoke accounts + concurrency lanes) | Shipped | 2026-07-10 | 4 | 11 | Narrative · Audit |
| v4.1 — Engagement & Retention | Engagement & Retention (Micro-Journal, Privacy Controls, Onboarding Pledge, Home Widgets) | Shipped | 2026-07-08 | 4 | 23 | Narrative · Audit |
| v3.12 — Identity-Anchored Goal Journey | Identity-Anchored Goal Journey (PRs #1243/#1260/#1289) | Shipped | 2026-07-06 | 3 | 3 | Narrative · Audit |
| v1.23 — Coach Message Trigger Redesign | Coach Message Trigger Redesign | Shipped | 2026-06-16 | 5 | 7 | Narrative |
| v3.11.25 — Hallmark Pre-Beta Design Remediation | Hallmark Pre-Beta Design Remediation (PRs #1101/#1102/#1103) | Shipped | 2026-06-08 | 5 | 8 | Narrative · Audit |
| v3.11 — Goal Flow & App Polish Batch | Goal Flow & App Polish Batch (PRs #1077–#1083) | Shipped | 2026-06-04 | 7 | — | Narrative |
| v2.5 — Documentation Audit & Refresh | Documentation Audit & Refresh | Shipped | 2026-05-22 | 13 | 19 | Narrative |
| v2.3 — Partner Invite Deep Link | Partner Invite Deep Link | Shipped | 2026-05-22 | 4 | 4 | Narrative |
| v2.0 — Ally Social Graph Write | Ally Social Graph Write | Shipped | 2026-05-17 | 5 | 7 | Narrative |
| v1.22 — Weekly Digest Email | Weekly Digest Email — Complete Delivery | Shipped | 2026-05-17 | 1 | 8 | Narrative · Audit |
| v1.21 — Goal Template Library | Goal Template Library — Curated Seed | Shipped | 2026-05-15 | 5 | 14 | Narrative · Audit |
| v1.19 — Critical Path: Full Product | Daily Puzzle Graduation | Shipped | 2026-05-15 | 7 | 10 | Narrative · Audit |
| v1.18 — Enneagram Coach | Enneagram Assessment for Coach Personalization | Shipped | 2026-05-14 | 5 | 14 | Narrative · Audit |
| v1.16 — Community Cold-Start | Community Cold-Start | Shipped | 2026-05-13 | 4 | 26 | Narrative |
| v1.15 — PWA Augment | PWA Augment | Shipped | 2026-05-12 | 3 | — | Narrative · Audit |
| v1.14 — Coach Surfaces | Coach Surfaces, Always Valuable | Shipped | 2026-05-11 | 5 | 8 | Narrative · Audit |
| v1.12 — Architecture Health | Architecture Health | Shipped | 2026-05-03 | 6 | 18 | Narrative · Audit |
| v1.11 — Streak Compassion | Streak Compassion & Welcome Back | Shipped | 2026-04-30 | 4 | — | Narrative |
| v3.9 — App Visual Overhaul | App Visual Overhaul | Shipped | 2026-04-30 | 12 | — | Narrative |
| v1.10 — Onboarding | Onboarding Overhaul | Shipped | 2026-04-29 | 6 | 28 | Narrative |
| v1.10 — Visual | Visual Evolution | Shipped | 2026-04-27 | 11 | — | Narrative |
| v1.8 | Onboarding Wizard Overhaul | Shipped | 2026-04-18 | 6 | 32 | Audit |
| v1.7 | Admin Evolution | Shipped | 2026-04-18 | 6 | — | PRD |
| v1.6 | Audit Remediation | Shipped | 2026-04-16 | 5 | 31 | — |
| v1.5 | DDD Phase 2 — Domain Events | Shipped | 2026-04-15 | 4 | 32 | PRD |
| v1.4 | AI Workforce | Shipped | 2026-04-13 | 4 | 45 | PRD · Audit |
| v1.3 | Admin Dashboard | Shipped | 2026-04-12 | — | — | PRD |
| v1.2 | Meet Coach — World-Class Coaching Personalization | Shipped | 2026-04-11 | 5 | ~50 | PRD |
| v1.1 | Auth & Authorization Remediation | Shipped | 2026-04-10 | 5 | 54 | PRD · Audit |
| v1.0 | Dedicated AI Service | Shipped | 2026-04-10 | 4 | — | PRD |
Active phase post-v1.8: Phase 38 (Supporter & Revenue Analytics) is in flight on the post-v1.8 ROADMAP — admin Revenue tab with MRR tiles + theme-aware Doughnut chart.
Artifact structure (per milestone)
Every milestone has the same underlying planning trail on GitHub under .planning/milestones/:
.planning/milestones/
├── v1.N-ROADMAP.md Goal, phase breakdown, success criteria per phase
├── v1.N-REQUIREMENTS.md Full requirements list keyed by category prefix
├── v1.N-MILESTONE-AUDIT.md Post-ship audit: coverage, integration, tech debt
└── v1.N-phases/
└── NN-phase-name/
├── NN-NN-PLAN.md Per-plan execution plan
├── NN-NN-SUMMARY.md Per-plan what-shipped summary
├── NN-CONTEXT.md Phase context + dependencies
├── NN-RESEARCH.md Upfront research
├── NN-VERIFICATION.md Post-execution verification
├── NN-REVIEW.md Code review findings
└── NN-VALIDATION.md Acceptance criteria checklistMilestone pages here summarize and link back to these artifacts on GitHub, so the full record is always a click away.
Known gaps
- v1.0 has no
MILESTONE-AUDIT.md. The milestone predates the audit discipline; its phase-level artifacts underv1.0-phases/are complete. - v1.3 was shipped before the
.planning/milestones/convention stabilised — the PR (#312) merged the Admin Dashboard work, but no standalone roadmap, requirements, or audit file lives under.planning/milestones/v1.3-*. - v1.4 has an audit and a roadmap but the
v1.4-phases/directory was consolidated post-ship — phase artifacts are folded into the audit.
Adding a new milestone
When a new milestone starts or ships:
- Copy
TEMPLATE.mdtodocs/milestones/v1.N-slug.md. - Fill in the frontmatter and pull narrative content from
.planning/milestones/v1.N-*. - Add a row to the Milestones table above.
- Add the milestone link to the
Project Historysidebar section indocs_site/.vitepress/config.ts. - Commit and push — the Docs Deployment workflow picks up changes under
docs/**and redeploys.
Last updated: 2026-09-20 (v4.66 — Bound-Class Guard Reach Audit link added)