{
  "board": {
    "repo": {
      "owner": "deepstation",
      "name": "vantagepost",
      "base": "release/v0.1.7",
      "prod": "main"
    },
    "items": {
      "RMD-R0": {
        "id": "RMD-R0",
        "code": "R0",
        "wave": 0,
        "order": 0,
        "title": "Merge main's hotfixes back into release/v0.1.7",
        "issues": [],
        "rootCause": "main has hotfixes release/v0.1.7 lacks (VP-1231 wallet banners #638, X work #634/#635, Facebook Page posting, token logging). Shipping v0.1.7 without them drops them.",
        "fix": "Open a PR merging origin/main into release/v0.1.7, resolve conflicts keeping both sides' fixes, and get CI green. Done when GitHub shows main has 0 commits that release lacks.",
        "size": "M",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": "Auto-detected: the dashboard reads the main→release gap live from GitHub.",
        "kind": "blocker",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1251-merge-mains-hotfixes-back-into-releasev017-so-the-release",
        "ticket": "VP-1251",
        "pr": {
          "number": 648,
          "url": "https://github.com/deepstation/vantagepost/pull/648",
          "title": "Merge main's production hotfixes into release/v0.1.7 (VP-1251)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1251-merge-mains-hotfixes-back-into-releasev017-so-the-release",
          "sha": "d71ddea1e9cd0679011599132c8e870da7c39b3b",
          "ci": "none",
          "updatedAt": "2026-10-20T01:38:17Z"
        },
        "note": "review blocker B1 fixed: eecaa939 + 1a488210 pushed to PR #648; tsc 0, x-gate 7/7, related 18 suites pass",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792460307962,
        "deferred": null
      },
      "RMD-A1": {
        "id": "RMD-A1",
        "code": "A1",
        "wave": 1,
        "order": 1,
        "title": "Fact-check gate",
        "issues": [
          56,
          57
        ],
        "rootCause": "The fact check only reports. A flagged stat is a warning, the route always sets Complete, and social generation never sees the flags.",
        "fix": "Add a \"Needs review\" state while flagged claims remain, offer one-click fixes, and pass flagged claims to social as off-limits.",
        "size": "M",
        "tags": [],
        "deps": [
          "RMD-B1"
        ],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1257-bug-articles-with-made-up-statistics-still-show-as-complete",
        "ticket": "VP-1257",
        "pr": {
          "number": 690,
          "url": "https://github.com/deepstation/vantagepost/pull/690",
          "title": "Show Needs review when the fact check flags claims, offer Fix flagged claims, and keep flagged claims out of social posts (VP-1257)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1257-bug-articles-with-made-up-statistics-still-show-as-complete",
          "sha": "2790076e0ca155c4717b36b64bfb89a481c1bf26",
          "ci": "none",
          "updatedAt": "2026-10-20T12:00:14Z"
        },
        "note": "merged #690 (09c258d1) into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497619571,
        "deferred": null
      },
      "RMD-A2": {
        "id": "RMD-A2",
        "code": "A2",
        "wave": 1,
        "order": 2,
        "title": "Story templates without invented stories",
        "issues": [
          22
        ],
        "rootCause": "Story templates ask for a real moment but have no fallback, and the example is a first-person company anecdote. The legacy LinkedIn path has no rule at all.",
        "fix": "Fall back to a \"Picture…\" scene or placeholder when the source has no story; replace the example; add the rule to the legacy path. Presets change only in lib/prompt-templates/system-presets.ts + the seed script.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
        "ticket": "VP-1261",
        "pr": {
          "number": 651,
          "url": "https://github.com/deepstation/vantagepost/pull/651",
          "title": "Stop story post templates from inventing company anecdotes (VP-1261)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
          "sha": "1d048463b9b37859b6b7d06205047cec8ef9c055",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:59Z"
        },
        "note": "PR #651 open; done pending review/merge. Seed to run after merge.",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-B1": {
        "id": "RMD-B1",
        "code": "B1",
        "wave": 1,
        "order": 3,
        "title": "Fact-check link matching and labels",
        "issues": [
          12,
          77
        ],
        "rootCause": "The fact check matches URLs by exact text while the app uses loose matching (linkKey). The re-run route leaves out the org's own sources. 403s count as broken, and the headline ignores warnings.",
        "fix": "Use the shared link matcher, pass every source to the re-run, count only 404/410 as broken, and include warnings in the headline count.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1255-bug-the-fact-check-calls-the-articles-own-sources-not",
        "ticket": "VP-1255",
        "pr": {
          "number": 650,
          "url": "https://github.com/deepstation/vantagepost/pull/650",
          "title": "Match fact-check links to their sources, count 403s as unverified, and show warnings in the headline (VP-1255)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1255-bug-the-fact-check-calls-the-articles-own-sources-not",
          "sha": "0e83d6a1fc189cee57e5ec6674dc805ac76dde0c",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:52Z"
        },
        "note": "PR #650 open into release/v0.1.7; review clean; lease released",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-B4": {
        "id": "RMD-B4",
        "code": "B4",
        "wave": 1,
        "order": 4,
        "title": "Knowledge indexing",
        "issues": [
          41
        ],
        "rootCause": "Onboarding's Business Overview and Website Content are saved by createContextEntry without indexing, and column defaults mark them ready with 0 chunks.",
        "fix": "Index them on save; show \"Not indexed\" instead of READY; repair existing rows with a one-off script in scripts/ (no raw SQL).",
        "size": "M",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1264-bug-the-knowledge-library-shows-the-website-and-business",
        "ticket": "VP-1264",
        "pr": {
          "number": 653,
          "url": "https://github.com/deepstation/vantagepost/pull/653",
          "title": "Index the onboarding website and show unindexed library entries as Not indexed (VP-1264)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1264-bug-the-knowledge-library-shows-the-website-and-business",
          "sha": "1267fea5065aebcc62a1807d5c0c42fb8d37e55a",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:06Z"
        },
        "note": "PR #653 open; awaiting Micah review/merge, then run repair script",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-C1": {
        "id": "RMD-C1",
        "code": "C1",
        "wave": 1,
        "order": 5,
        "title": "Wallet accounting",
        "issues": [
          10,
          24
        ],
        "rootCause": "Debits have no floor, Team credits expire with no refresh, each Billing tile uses its own formula, and there's no per-action log (Team wallets record none).",
        "fix": "A debit that checks the balance first and never goes below $0 (DEC-4), one balance formula for every display, and a usage log on Billing.",
        "size": "M",
        "tags": [
          "migration"
        ],
        "deps": [],
        "decisions": [
          "DEC-4"
        ],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1268-bug-wallet-balances-go-below-0-the-billing-tiles-disagree",
        "ticket": "VP-1268",
        "pr": {
          "number": 657,
          "url": "https://github.com/deepstation/vantagepost/pull/657",
          "title": "Stop wallets at $0, make the Billing tiles agree, and show what each action cost (VP-1268)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1268-bug-wallet-balances-go-below-0-the-billing-tiles-disagree",
          "sha": "7e48fc317c9e967662c31c72c15934d38736ba1c",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:23Z"
        },
        "note": "PR #657 open; awaiting CI and Micah",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-C3": {
        "id": "RMD-C3",
        "code": "C3",
        "wave": 1,
        "order": 6,
        "title": "Signed links for draft images",
        "issues": [
          20
        ],
        "rootCause": "Draft images get public links that never expire, under paths containing the org ID (getPublicUrl, lib/storage/s3.ts).",
        "fix": "Signed, expiring links for drafts, long enough for Instagram and LinkedIn to fetch at publish time. Also check whether the bucket can be listed.",
        "size": "M",
        "tags": [
          "security"
        ],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
        "ticket": "VP-1270",
        "pr": {
          "number": 652,
          "url": "https://github.com/deepstation/vantagepost/pull/652",
          "title": "Keep draft social images private and show them by signed links that expire (VP-1270)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
          "sha": "d930de8c7875f6ea541149b879703981f09a46e6",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:11Z"
        },
        "note": "PR #652 rebased, mergeable; waiting on Micah. Before merge: S14 bucket check.",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530,
        "deferred": null
      },
      "RMD-C4": {
        "id": "RMD-C4",
        "code": "C4",
        "wave": 1,
        "order": 7,
        "title": "Social statuses that tell the truth",
        "issues": [
          5,
          37,
          36,
          4
        ],
        "rootCause": "Generation status is shown as publish state, the dashboard calls every post \"scheduled\", Up next ignores dates, and the preview silently drops a network with no text.",
        "fix": "Base the badges and counts on publishStatus via lib/dashboard/social-badge.ts, mark past dates Overdue, and label empty networks instead of dropping them.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1274-bug-new-social-drafts-show-a-green-published-badge-the",
        "ticket": "VP-1274",
        "pr": {
          "number": 649,
          "url": "https://github.com/deepstation/vantagepost/pull/649",
          "title": "Show social posts by their publish state, mark past Up next items Overdue and keep empty networks on the draft card (VP-1274)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1274-bug-new-social-drafts-show-a-green-published-badge-the",
          "sha": "c95b64e57c173e59c8647dff1ae335fe48a8a573",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:45Z"
        },
        "note": "Merged release/v0.1.7 into #649 (c95b64e5); one conflict in ArticleSocialPostsTab.tsx resolved; tsc clean, 71 tests pass; PR mergeable CLEAN; awaiting Micah review",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-D1": {
        "id": "RMD-D1",
        "code": "D1",
        "wave": 1,
        "order": 8,
        "title": "Plan-aware banners and gates",
        "issues": [
          52,
          53,
          54,
          59,
          38
        ],
        "rootCause": "Free users are stored as \"active\", so the banners treat them as paid. The low-balance warning starts at $5 against a $2 grant. The keyword banner links to a paid-only page.",
        "fix": "Base banners on a real paid check, add a free-credits state, hide or label paid-only entry points, and fix the \"unlock publishing\" wording.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [],
        "notes": "R0 brings VP-1231 (wallet banners) into release; build on top of it.",
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1276-bug-free-accounts-get-paid-plan-banners-a-100-upsell-a-low",
        "ticket": "VP-1276",
        "pr": {
          "number": 680,
          "url": "https://github.com/deepstation/vantagepost/pull/680",
          "title": "Count a workspace member's own credits down instead of Low balance at $5 (VP-1291)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
          "sha": "26d6e57320c507c278e1bf2e0b4570dddcec9a07",
          "ci": "none",
          "updatedAt": "2026-10-20T11:36:01Z"
        },
        "note": "DEC-1 rewording pushed (756dc6f1); PR #654 ready for review",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496168307,
        "deferred": null
      },
      "RMD-D2": {
        "id": "RMD-D2",
        "code": "D2",
        "wave": 2,
        "order": 9,
        "title": "Paid plans only: remove \"free\" and fix the pricing copy",
        "issues": [
          32,
          48,
          49,
          33
        ],
        "rootCause": "The site promises \"Start free, no card\" but there is no Free plan, the onboarding free link is buried under paid cards, and \"roughly 10 articles for $100\" doesn't match what Engine v2 charges.",
        "fix": "Remove Free / Start free / No card from the homepage, pricing, signup and onboarding; signup goes straight to the paid plans (DEC-1). Keep the writing calls free and rewrite the article-cost copy to real costs (DEC-2).",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-D1"
        ],
        "decisions": [
          "DEC-1",
          "DEC-2"
        ],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": null,
        "ticket": "VP-1247",
        "pr": {
          "number": 687,
          "url": "https://github.com/deepstation/vantagepost/pull/687",
          "title": "Sell paid plans only and say what an article really costs (VP-1247)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1247-remove-free-from-the-site-and-onboarding-and-make-the",
          "sha": "012b56df31375f1b58281c9538c85f3b608803b9",
          "ci": "none",
          "updatedAt": "2026-10-20T11:49:26Z"
        },
        "note": "PR #687 squash-merged into release/v0.1.7 (228de1a6)",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496975523,
        "deferred": null
      },
      "RMD-C2": {
        "id": "RMD-C2",
        "code": "C2",
        "wave": 5,
        "order": 11,
        "title": "Later: variation default, outline fee, Enterprise list",
        "issues": [
          58,
          55,
          34
        ],
        "rootCause": "3 variations by default with no cost shown; the free first article's outline is charged; CMS is listed under both Creator and Enterprise.",
        "fix": "Parked by Micah on 2026-10-19 (DEC-3, DEC-5, DEC-7): no free plan for now, keep 3 variations, CMS stays on every plan. Revisit when Free or a trial comes back.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "deferred",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": null,
        "ticket": "VP-1272",
        "pr": null,
        "note": "ticket filed (parked, Backlog)",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792444542585,
        "deferred": "Parked by Micah on 2026-10-19; revisit when Free or a trial comes back."
      },
      "RMD-A3": {
        "id": "RMD-A3",
        "code": "A3",
        "wave": 2,
        "order": 12,
        "title": "Product status and per-piece product",
        "issues": [
          40,
          9
        ],
        "rootCause": "A product has no status and can't be chosen per piece; the writer gets every product with no URL, and the CTA falls back to the homepage.",
        "fix": "Add a product status (live, coming soon, past), promote only live products, add a product picker to the brief and composer, and use product URLs.",
        "size": "M",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1250-mark-each-product-as-live-coming-soon-or-past-and-pick-which",
        "ticket": "VP-1250",
        "pr": {
          "number": 658,
          "url": "https://github.com/deepstation/vantagepost/pull/658",
          "title": "Mark each product as live, coming soon or past, and pick which product each piece promotes (VP-1250)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1250-mark-each-product-as-live-coming-soon-or-past-and-pick-which",
          "sha": "4a6ca31bb84fc17069ecd69c14d270de3cdd0783",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:31Z"
        },
        "note": "PR #658 open; tsc 0; related tests green except pre-existing S17",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-F1": {
        "id": "RMD-F1",
        "code": "F1",
        "wave": 2,
        "order": 13,
        "title": "Title, meta title and pull quote",
        "issues": [
          1,
          16,
          13,
          7
        ],
        "rootCause": "No step enforces 70 characters on the title, the meta title is cut at a word, and the pull quote is placed in the body and then added again.",
        "fix": "Always propose a title under 70, warn before the paid step, cut the meta title at a clause or use the writer's own, and print the pull quote once.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1253-bug-article-titles-run-past-70-characters-the-meta-title-is",
        "ticket": "VP-1253",
        "pr": {
          "number": 661,
          "url": "https://github.com/deepstation/vantagepost/pull/661",
          "title": "Keep titles within 70 characters, cut the meta title at a phrase, and print the pull quote once (VP-1253)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1253-bug-article-titles-run-past-70-characters-the-meta-title-is",
          "sha": "372358d2f233d8ac12b7d96620c062baee67ebf5",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:56Z"
        },
        "note": "PR #661 open into release/v0.1.7; reviewed by a second agent, findings fixed; tsc 0; awaiting CI and Micah",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-F2": {
        "id": "RMD-F2",
        "code": "F2",
        "wave": 2,
        "order": 14,
        "title": "Onboarding wizard",
        "issues": [
          47,
          43,
          50,
          51,
          35,
          63
        ],
        "rootCause": "The website field is type=url, the welcome screen counts as a step, the last button is mislabelled, there's no name fallback, and orgs default to Los Angeles.",
        "fix": "Prefix https://, match the step counts, rename the last button to \"Write my first article\" (it keeps opening the writer), fix the greeting and possessive, and set new workspaces' time zone from the browser; existing workspaces are left as they are (DEC-9).",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [
          "DEC-9"
        ],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1258-bug-onboarding-blocks-create-when-the-website-has-no-https",
        "ticket": "VP-1258",
        "pr": {
          "number": 656,
          "url": "https://github.com/deepstation/vantagepost/pull/656",
          "title": "Let onboarding create a workspace from a bare domain, and fix its steps, last button, greeting and time zone (VP-1258)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1258-bug-onboarding-blocks-create-when-the-website-has-no-https",
          "sha": "ebff692ab8338754620e6ffb643df8be95e7ca6a",
          "ci": "none",
          "updatedAt": "2026-10-20T11:35:26Z"
        },
        "note": "PR #656 open; awaiting CI and Micah review",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496135224,
        "deferred": null
      },
      "RMD-F3": {
        "id": "RMD-F3",
        "code": "F3",
        "wave": 2,
        "order": 15,
        "title": "Menu button and sidebar layering",
        "issues": [
          44,
          2
        ],
        "rootCause": "The app menu shows during onboarding and sits above dialogs.",
        "fix": "Hide it on /onboarding, layer it under dialogs, and add a mobile top offset.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1263-bug-the-app-menu-shows-during-onboarding-and-the-phone-menu",
        "ticket": "VP-1263",
        "pr": {
          "number": 659,
          "url": "https://github.com/deepstation/vantagepost/pull/659",
          "title": "Hide the app menu during onboarding and keep the phone menu button under dialogs (VP-1263)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1263-bug-the-app-menu-shows-during-onboarding-and-the-phone-menu",
          "sha": "4bcb0d33e2e0940f77ed7c6f04964a1be0c5762f",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:42Z"
        },
        "note": "PR #659 open into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-G1": {
        "id": "RMD-G1",
        "code": "G1",
        "wave": 2,
        "order": 16,
        "title": "Sign-in page",
        "issues": [
          29,
          30,
          31
        ],
        "rootCause": "Only \"Sign in\" wording, Terms and Privacy as plain text, and a full-height CAPTCHA slot.",
        "fix": "Add \"Create your free account\" for new visitors, link Terms and Privacy, and collapse the CAPTCHA slot (Login.tsx, TurnstileWidget.tsx).",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1266-make-the-sign-in-page-work-for-new-accounts-too-link-terms",
        "ticket": "VP-1266",
        "pr": {
          "number": 660,
          "url": "https://github.com/deepstation/vantagepost/pull/660",
          "title": "Let new visitors create an account from the sign-in page, link Terms and Privacy, and close the blank bot-check gap (VP-1266)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1266-make-the-sign-in-page-work-for-new-accounts-too-link-terms",
          "sha": "a903f5b9fe5935a8743f7ae53ebe84a08c8aaef3",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:48Z"
        },
        "note": "PR #660 open; awaiting CI and Micah review",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-B2": {
        "id": "RMD-B2",
        "code": "B2",
        "wave": 3,
        "order": 17,
        "title": "Check every claim against its cited page",
        "issues": [
          78,
          19,
          18
        ],
        "rootCause": "Nothing checks a claim against the page it links to, and top-up sources are cited from their title alone. The fact-check format makes the model pick a verdict before it reasons.",
        "fix": "Pull page facts for every source in the writer step, check each citation before linking it, and use one verdict per claim with the reason first.",
        "size": "L",
        "tags": [],
        "deps": [
          "RMD-B1",
          "RMD-A1"
        ],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1249-bug-citations-link-to-pages-that-dont-say-what-the-sentence",
        "ticket": "VP-1249",
        "pr": {
          "number": 702,
          "url": "https://github.com/deepstation/vantagepost/pull/702",
          "title": "Check every citation against the page it links to, and give each fact-check claim one reasoned verdict (VP-1249)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1249-bug-citations-link-to-pages-that-dont-say-what-the-sentence",
          "sha": "04187dfbbbc8e9eca0f173b4a72d4c366a82dbf8",
          "ci": "none",
          "updatedAt": "2026-10-20T12:31:43Z"
        },
        "note": "PR #702 merged into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499511561,
        "deferred": null
      },
      "RMD-B3": {
        "id": "RMD-B3",
        "code": "B3",
        "wave": 3,
        "order": 18,
        "title": "Source ranking, language and shortfall",
        "issues": [
          75,
          8,
          76
        ],
        "rootCause": "Sources stay in search order with no authority ranking, research is never told the article's language, and the reason for a shortfall is only logged.",
        "fix": "A ranking step (official docs, standards bodies, .edu/.gov, major publishers first; near-duplicate SEO blogs demoted), an English locale on fetches, 20 sources by default, and the requested/found/cited counts saved and shown.",
        "size": "M",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1252-rank-sources-by-authority-fetch-them-in-the-articles",
        "ticket": "VP-1252",
        "pr": {
          "number": 665,
          "url": "https://github.com/deepstation/vantagepost/pull/665",
          "title": "Rank sources by authority, fetch them in the article's language, and say why fewer were found (VP-1252)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1252-rank-sources-by-authority-fetch-them-in-the-articles",
          "sha": "7054d6ae22a9da479d0593be7e1753f11eb77862",
          "ci": "none",
          "updatedAt": "2026-10-20T11:24:27Z"
        },
        "note": "PR #665 open; awaiting Micah review/merge",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-B5": {
        "id": "RMD-B5",
        "code": "B5",
        "wave": 3,
        "order": 19,
        "title": "Onboarding site research",
        "issues": [
          45,
          46
        ],
        "rootCause": "The scraper strips links, so products have no URLs; competitors come from the model's memory.",
        "fix": "Keep the site's links and nav, and find competitors with a dated web search.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1254-bug-onboarding-research-finds-products-with-no-links-and",
        "ticket": "VP-1254",
        "pr": {
          "number": 662,
          "url": "https://github.com/deepstation/vantagepost/pull/662",
          "title": "Find product links and current competitors in onboarding website research (VP-1254)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1254-bug-onboarding-research-finds-products-with-no-links-and",
          "sha": "4adb7c051e1a99c69e6f26e44a44cd2f38aded0f",
          "ci": "none",
          "updatedAt": "2026-10-20T11:24:04Z"
        },
        "note": "PR #662 open into release/v0.1.7; tsc 0; 862 related tests pass; live proof 2 calls ~$0.081",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-E1": {
        "id": "RMD-E1",
        "code": "E1",
        "wave": 4,
        "order": 20,
        "title": "One keyword clean-up step",
        "issues": [
          60,
          67,
          68,
          70
        ],
        "rootCause": "Variant merging misses plurals, price/pricing and on/for/in; the chat skips merging and the brand filter; the wizard counts skipped keywords as new.",
        "fix": "One shared clean-up (variants plus a brand and relevance filter), called from chat, wizard, discovery and the bank insert, reporting new vs already tracked.",
        "size": "M",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": "No paid DataForSEO calls for testing without Micah's OK.",
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1260-bug-keyword-research-saves-near-duplicate-keywords-and-other",
        "ticket": "VP-1260",
        "pr": {
          "number": 664,
          "url": "https://github.com/deepstation/vantagepost/pull/664",
          "title": "Score keyword priority and the Write NOW tag from volume, difficulty and traffic potential (VP-1265)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1265-bug-every-keyword-shows-medium-priority-and-write-now-goes",
          "sha": "24d9ae4c15a7b3f16e3a373ac79fb4bde0e6dc8f",
          "ci": "none",
          "updatedAt": "2026-10-20T11:37:30Z"
        },
        "note": "PR #663 open into release/v0.1.7, review clean; awaiting Micah",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496257575,
        "deferred": null
      },
      "RMD-E2": {
        "id": "RMD-E2",
        "code": "E2",
        "wave": 4,
        "order": 21,
        "title": "One scoring function",
        "issues": [
          61,
          73
        ],
        "rootCause": "Priority is never calculated (all Medium), and the tag ignores traffic potential.",
        "fix": "Score volume, KD and traffic potential once, and use it for both the priority and the tag.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1265-bug-every-keyword-shows-medium-priority-and-write-now-goes",
        "ticket": "VP-1265",
        "pr": {
          "number": 664,
          "url": "https://github.com/deepstation/vantagepost/pull/664",
          "title": "Score keyword priority and the Write NOW tag from volume, difficulty and traffic potential (VP-1265)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1265-bug-every-keyword-shows-medium-priority-and-write-now-goes",
          "sha": "24d9ae4c15a7b3f16e3a373ac79fb4bde0e6dc8f",
          "ci": "none",
          "updatedAt": "2026-10-20T11:37:30Z"
        },
        "note": "PR #664 open; awaiting Micah review/merge; run scripts/recompute-keyword-priority.ts after deploy",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496257575,
        "deferred": null
      },
      "RMD-E3": {
        "id": "RMD-E3",
        "code": "E3",
        "wave": 4,
        "order": 22,
        "title": "One source of truth for clusters",
        "issues": [
          65,
          66,
          74,
          62
        ],
        "rootCause": "Clusters are created in four places with no duplicate check, the wizard ignores existing ones, and the planner copies the title into the Cluster column.",
        "fix": "A shared find-or-create with a unique active-name index and ID lookups; the wizard reads existing clusters and shows pillar volume and KD.",
        "size": "M",
        "tags": [
          "migration"
        ],
        "deps": [
          "RMD-E1"
        ],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1271-keep-one-list-of-clusters-that-the-strategy-wizard-research",
        "ticket": "VP-1271",
        "pr": {
          "number": 689,
          "url": "https://github.com/deepstation/vantagepost/pull/689",
          "title": "Keep one list of clusters that the strategy wizard, research chat and planner all share (VP-1271)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1271-keep-one-list-of-clusters-that-the-strategy-wizard-research",
          "sha": "227f152cf8588a61941e442c940a181b24eaabe1",
          "ci": "none",
          "updatedAt": "2026-10-20T11:59:03Z"
        },
        "note": "PR #689 merged (ae812b60)",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497552521,
        "deferred": null
      },
      "RMD-E4": {
        "id": "RMD-E4",
        "code": "E4",
        "wave": 4,
        "order": 23,
        "title": "Keyword one-offs",
        "issues": [
          64,
          69,
          71,
          72
        ],
        "rootCause": "No wizard entry on Keyword Research, a session field-name mismatch (updated_at vs updatedAt), a 200-keyword lookup cap, and two volume sources.",
        "fix": "Add the entry point, fix the field name and auto-title sessions, page the lookup, and fall back to the exact-volume lookup.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1275-bug-keyword-chat-history-shows-untitled-session-invalid-date",
        "ticket": "VP-1275",
        "pr": {
          "number": 666,
          "url": "https://github.com/deepstation/vantagepost/pull/666",
          "title": "Show real dates and titles in keyword chat history, check the whole keyword bank, keep chat volumes on save, and reopen the strategy wizard from Keyword Research (VP-1275)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1275-bug-keyword-chat-history-shows-untitled-session-invalid-date",
          "sha": "9f0140e37a51693da36666b2605addd1e5dd8c10",
          "ci": "none",
          "updatedAt": "2026-10-20T11:24:34Z"
        },
        "note": "PR #666 open; tests + tsc green; merges cleanly with E1/E2 working trees",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554,
        "deferred": null
      },
      "RMD-G2": {
        "id": "RMD-G2",
        "code": "G2",
        "wave": 5,
        "order": 24,
        "title": "Marketing nav, footer and help",
        "issues": [
          25,
          26,
          27,
          28
        ],
        "rootCause": "Two generations of nav and footer: placeholder links on the new one, links to removed sections and 404 social accounts on the old one.",
        "fix": "One footer and nav; build every page the links point to (Docs, Support, Contact, Status, Help and Getting started); every homepage link works; rename \"Watch Vince work\" to what it does (DEC-8).",
        "size": "L",
        "tags": [],
        "deps": [],
        "decisions": [
          "DEC-8"
        ],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1256-build-the-docs-support-contact-status-help-and-getting",
        "ticket": "VP-1256",
        "pr": {
          "number": 676,
          "url": "https://github.com/deepstation/vantagepost/pull/676",
          "title": "Build the Docs, Support, Contact, Status, Help and Getting started pages, and give the site one nav and footer where every link works (VP-1256)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1256-build-the-docs-support-contact-status-help-and-getting",
          "sha": "42702b785c26b4441b0dc27bf4a5f800f111676a",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:35Z"
        },
        "note": "PR #676 open into release/v0.1.7; tsc 0, related jest 154 pass; Linear VP-1256 In Progress with PR attached",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530,
        "deferred": null
      },
      "RMD-H1": {
        "id": "RMD-H1",
        "code": "H1",
        "wave": 5,
        "order": 25,
        "title": "Article workspace layout and a11y",
        "issues": [
          3,
          6,
          17,
          14,
          15,
          11
        ],
        "rootCause": "Nothing reserves room for the floating and sticky elements, the tab title is set once, and icon tabs and buttons lose their names on small screens.",
        "fix": "Bottom padding for Vince, scroll offset for the step bar, update document.title, aria-labels, and one axe run (#11 re-checked there).",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1259-bug-on-the-article-page-vince-covers-share-the-step-bar",
        "ticket": "VP-1259",
        "pr": {
          "number": 669,
          "url": "https://github.com/deepstation/vantagepost/pull/669",
          "title": "Keep the article page clear of Vince and the step bar, keep its tab title current, and name its icon controls (VP-1259)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1259-bug-on-the-article-page-vince-covers-share-the-step-bar",
          "sha": "e4c81b05df06ab645ddb0990a0d1541c1e0fd31c",
          "ci": "none",
          "updatedAt": "2026-10-20T11:24:55Z"
        },
        "note": "PR #669 open; awaiting Micah merge. #3 live 800px check left for staging verification.",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530,
        "deferred": null
      },
      "RMD-S1": {
        "id": "RMD-S1",
        "code": "S1",
        "wave": 5,
        "order": 26,
        "title": "Enterprise labelled Free; its credits never used",
        "issues": [],
        "rootCause": "Only Team workspaces bill the workspace wallet, and Billing labels Enterprise as Free.",
        "fix": "Bill Enterprise to the workspace wallet and label it correctly. Its own ticket.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-C1"
        ],
        "decisions": [],
        "notes": null,
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1267-bug-billing-shows-enterprise-workspaces-as-free-and-their",
        "ticket": "VP-1267",
        "pr": {
          "number": 697,
          "url": "https://github.com/deepstation/vantagepost/pull/697",
          "title": "Spend an Enterprise workspace's credits and name its plan on Billing (VP-1267)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1267-bug-billing-shows-enterprise-workspaces-as-free-and-their",
          "sha": "0adec2c52fad3dc660db4dc24e489f3f7f2b2f30",
          "ci": "none",
          "updatedAt": "2026-10-20T12:20:06Z"
        },
        "note": "merged #697 into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792498813539,
        "deferred": null
      },
      "RMD-S2": {
        "id": "RMD-S2",
        "code": "S2",
        "wave": 5,
        "order": 27,
        "title": "Wizard saves keywords into the wrong cluster",
        "issues": [],
        "rootCause": "The wizard finds its cluster by name only; with two clusters of the same name a re-run lands in the old one. Found in code, not tested live.",
        "fix": "Look clusters up by ID. Its own ticket; may close with E3.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-E3"
        ],
        "decisions": [],
        "notes": null,
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1269-bug-re-running-the-keyword-wizard-can-save-the-new-keywords",
        "ticket": "VP-1269",
        "pr": {
          "number": 694,
          "url": "https://github.com/deepstation/vantagepost/pull/694",
          "title": "File the chat's and ideation's keywords by the active cluster's id, never its name (VP-1269)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1269-bug-re-running-the-keyword-wizard-can-save-the-new-keywords",
          "sha": "270659f6481a604a51ab5e704dd1f4e728e283dc",
          "ci": "none",
          "updatedAt": "2026-10-20T12:07:49Z"
        },
        "note": "PR #694 merged",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792498073790,
        "deferred": null
      },
      "RMD-S3": {
        "id": "RMD-S3",
        "code": "S3",
        "wave": 5,
        "order": 28,
        "title": "Comments unreachable below 1024px",
        "issues": [],
        "rootCause": "The Comments panel and its button are hidden below 1024px.",
        "fix": "Give comments a drawer or button at narrow widths. Its own ticket.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": null,
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1262-bug-comments-cant-be-opened-on-the-article-page-below-1024px",
        "ticket": "VP-1262",
        "pr": {
          "number": 668,
          "url": "https://github.com/deepstation/vantagepost/pull/668",
          "title": "Open comments in a drawer below 1024px on the article page (VP-1262)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1262-bug-comments-cant-be-opened-on-the-article-page-below-1024px",
          "sha": "a79eea446d4ea3caf3bc52f21d213e63294c5dd2",
          "ci": "none",
          "updatedAt": "2026-10-20T11:24:47Z"
        },
        "note": "PR #668 open into release/v0.1.7; tsc 0; 337/337 related tests pass",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530,
        "deferred": null
      },
      "RMD-V1": {
        "id": "RMD-V1",
        "code": "V1",
        "wave": 6,
        "order": 29,
        "title": "Full 78-item re-run on staging",
        "issues": [],
        "rootCause": "Nobody has run the list end to end.",
        "fix": "Run all 78 items on staging with a fresh free account and the existing account, send Micah screenshots, and keep the run as the standing pre-release checklist.",
        "size": "M",
        "tags": [],
        "deps": [
          "RMD-R0",
          "RMD-A1",
          "RMD-A2",
          "RMD-B1",
          "RMD-B4",
          "RMD-C1",
          "RMD-C3",
          "RMD-C4",
          "RMD-D1",
          "RMD-D2",
          "RMD-X1",
          "RMD-A3",
          "RMD-F1",
          "RMD-F2",
          "RMD-F3",
          "RMD-G1",
          "RMD-B2",
          "RMD-B3",
          "RMD-B5",
          "RMD-E1",
          "RMD-E2",
          "RMD-E3",
          "RMD-E4",
          "RMD-G2",
          "RMD-H1",
          "RMD-S1",
          "RMD-S2",
          "RMD-S3",
          "RMD-S4",
          "RMD-S5",
          "RMD-S6",
          "RMD-S8",
          "RMD-S9",
          "RMD-S10",
          "RMD-S11",
          "RMD-S12",
          "RMD-S13",
          "RMD-S14",
          "RMD-S15",
          "RMD-S16",
          "RMD-S17",
          "RMD-S18",
          "RMD-S19",
          "RMD-S20",
          "RMD-S21",
          "RMD-S22",
          "RMD-S23",
          "RMD-S24",
          "RMD-S25",
          "RMD-S26",
          "RMD-S27",
          "RMD-S28",
          "RMD-S29",
          "RMD-S30",
          "RMD-S31",
          "RMD-S32",
          "RMD-S33",
          "RMD-S34",
          "RMD-S35",
          "RMD-S36",
          "RMD-S37",
          "RMD-S38",
          "RMD-S39",
          "RMD-S40",
          "RMD-S41",
          "RMD-S42",
          "RMD-S43",
          "RMD-S46",
          "RMD-S44",
          "RMD-S45",
          "RMD-S47"
        ],
        "decisions": [],
        "notes": "Ready only when every other item is merged.",
        "kind": "verify",
        "status": "ready",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": null,
        "ticket": "VP-1273",
        "pr": null,
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792504004721,
        "deferred": null
      },
      "RMD-X1": {
        "id": "RMD-X1",
        "code": "X1",
        "wave": 2,
        "order": 10,
        "title": "Turn on X publishing for paid plans",
        "issues": [
          39
        ],
        "rootCause": "The homepage promises X publishing but the x_connections flag is on for super admins only. main has the newer X work (#634 VP-678, #635 paid-only X) that release lacks.",
        "fix": "After R0 brings the X work into release, turn X on for paid plans and keep the homepage copy (DEC-6).",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [
          "DEC-6"
        ],
        "notes": null,
        "kind": "workstream",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1248-turn-on-x-publishing-for-paid-plans",
        "ticket": "VP-1248",
        "pr": {
          "number": 655,
          "url": "https://github.com/deepstation/vantagepost/pull/655",
          "title": "Turn on X publishing for paid plans (VP-1248)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1248-turn-on-x-publishing-for-paid-plans",
          "sha": "7d8ac04d2e1ee90874df8ab9b62c1c1198366302",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:03Z"
        },
        "note": "PR #655 open",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530,
        "deferred": null
      },
      "RMD-S4": {
        "id": "RMD-S4",
        "code": "S4",
        "wave": 5,
        "order": 1030,
        "title": "Planner can show X as connected where production hides X",
        "issues": [],
        "rootCause": "Found during the R0 merge (VP-1251). Production gates X on the x_connections flag, X posting being configured, and a paid plan (resolveXAccess in lib/integrations/twitter-service.ts). Release's lib/social-media/connections.ts (getConnectedNetworks) checks only the paid plan, and release's X plan recheck route has no gate of its own. So after the merge the planner can list X as connected for a workspace production would not offer X to; the send is still refused when the token is read.",
        "fix": "Make getConnectedNetworks use resolveXAccess (report X unavailable when not offered, as the integrations status route does) and gate the X recheck route with the same check. Add tests for flag-off and unconfigured cases.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": null,
        "ticket": "VP-1277",
        "pr": {
          "number": 648,
          "url": "https://github.com/deepstation/vantagepost/pull/648",
          "title": "Merge main's production hotfixes into release/v0.1.7 (VP-1251)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1251-merge-mains-hotfixes-back-into-releasev017-so-the-release",
          "sha": "d71ddea1e9cd0679011599132c8e870da7c39b3b",
          "ci": "none",
          "updatedAt": "2026-10-20T01:38:17Z"
        },
        "note": "fixed in PR #648 commits 1a488210 + d71ddea1",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792460307962
      },
      "RMD-S5": {
        "id": "RMD-S5",
        "code": "S5",
        "wave": 5,
        "order": 1031,
        "title": "Delete the unused LinkedIn page-selection module and its test",
        "issues": [],
        "rootCause": "The merge kept production's linkedin-pending-connection module; the release's linkedin-pending-selection module is now imported only by its own test.",
        "fix": "Delete lib/integrations/linkedin-pending-selection.ts and its test.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1278-delete-the-unused-linkedin-page-selection-module-and-its",
        "ticket": "VP-1278",
        "pr": {
          "number": 672,
          "url": "https://github.com/deepstation/vantagepost/pull/672",
          "title": "Delete the unused LinkedIn page-selection module and its test (VP-1278)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1278-delete-the-unused-linkedin-page-selection-module-and-its",
          "sha": "f09dd665f1793700f3621080a70589304afd380d",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:42Z"
        },
        "note": "PR #672 open; awaiting review/merge",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554
      },
      "RMD-S6": {
        "id": "RMD-S6",
        "code": "S6",
        "wave": 5,
        "order": 1032,
        "title": "Make switched-off X and personal LinkedIn answer the same plain \"Not found\" as every other switched-off feature",
        "issues": [],
        "rootCause": "X and personal-LinkedIn routes answer a feature_disabled 404 (x-route-responses.ts:16, linkedin-personal-route-responses.ts:14) while withFeature answers a plain Not found (guard.ts:95).",
        "fix": "Make both helpers return withFeature's plain Not found and update the tests.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1279-make-switched-off-x-and-personal-linkedin-answer-the-same",
        "ticket": "VP-1279",
        "pr": {
          "number": 674,
          "url": "https://github.com/deepstation/vantagepost/pull/674",
          "title": "Make switched-off X and personal LinkedIn answer the same plain Not found (VP-1279)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1279-make-switched-off-x-and-personal-linkedin-answer-the-same",
          "sha": "989353e887137e00cb4e9315f88c977cd12a6753",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:19Z"
        },
        "note": "PR #674 open, Linear VP-1279 In Progress with PR attached; lease released",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S8": {
        "id": "RMD-S8",
        "code": "S8",
        "wave": 5,
        "order": 1033,
        "title": "BUG: The test type check fails on the release with 7 errors in the Newsletter Studio tests, so PR Check goes red",
        "issues": [],
        "rootCause": "Newsletter Studio test files from batch 2 (#622) were not updated when batch 3 (#623) changed the types; bun run typecheck:tests exits 2 with 7 errors, and PR Check runs it (pr-check.yml:84).",
        "fix": "Fix the three test files (params helper type, extra argument at image-routes.test.ts:435, sendPlan: null in two fixtures) on release/v0.1.7 now.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1280-bug-the-test-type-check-fails-on-the-release-with-7-errors",
        "ticket": "VP-1280",
        "pr": {
          "number": 670,
          "url": "https://github.com/deepstation/vantagepost/pull/670",
          "title": "Fix the Newsletter Studio test types so the test type check passes again (VP-1280)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1280-bug-the-test-type-check-fails-on-the-release-with-7-errors",
          "sha": "59310de28869b7bd3b509586d88968f8256af099",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:21Z"
        },
        "note": "PR #670 open; done pending review/merge",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495373412
      },
      "RMD-S9": {
        "id": "RMD-S9",
        "code": "S9",
        "wave": 5,
        "order": 1034,
        "title": "Refuse a Facebook post at schedule time when the workspace has no Facebook Page connected",
        "issues": [],
        "rootCause": "getConnectedNetworks never looks up Facebook (connections.ts:50-67), so refuseUnconnected (connection-guard.ts:42) always lets Facebook through; the publisher refuses later (publish-service.ts:414-419).",
        "fix": "Look up the Facebook Page in getConnectedNetworks and return facebook true/false so refuseUnconnected gives a 409 at schedule time; add tests.",
        "size": "S",
        "tags": [],
        "deps": [
          "RMD-R0"
        ],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1281-refuse-a-facebook-post-at-schedule-time-when-the-workspace",
        "ticket": "VP-1281",
        "pr": {
          "number": 675,
          "url": "https://github.com/deepstation/vantagepost/pull/675",
          "title": "Refuse a Facebook post at schedule time when the workspace has no Facebook Page (VP-1281)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1281-refuse-a-facebook-post-at-schedule-time-when-the-workspace",
          "sha": "db2deadad3e207ba22a6c5face981f0e54a4be76",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:26Z"
        },
        "note": "PR #675 open; tsc 0; 18 related suites / 287 tests pass",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S10": {
        "id": "RMD-S10",
        "code": "S10",
        "wave": 5,
        "order": 1035,
        "title": "Launch Spotlight example models an invented first-person proof stat",
        "issues": [],
        "rootCause": "The Launch Spotlight preset example (lib/prompt-templates/system-presets.ts:326 on release) says \"In our own testing it cut the time to schedule a week of content from about an hour to under ten minutes\". The preset asks for a proof point, and the model can copy this first-person, number-carrying shape when the source has no proof point.",
        "fix": "Rewrite the example proof as a fact the source would give, add the no-invented-numbers fallback (write around a missing proof point). Change only system-presets.ts, then run the seed.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
        "ticket": "VP-1282",
        "pr": {
          "number": 651,
          "url": "https://github.com/deepstation/vantagepost/pull/651",
          "title": "Stop story post templates from inventing company anecdotes (VP-1261)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
          "sha": "1d048463b9b37859b6b7d06205047cec8ef9c055",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:59Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554
      },
      "RMD-S11": {
        "id": "RMD-S11",
        "code": "S11",
        "wave": 5,
        "order": 1036,
        "title": "Check DeepStation org-scoped copies of the old story presets",
        "issues": [],
        "rootCause": "VP-1261 fixes the global system presets only. scripts/preserve-deepstation-presets.ts copied the pre-VP-60 branded presets (incl. Founder Story / Startup Founder style prompts) into DeepStation org-scoped templates; if those rows exist and are in use, they keep the old no-fallback story prompts after the seed runs. Not verified: no DB read was made.",
        "fix": "Read DeepStation org-scoped social templates on staging/prod; if story-style ones are in use, add the same no-invented-story fallback (via the app, not raw SQL) or retire them.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
        "ticket": "VP-1283",
        "pr": {
          "number": 651,
          "url": "https://github.com/deepstation/vantagepost/pull/651",
          "title": "Stop story post templates from inventing company anecdotes (VP-1261)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
          "sha": "1d048463b9b37859b6b7d06205047cec8ef9c055",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:59Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554
      },
      "RMD-S12": {
        "id": "RMD-S12",
        "code": "S12",
        "wave": 5,
        "order": 1037,
        "title": "Planner angle overrides a story template's opening (1-3-1 Story never opens with Picture…)",
        "issues": [],
        "rootCause": "On the social planner (lib/social-planner/generate.ts ~1066-1104), each draft gets an angle (\"Commit fully to the <angle>, it is the hook and framing\") and, when templatePrescribesOpening is false, a hook technique. Runtime check during VP-1261 (gpt-5.4-mini, 6 runs, payroll explainer with no story): 0 invented anecdotes, but 0 of 6 opened with the 1-3-1 Story \"Picture…\" scene; renaming the first structure step to make the opening template-owned did not change it. The angle still drives the opening.",
        "fix": "When a template sets the opening or the story, have the planner angle only choose which part of the source to use (the same precedence line VP-1261 added to the older LinkedIn path), then re-run the 1-3-1 Story check.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
        "ticket": "VP-1284",
        "pr": {
          "number": 651,
          "url": "https://github.com/deepstation/vantagepost/pull/651",
          "title": "Stop story post templates from inventing company anecdotes (VP-1261)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1261-bug-story-post-templates-invent-company-anecdotes-when-the",
          "sha": "1d048463b9b37859b6b7d06205047cec8ef9c055",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:59Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554
      },
      "RMD-S13": {
        "id": "RMD-S13",
        "code": "S13",
        "wave": 5,
        "order": 1038,
        "title": "Strip the NUL byte from lib/article-engine/documents.ts",
        "issues": [],
        "rootCause": "The file holds one NUL byte, so file reports it as data and grep skips it silently (found during the VP-1255 review; pre-existing on release/v0.1.7).",
        "fix": "Remove the byte in its own small PR; no behavior change.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1285-replace-the-hidden-nul-character-in-the-article-engines",
        "ticket": "VP-1285",
        "pr": {
          "number": 677,
          "url": "https://github.com/deepstation/vantagepost/pull/677",
          "title": "Write the article engine's document key separator as an escape, not a raw NUL (VP-1285)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1285-replace-the-hidden-nul-character-in-the-article-engines",
          "sha": "b2ca7dde6aee9e042577de7e01e5182f5705fb99",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:46Z"
        },
        "note": "PR #677 open; awaiting review/merge by Micah",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S14": {
        "id": "RMD-S14",
        "code": "S14",
        "wave": 5,
        "order": 1039,
        "title": "Check the image bucket: public listing, and that private/ is not public",
        "issues": [],
        "rootCause": "VP-1270 (C3) moved new draft social images to private/ in code only. Whether the bucket allows public ListBucket was never checked, and the bucket policy that makes images/ public was not read, so it is unconfirmed that private/ is actually not public.",
        "fix": "Live AWS check (read-only): bucket policy, ACL and Block Public Access. Confirm no public s3:ListBucket and no public s3:GetObject on private/*. Record the result on VP-1270; close listing if it is open.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
        "ticket": "VP-1286",
        "pr": {
          "number": 652,
          "url": "https://github.com/deepstation/vantagepost/pull/652",
          "title": "Keep draft social images private and show them by signed links that expire (VP-1270)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
          "sha": "d930de8c7875f6ea541149b879703981f09a46e6",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:11Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S15": {
        "id": "RMD-S15",
        "code": "S15",
        "wave": 5,
        "order": 1040,
        "title": "Move draft images saved before VP-1270 out of the public folder",
        "issues": [],
        "rootCause": "VP-1270 (C3) stores new draft images under private/, but images already saved under images/social-media/<org>/ and images/social-thumbnails/<org>/ stay public with links that never expire.",
        "fix": "One-time script in scripts/: copy unpublished posts images to private/<folder>/<org>/, rewrite social_media_posts.image_url, then delete the public copies. Needs S3 writes, so run on dev/staging first.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
        "ticket": "VP-1287",
        "pr": {
          "number": 652,
          "url": "https://github.com/deepstation/vantagepost/pull/652",
          "title": "Keep draft social images private and show them by signed links that expire (VP-1270)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1270-bug-draft-social-images-are-served-from-public-links-that",
          "sha": "d930de8c7875f6ea541149b879703981f09a46e6",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:11Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S16": {
        "id": "RMD-S16",
        "code": "S16",
        "wave": 5,
        "order": 1041,
        "title": "BUG: Content automation offers \"Build keyword strategy\" to accounts without a paid plan, then refuses it",
        "issues": [],
        "rootCause": "/content/automation lets in accounts without a paid plan while their free credits last (requirePlatformAccess), and components/organizations/ContentAutomationSettings.tsx:584-597 shows Build keyword strategy / Re-run strategy to everyone. The embedded flow calls the bootstrap-keywords routes, which require hasPlatformAccess and answer 403 'A paid subscription is required to run keyword research' (app/api/organizations/[id]/bootstrap-keywords/propose/route.ts:92-93). Found while building D1 (VP-1276), which fixes the same mismatch for the /content banner only.",
        "fix": "Pass the paid check to ContentAutomationSettings and, without a paid plan, hide the button or label it as a paid feature linking to /pricing (same rule D1 used for the /content banner).",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1288-bug-content-automation-shows-build-keyword-strategy-to",
        "ticket": "VP-1288",
        "pr": {
          "number": 678,
          "url": "https://github.com/deepstation/vantagepost/pull/678",
          "title": "Show the plans link, not Build keyword strategy, to accounts without a paid plan (VP-1288)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1288-bug-content-automation-shows-build-keyword-strategy-to",
          "sha": "20a2fb1de4c98c9365412caa3f2afac7f1674b8d",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:53Z"
        },
        "note": "PR #678 open; awaiting Micah review/merge",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S17": {
        "id": "RMD-S17",
        "code": "S17",
        "wave": 5,
        "order": 1042,
        "title": "BUG: app/api/articles/import/__tests__/route.test.ts fails 4 tests on release/v0.1.7",
        "issues": [],
        "rootCause": "Fails identically on untouched origin/release/v0.1.7 @ 9b8529fa (found by build-b4 while running VP-1264 related tests): slug gets -1 when a deleted article holds the address, the print view renders <script> from a hostile import, audit-line notice differs.",
        "fix": "Find which merge changed import/print behaviour vs the test and fix the code or the test; keep PR Check green.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1289-bug-four-article-import-tests-fail-on-releasev017-so-the",
        "ticket": "VP-1289",
        "pr": {
          "number": 680,
          "url": "https://github.com/deepstation/vantagepost/pull/680",
          "title": "Count a workspace member's own credits down instead of Low balance at $5 (VP-1291)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
          "sha": "26d6e57320c507c278e1bf2e0b4570dddcec9a07",
          "ci": "none",
          "updatedAt": "2026-10-20T11:36:01Z"
        },
        "note": "traced all 4 failures; print view is sanitized (no live XSS); fixing stale tests + slug fallback wording",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496168307
      },
      "RMD-S18": {
        "id": "RMD-S18",
        "code": "S18",
        "wave": 5,
        "order": 1043,
        "title": "Context refresh does not re-scrape the website; the old article form counts unindexed entries as ready documents",
        "issues": [],
        "rootCause": "(1) POST /api/organizations/[id]/context/refresh says Force re-scrape, but ensureBusinessContext returns the existing entries when any exist (lib/content-schedule/ideation-service.ts:131-145), so nothing is re-scraped and an existing Website Content is never re-read. (2) components/blog-generator/ArticleGeneratorForm.tsx:826-840 counts every ready entry from /api/organizations/[id]/context as a ready document for the docs-only option, including Business Overview and other 0-chunk entries. Found by build-b4 (VP-1264).",
        "fix": "(1) Make refresh actually re-scrape and re-queue Website Content. (2) Count only entries with chunks (or the library list) for docs-only.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1264-bug-the-knowledge-library-shows-the-website-and-business",
        "ticket": "VP-1290",
        "pr": {
          "number": 653,
          "url": "https://github.com/deepstation/vantagepost/pull/653",
          "title": "Index the onboarding website and show unindexed library entries as Not indexed (VP-1264)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1264-bug-the-knowledge-library-shows-the-website-and-business",
          "sha": "1267fea5065aebcc62a1807d5c0c42fb8d37e55a",
          "ci": "none",
          "updatedAt": "2026-10-20T11:23:06Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495486554
      },
      "RMD-S19": {
        "id": "RMD-S19",
        "code": "S19",
        "wave": 5,
        "order": 1044,
        "title": "BUG: Comped workspaces and Team members in a non-Team workspace see Low balance against their personal wallet",
        "issues": [],
        "rootCause": "hasPlatformAccess passes when the user belongs to any paying or comped org (userHasAccessGrantingOrg), but hooks/useWallet.ts reads the org wallet only when the current workspace's planTier is 'team'. So a comped-org member, or a Team member viewing another workspace, has the personal wallet ($2 grant) checked against the paid $5 point in components/subscription/UpgradeBanner.tsx and gets Low balance with Top up. Pre-existing (the old isSubscribed check did the same); found in review of D1 (VP-1276).",
        "fix": "Decide which wallet pays for the current workspace the same way dispatch-debit does (comped/enterprise included) and read that one, or skip the balance banners for access that a workspace grants.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
        "ticket": "VP-1291",
        "pr": {
          "number": 680,
          "url": "https://github.com/deepstation/vantagepost/pull/680",
          "title": "Count a workspace member's own credits down instead of Low balance at $5 (VP-1291)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
          "sha": "26d6e57320c507c278e1bf2e0b4570dddcec9a07",
          "ci": "none",
          "updatedAt": "2026-10-20T11:36:01Z"
        },
        "note": "PR #680 open; review done; follow-up S27 filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496168307
      },
      "RMD-S20": {
        "id": "RMD-S20",
        "code": "S20",
        "wave": 5,
        "order": 1045,
        "title": "Add an X switch (x_connections) to the admin Features panel",
        "issues": [],
        "rootCause": "useFeatureFlags reads only FEATURE_KEYS; x_connections is a KNOWN_FLAGS key outside FEATURE_KEYS.",
        "fix": "List x_connections in the admin Features panel (or a dedicated X switch) using the existing PATCH /api/admin/feature-flags/[key] endpoint.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "notes": "Found by build-x1 on X1/VP-1248. The admin Features panel (app/admin/FeaturesSection.tsx via app/admin/useFeatureFlags.ts) lists only FEATURE_KEYS, so x_connections can be switched only through PATCH /api/admin/feature-flags/x_connections. Production and staging likely hold a stored off row, so turning X on after VP-1248 needs that API call. A switch in the panel would make it a click.",
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1248-turn-on-x-publishing-for-paid-plans",
        "ticket": "VP-1292",
        "pr": {
          "number": 655,
          "url": "https://github.com/deepstation/vantagepost/pull/655",
          "title": "Turn on X publishing for paid plans (VP-1248)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1248-turn-on-x-publishing-for-paid-plans",
          "sha": "7d8ac04d2e1ee90874df8ab9b62c1c1198366302",
          "ci": "none",
          "updatedAt": "2026-10-20T11:25:03Z"
        },
        "note": "ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S21": {
        "id": "RMD-S21",
        "code": "S21",
        "wave": 5,
        "order": 1046,
        "title": "BUG: app/api/integrations/linkedin/disconnect-personal/__tests__/route.test.ts fails 1 test on release/v0.1.7",
        "issues": [],
        "rootCause": "The route now also clears linkedinPersonalRefreshToken and linkedinPersonalRefreshExpiresAt, but the test still expects only the four older columns (route.test.ts:56). Fails on origin/release/v0.1.7 9b8529fa with no other changes.",
        "fix": "Update the expected cleared columns in the test to include the two refresh-token columns (check the route clears them on purpose first).",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1293-bug-the-personal-linkedin-disconnect-test-fails-on",
        "ticket": "VP-1293",
        "pr": {
          "number": 680,
          "url": "https://github.com/deepstation/vantagepost/pull/680",
          "title": "Count a workspace member's own credits down instead of Low balance at $5 (VP-1291)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
          "sha": "26d6e57320c507c278e1bf2e0b4570dddcec9a07",
          "ci": "none",
          "updatedAt": "2026-10-20T11:36:01Z"
        },
        "note": "PR #671 open",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496168307
      },
      "RMD-S22": {
        "id": "RMD-S22",
        "code": "S22",
        "wave": 5,
        "order": 1047,
        "title": "BUG: Sign-in button stays disabled with no message when the bot check script fails to load",
        "issues": [],
        "rootCause": "TurnstileWidget.tsx .catch (script load failure) only clears the token; Login.tsx disables Continue with Email while there is no token and shows nothing, so a blocked challenges.cloudflare.com (ad blocker, network) leaves the visitor at a dead button with no reason. Pre-existing; found in VP-1266 review.",
        "fix": "Surface the load failure in Login/OtpInput (an inline message such as: the security check could not load, allow challenges.cloudflare.com or try another network, or continue with Google). Do not change the key or verification.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1294-bug-if-the-bot-check-cant-load-an-ad-blocker-a-blocked",
        "ticket": "VP-1294",
        "pr": {
          "number": 682,
          "url": "https://github.com/deepstation/vantagepost/pull/682",
          "title": "Say why email sign-in is stuck when the bot check can't load, with Try again (VP-1294)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1294-bug-if-the-bot-check-cant-load-an-ad-blocker-a-blocked",
          "sha": "3db0a30e2dee785cee629190c15ce42157282f09",
          "ci": "none",
          "updatedAt": "2026-10-20T11:34:40Z"
        },
        "note": "PR #682 open; tests + tsc green; never merged",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496089916
      },
      "RMD-S23": {
        "id": "RMD-S23",
        "code": "S23",
        "wave": 5,
        "order": 1048,
        "title": "Keyword merge key treats opposite conversions as one keyword",
        "issues": [],
        "rootCause": "canonicalKey in lib/keyword-research/near-duplicates.ts sorts the token set, so directional keywords like \"pdf to word\" and \"word to pdf\" (or \"python to java\" / \"java to python\") share a key and are always merged, whatever their volumes. Pre-existing since VP-456; found while building VP-1260 (E1), which leaves it as is.",
        "fix": "Keep the order of the two sides around a directional \"to\" in canonicalKey (e.g. key \"pdf>word\"), with a test for both directions.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1295-close-variant-direction",
        "ticket": "VP-1295",
        "pr": {
          "number": 704,
          "url": "https://github.com/deepstation/vantagepost/pull/704",
          "title": "Keep \"pdf to word\" and \"word to pdf\" apart in the close-variant merge too (VP-1295)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1295-close-variant-direction",
          "sha": "c1236ffb9e347d2d2786899634a635c1ae869265",
          "ci": "none",
          "updatedAt": "2026-10-20T12:37:10Z"
        },
        "note": "PR #704 (second half) squash-merged (fa4f4b3b); VP-1295 Done with #679 and #704 attached",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499838532
      },
      "RMD-S24": {
        "id": "RMD-S24",
        "code": "S24",
        "wave": 5,
        "order": 1049,
        "title": "Research keeps the same page twice under different tracking queries",
        "issues": [],
        "rootCause": "cleanResearchSources dedupes on the URL without its fragment, and stripTrackingParams only strips known trackers (utm_*, gclid…). A live research run on 2026-10-19 (build-b3, VP-1252) returned anthropic.com/news/claude-opus-4-8?os=0 and ?asuniq=7a954aaa, claude-3-7-sonnet and ?via=Top10SM, claude-code-on-team-and-enterprise?sf7300509=1 and ?cId=cj as separate sources, so one page can take two of the brief's slots.",
        "fix": "In cleanResearchSources, treat two URLs as the same page when host+path match and the only difference is query parameters that are not part of the page's identity (or strip unknown single-use params such as os, asuniq, via, cId, sf*). Keep the first. Add a test from the live URLs.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1296-bug-research-lists-the-same-page-twice-when-its-links-differ",
        "ticket": "VP-1296",
        "pr": {
          "number": 681,
          "url": "https://github.com/deepstation/vantagepost/pull/681",
          "title": "Keep one research source per page when links differ only by tracking tags (VP-1296)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1296-bug-research-lists-the-same-page-twice-when-its-links-differ",
          "sha": "d5eadbc418826d18d5b08066368fd64f09b1185c",
          "ci": "none",
          "updatedAt": "2026-10-20T11:26:12Z"
        },
        "note": "PR #681 open, awaiting review",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495603530
      },
      "RMD-S25": {
        "id": "RMD-S25",
        "code": "S25",
        "wave": 5,
        "order": 1050,
        "title": "The bare-spinner guard fails on release: StepApprove has 4 bare Loader2, ceiling 3",
        "issues": [],
        "rootCause": "dff8547e (VP-904, #617, the outline note on the Approve step) added a fourth bare <Loader2> to components/blog-generator/vnext/StepApprove.tsx; __tests__/cross-cutting/no-bare-loader2.test.ts caps that file at 3, so the guard fails on origin/release/v0.1.7 @ 9b8529fa for every PR.",
        "fix": "Swap the new Loader2 for <Spinner label> or <SpinnerIcon size=\"sm\"> with aria-busy on its button (VP-330 rule), so the file is back at its ceiling. Do not raise the ceiling.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1297-bug-the-spinner-guard-test-fails-on-releasev017-so-every-pr",
        "ticket": "VP-1297",
        "pr": {
          "number": 673,
          "url": "https://github.com/deepstation/vantagepost/pull/673",
          "title": "Draw the Revise button's busy spinner as the house spinner, so the bare-spinner guard passes again (VP-1297)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1297-bug-the-spinner-guard-test-fails-on-releasev017-so-every-pr",
          "sha": "c4f07d66fecde8c2c6d387278ac7ffd5201bee64",
          "ci": "none",
          "updatedAt": "2026-10-20T11:22:17Z"
        },
        "note": "PR #673 open",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792495373412
      },
      "RMD-S26": {
        "id": "RMD-S26",
        "code": "S26",
        "wave": 5,
        "order": 1051,
        "title": "Book-a-demo form tells VantagePost visitors to email info@deepstation.ai",
        "issues": [],
        "rootCause": "components/demo/BookDemoForm.tsx:118 and :150-153 fall back to info@deepstation.ai (a DeepStation address) on the VantagePost /schedule-a-demo page; Login.tsx error toasts say the same. Every other VantagePost page uses support@vantagepost.ai.",
        "fix": "Use support@vantagepost.ai (or a sales address Micah names) in BookDemoForm and the Login error toasts.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1298-bug-the-book-a-demo-page-and-sign-in-errors-tell-vantagepost",
        "ticket": "VP-1298",
        "pr": {
          "number": 688,
          "url": "https://github.com/deepstation/vantagepost/pull/688",
          "title": "Give support@vantagepost.ai on the demo form and sign-in errors (VP-1298)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1298-bug-the-book-a-demo-page-and-sign-in-errors-tell-vantagepost",
          "sha": "76660273a48681327c3663afedc1b0e4d5e929fb",
          "ci": "none",
          "updatedAt": "2026-10-20T11:50:37Z"
        },
        "note": "PR #688 merged; VP-1298 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497038466
      },
      "RMD-S27": {
        "id": "RMD-S27",
        "code": "S27",
        "wave": 5,
        "order": 1052,
        "title": "The pre-flight balance check and the usage hook still carry their own copy of the which-wallet-pays rule",
        "issues": [],
        "rootCause": "VP-1291 put the rule (workspace wallet only on Team) in lib/wallet/paying-wallet.ts walletThatPays, used by the charge (dispatch-debit.ts) and the wallet banner hook (useWallet.ts). lib/entitlements/can-generate.ts:61 (the check that decides whether a generation may start, and which wallet it checks) and hooks/useSubscriptionUsage.ts:60 still hard-code planTier === 'team'. Same answer today, but if the rule changes (e.g. comped workspaces paying from the workspace wallet) the pre-flight check and usage display would check a different wallet than the one charged.",
        "fix": "Have can-generate.ts and useSubscriptionUsage.ts call walletThatPays, with a test that each follows the helper. After VP-1291 merges.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
        "ticket": "VP-1299",
        "pr": {
          "number": 680,
          "url": "https://github.com/deepstation/vantagepost/pull/680",
          "title": "Count a workspace member's own credits down instead of Low balance at $5 (VP-1291)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1291-bug-comped-workspaces-and-team-members-working-in-another",
          "sha": "26d6e57320c507c278e1bf2e0b4570dddcec9a07",
          "ci": "none",
          "updatedAt": "2026-10-20T11:36:01Z"
        },
        "note": "Ticket filed",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496168307
      },
      "RMD-S28": {
        "id": "RMD-S28",
        "code": "S28",
        "wave": 5,
        "order": 1053,
        "title": "A page can still appear twice in an article's sources when two source lists are merged",
        "issues": [],
        "rootCause": "VP-1296 (RMD-S24) dedupes within one research call via samePageKey in lib/article-engine/link-address.ts. Merges still compare exact links: lib/article-engine/draft.ts:800 (mergeSources) and draft.ts:1766-1767 (supplied links plus found ones), and lib/article-engine/source-list.ts:292 (sourceKey) keeps its own copy of the tracking list without the single-use tags. So a shortfall search returning claude-opus-4-8 after the first search returned claude-opus-4-8?os=0, or a user link https://a.com/page with research returning https://a.com/page/ or ?os=0, keeps both.",
        "fix": "After VP-1296 merges, key those merges (and sourceKey) on samePageKey. Test with a first search + shortfall search returning the same page under two links, and a supplied link vs a found ?os=0 copy.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1300-bug-a-page-can-still-show-up-twice-in-an-articles-sources",
        "ticket": "VP-1300",
        "pr": {
          "number": 703,
          "url": "https://github.com/deepstation/vantagepost/pull/703",
          "title": "Keep one source per page when two source lists are combined (VP-1300)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1300-bug-a-page-can-still-show-up-twice-in-an-articles-sources",
          "sha": "de01d0b4cbd8829be8f294f0eec31def11d3d23a",
          "ci": "none",
          "updatedAt": "2026-10-20T12:34:46Z"
        },
        "note": "merged #703",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499694783
      },
      "RMD-S29": {
        "id": "RMD-S29",
        "code": "S29",
        "wave": 5,
        "order": 1054,
        "title": "Supplier-name check fails on release: new sign-in help text says continue with Google",
        "issues": [],
        "rootCause": "Login.tsx:209/:268, getting-started/help/support pages use Google sign-in wording not on the allowed list.",
        "fix": "Allow those sign-in phrases (customer own account) or reword.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1301-bug-the-supplier-name-check-fails-on-the-release-because-new",
        "ticket": "VP-1301",
        "pr": {
          "number": 683,
          "url": "https://github.com/deepstation/vantagepost/pull/683",
          "title": "Allow the sign-in page's own Google sign-in wording in the supplier-name check (VP-1301)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1301-bug-the-supplier-name-check-fails-on-the-release-because-new",
          "sha": "4b6838cd591d37de9e89f6e87dab1660c576b451",
          "ci": "none",
          "updatedAt": "2026-10-20T11:41:20Z"
        },
        "note": "merged #683; VP-1301 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496490083
      },
      "RMD-S30": {
        "id": "RMD-S30",
        "code": "S30",
        "wave": 5,
        "order": 1055,
        "title": "Spinner check fails on release: UsageHistory uses a bare Loader2",
        "issues": [],
        "rootCause": "components/organizations/UsageHistory.tsx:161 from VP-1268.",
        "fix": "Use the shared house spinner.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1302-bug-the-spinner-check-fails-on-the-release-because-the-new",
        "ticket": "VP-1302",
        "pr": {
          "number": 685,
          "url": "https://github.com/deepstation/vantagepost/pull/685",
          "title": "Show the shared spinner while usage history loads (VP-1302)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1302-bug-the-spinner-check-fails-on-the-release-because-the-new",
          "sha": "c3b92877442633aadf889f17e2884c602f59dfab",
          "ci": "none",
          "updatedAt": "2026-10-20T11:41:57Z"
        },
        "note": "merged #685; VP-1302 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496525683
      },
      "RMD-S31": {
        "id": "RMD-S31",
        "code": "S31",
        "wave": 5,
        "order": 1056,
        "title": "keyword-tools-bank-and-save test fails 2 tests on release/v0.1.7",
        "issues": [],
        "rootCause": "lib/copilot/tools/__tests__/keyword-tools-bank-and-save.test.ts: the two #72 saveKeywords Labs-fallback tests get result.success false. Fails the same with release/v0.1.7 own source (found while merging #680; not caused by it).",
        "fix": "Find which merged PR changed saveKeywords or its mocks and update the test or the code.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1303-bug-saving-keywords-from-chat-fails-its-fallback-tests-on",
        "ticket": "VP-1303",
        "pr": {
          "number": 684,
          "url": "https://github.com/deepstation/vantagepost/pull/684",
          "title": "Give the saveKeywords test the bank's real save result, so its fallback tests pass again (VP-1303)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1303-bug-saving-keywords-from-chat-fails-its-fallback-tests-on",
          "sha": "48778e907aa69f48e64ca87a13b742b5f745892e",
          "ci": "none",
          "updatedAt": "2026-10-20T11:40:00Z"
        },
        "note": "PR open, merging",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496408608
      },
      "RMD-S32": {
        "id": "RMD-S32",
        "code": "S32",
        "wave": 5,
        "order": 1057,
        "title": "Disposable-database check fails on release: the wallet-debit integration test inserts before its database check",
        "issues": [],
        "rootCause": "__tests__/cross-cutting/integration-disposable-database.test.ts:196 requires await assertReachedToldDisposableDatabase(db) to appear in the source before the first .insert(. lib/wallet/__tests__/wallet-debit.integration.test.ts (added by VP-1268, #657) has helper newTeamOrg with .insert(organizations) at line 62, above the check in beforeAll at line 94. At run time beforeAll runs first, so this is the textual guard, but the guard is red on release 5fb76eed.",
        "fix": "Move the check above the seeding helpers (or the helpers below beforeAll) in wallet-debit.integration.test.ts so the guard reads the check first; do not loosen the guard.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1304-bug-the-disposable-database-check-fails-on-the-release",
        "ticket": "VP-1304",
        "pr": {
          "number": 686,
          "url": "https://github.com/deepstation/vantagepost/pull/686",
          "title": "Check the wallet test's database before its seeding helpers can write (VP-1304)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1304-bug-the-disposable-database-check-fails-on-the-release",
          "sha": "902760f30097ad9bf1e3951f8cda736c84026a9e",
          "ci": "none",
          "updatedAt": "2026-10-20T11:46:35Z"
        },
        "note": "PR #686 merged; VP-1304 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792496798292
      },
      "RMD-S33": {
        "id": "RMD-S33",
        "code": "S33",
        "wave": 5,
        "order": 1058,
        "title": "The Traditional Writer and scheduled articles still charge for the writing",
        "issues": [],
        "rootCause": "DEC-2 keeps an article's writing calls unbilled, and /pricing now says an article spends credits only on its research. That holds for the article engine on /content (lib/article-engine/usage.ts, VP-490). But the Traditional Writer (/content/new/classic POSTs /api/articles) and the content queuer / scheduled content send article/generate.requested to the old pipeline (lib/inngest/functions/generate-article.ts), whose LLM calls go through lib/article-generation/utils/llm-client.ts logAIUsage with chargeWallet unset, which means charge (lib/usage-tracking/token-tracker.ts:173).",
        "fix": "Decide: record-only for the old pipeline's writing calls too (pass chargeWallet:false as lib/article-engine/usage.ts does), or retire the old pipeline for these entry points. Then the pricing line is true everywhere.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1305-bug-the-traditional-writer-and-scheduled-articles-still",
        "ticket": "VP-1305",
        "pr": {
          "number": 699,
          "url": "https://github.com/deepstation/vantagepost/pull/699",
          "title": "Stop charging for the Traditional Writer's and scheduled articles' writing calls; research still charges (VP-1305)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1305-bug-the-traditional-writer-and-scheduled-articles-still",
          "sha": "3264853e57e2023dc19a579af15f7c09afec45e7",
          "ci": "none",
          "updatedAt": "2026-10-20T12:23:58Z"
        },
        "note": "PR #699 squash-merged into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499041843
      },
      "RMD-S34": {
        "id": "RMD-S34",
        "code": "S34",
        "wave": 5,
        "order": 1059,
        "title": "The free taste is still granted after the free wording was removed",
        "issues": [],
        "rootCause": "DEC-1: no free plan or trial for now. VP-1247 removed the free copy and the onboarding skip link, but the entitlement remains: every new user gets $2 (seedWelcomeBonusIfNeeded, lib/wallet/service.ts:265, FREE_WELCOME_BONUS_CENTS) and a waived first article (lib/entitlements/free-article.ts); app/onboarding/page.tsx:51-54 sends an unpaid user with an org and that taste to /content instead of the plans; the access guard admits trial credits. The Billing tab still labels an unpaid personal plan 'Free' (components/organizations/BillingTab.tsx:484). Vince's prompts tell the model 'This user is on the FREE plan' (lib/copilot/prompts/articles-planner.ts:100, social-media-assistant.ts:92, events-assistant.ts:84, events-list-assistant.ts:51), so the assistant can say 'free plan' to a customer.",
        "fix": "Micah decides whether DEC-1 also ends the grant and the first-article waiver now. If yes: stop the grant for new signups, send unpaid org-holders to /pricing?gated=1, relabel BillingTab 'No plan', and reword the copilot prompts to 'no paid plan'. If no: say so on DEC-1 so the remaining copy is deliberate.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1306-bug-new-accounts-still-get-free-credits-and-a-free-first",
        "ticket": "VP-1306",
        "pr": {
          "number": 693,
          "url": "https://github.com/deepstation/vantagepost/pull/693",
          "title": "Stop the free credits and free first article for new accounts, and send unpaid users to the plans (VP-1306)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1306-bug-new-accounts-still-get-free-credits-and-a-free-first",
          "sha": "7b83a76ec19c20bb6d0026e117c3f714926b7ef7",
          "ci": "none",
          "updatedAt": "2026-10-20T12:06:26Z"
        },
        "note": "PR #693 squash-merged into release/v0.1.7 (a8d43df4); VP-1306 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497995493
      },
      "RMD-S35": {
        "id": "RMD-S35",
        "code": "S35",
        "wave": 5,
        "order": 1060,
        "title": "Pricing page Enterprise contact dialog tells VantagePost visitors to email info@deepstation.ai",
        "issues": [],
        "rootCause": "components/pricing/EnterpriseContactDialog.tsx:108-111 shows a mailto:info@deepstation.ai link on the VantagePost pricing page (found while fixing VP-1298, which covered only the demo form and sign-in). Separately, app/api/enterprise-leads/route.ts:90 falls back to info@deepstation.ai as the internal notification recipient when ENTERPRISE_LEADS_EMAIL is unset; that is a destination, not visitor copy, so Micah should name it.",
        "fix": "Use support@vantagepost.ai in EnterpriseContactDialog and extend app/__tests__/visitor-contact-address.test.ts to scan it. Leave the enterprise-leads notify fallback for Micah to decide.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1307-bug-the-enterprise-contact-dialog-on-the-pricing-page-tells",
        "ticket": "VP-1307",
        "pr": {
          "number": 692,
          "url": "https://github.com/deepstation/vantagepost/pull/692",
          "title": "Give support@vantagepost.ai in the pricing page's Enterprise contact dialog (VP-1307)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1307-bug-the-enterprise-contact-dialog-on-the-pricing-page-tells",
          "sha": "66f38db705851ababa4c2330b9d7a51ad1d66447",
          "ci": "none",
          "updatedAt": "2026-10-20T12:06:12Z"
        },
        "note": "merged #692",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497975559
      },
      "RMD-S36": {
        "id": "RMD-S36",
        "code": "S36",
        "wave": 5,
        "order": 1061,
        "title": "Aurora grey guard fails on release: OutOfCreditsDialog counted as an aurora-mounted file after VP-1247",
        "issues": [],
        "rootCause": "__tests__/cross-cutting/aurora-hardcoded-grey.test.ts \"no mounted file exceeds its ratchet ceiling\" fails on release 0a5ca2c3: components/billing/OutOfCreditsDialog.tsx: 1 found, 0 allowed (text-slate-500=1, line 77). Green at 5fb76eed, red from 228de1a6 (VP-1247, #687). VP-1247 did not add the class; it added components/marketing/__tests__/paid-plans-copy.test.tsx which imports OutOfCreditsDialog next to aurora marketing components, which appears to pull the dialog into the derived mounted set.",
        "fix": "Either replace the bare text-slate-500 on OutOfCreditsDialog.tsx:77 with the muted-foreground token (preferred: the dialog can open over aurora pages), or keep test files out of the guard import graph. Do not raise the ceiling.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1308-bug-the-grey-text-check-fails-on-the-release-because-the-out",
        "ticket": "VP-1308",
        "pr": {
          "number": 691,
          "url": "https://github.com/deepstation/vantagepost/pull/691",
          "title": "Use the theme's muted text colour on the out-of-credits dialog's Maybe later button (VP-1308)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1308-bug-the-grey-text-check-fails-on-the-release-because-the-out",
          "sha": "1e9ad4e1cfe4c8a431cf81cdbd270b91d1037776",
          "ci": "none",
          "updatedAt": "2026-10-20T12:00:36Z"
        },
        "note": "merged #691",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792497638905
      },
      "RMD-S37": {
        "id": "RMD-S37",
        "code": "S37",
        "wave": 5,
        "order": 1062,
        "title": "Cluster edits drop the pillar keyword, volume, KD and sort order; renaming to a taken name fails with a bare 500",
        "issues": [],
        "rootCause": "updateTopicCluster (lib/keyword-research/services/keyword-service.ts, below findOrCreateCluster) checks snake_case keys (\"pillar_keyword\" in data, \"pillar_volume\", \"pillar_difficulty\", \"sort_order\") but both callers send camelCase: PATCH app/api/keyword-research/clusters/[id]/route.ts:63-68 and the chat updateCluster tool lib/copilot/tools/keyword-tools.ts:485-490. So editing a cluster pillar or reordering clusters is silently ignored (only name/description/status apply). Also since VP-1271 (#689) added the unique index on active (org, lower(name)), renaming a cluster to a name another active cluster has, or unarchiving one whose name is now taken, throws a 23505 that the route returns as a generic 500. Found while doing VP-1271; createTopicCluster had the same snake/camel mismatch and was fixed there.",
        "fix": "Make updateTopicCluster read camelCase (typed ClusterInput-style input, like createTopicCluster after VP-1271), and map a unique violation on rename/unarchive to a 409 \"A cluster named X already exists\" in the PATCH route and a clear error in the chat tool. Tests: camelCase pillar/sortOrder update applies; rename to a taken name returns 409.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1309-bug-editing-a-cluster-drops-changes-to-its-pillar-keyword",
        "ticket": "VP-1309",
        "pr": {
          "number": 696,
          "url": "https://github.com/deepstation/vantagepost/pull/696",
          "title": "Save every field of a cluster edit, and answer a taken name with 409 and a clear message (VP-1309)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1309-bug-editing-a-cluster-drops-changes-to-its-pillar-keyword",
          "sha": "57a02d1d67a2ad8652aeb2295e438679aa8c2f2d",
          "ci": "none",
          "updatedAt": "2026-10-20T12:12:49Z"
        },
        "note": "PR #696 merged",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792498376300
      },
      "RMD-S38": {
        "id": "RMD-S38",
        "code": "S38",
        "wave": 5,
        "order": 1063,
        "title": "Bare-spinner guard fails on release: EnginePanel has 2 bare Loader2, ceiling 1 after VP-1257 merged",
        "issues": [],
        "rootCause": "__tests__/cross-cutting/no-bare-loader2.test.ts fails on release/v0.1.7 at 6aee7723: components/blog-generator/workspace/EnginePanel.tsx has 2 bare <Loader2>, ceiling 1. The second arrived with A1 (#690, VP-1257, Fix flagged claims).",
        "fix": "Use <SpinnerIcon size=\"sm\"> with aria-busy inside the Fix flagged claims button (or <Spinner label>) so EnginePanel is back at its ceiling of 1; do not raise the ceiling.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1310-bug-the-spinner-check-fails-on-the-release-because-the-new",
        "ticket": "VP-1310",
        "pr": {
          "number": 695,
          "url": "https://github.com/deepstation/vantagepost/pull/695",
          "title": "Draw the Fix flagged claims button's busy spinner as the house spinner, so the bare-spinner guard passes again (VP-1310)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1310-bug-the-spinner-check-fails-on-the-release-because-the-new",
          "sha": "42db7383e0cfa2a009259bea0a73f57c1b49e68a",
          "ci": "none",
          "updatedAt": "2026-10-20T12:11:34Z"
        },
        "note": "PR #695 squash-merged into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792498298216
      },
      "RMD-S39": {
        "id": "RMD-S39",
        "code": "S39",
        "wave": 5,
        "order": 1064,
        "title": "Cluster routes answer a non-member with a 500 instead of 403",
        "issues": [],
        "rootCause": "app/api/keyword-research/clusters/[id]/route.ts GET/PATCH/DELETE call verifyOrgMembership (lib/keyword-research/services/keyword-service.ts), which throws \"You do not have access to this organization\"; the catch only maps messages containing \"not found\" to 404, so a non-member gets a generic 500. Found while doing VP-1309; not fixed there.",
        "fix": "Map the membership error to forbidden() (403) in the cluster routes (and any other keyword-research route with the same catch). Test: a non-member PATCH returns 403.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1311-bug-opening-editing-or-deleting-a-cluster-from-another",
        "ticket": "VP-1311",
        "pr": {
          "number": 698,
          "url": "https://github.com/deepstation/vantagepost/pull/698",
          "title": "Answer 403, not a server error, when a non-member opens, edits or deletes a cluster (VP-1311)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1311-bug-opening-editing-or-deleting-a-cluster-from-another",
          "sha": "4401f24a43ca173ad9521352389d617540604c82",
          "ci": "none",
          "updatedAt": "2026-10-20T12:24:02Z"
        },
        "note": "merged #698",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499051764
      },
      "RMD-S40": {
        "id": "RMD-S40",
        "code": "S40",
        "wave": 5,
        "order": 1065,
        "title": "Price-row guard fails on release: it reads claude-tips.blog in a source-rank comment as a model id",
        "issues": [],
        "rootCause": "lib/usage-tracking/__tests__/price-rows-complete.test.ts fails on release/v0.1.7 since #665 (VP-1252): lib/article-engine/source-rank.ts:107 has a comment naming the host claude-tips.blog, and the guard's model-id scan reads it as an unpriced model id.",
        "fix": "Teach the scan to skip hostnames (or comments), or reword the comment; do not add a price row for a hostname.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1313-bug-the-price-list-test-fails-on-the-release-because-it",
        "ticket": "VP-1313",
        "pr": {
          "number": 701,
          "url": "https://github.com/deepstation/vantagepost/pull/701",
          "title": "Read model ids only from code, not comments or website names, in the price-row check (VP-1313)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1313-bug-the-price-list-test-fails-on-the-release-because-it",
          "sha": "c34c990f02eeca87fcc89c60ff09146fdc1ece78",
          "ci": "none",
          "updatedAt": "2026-10-20T12:29:44Z"
        },
        "note": "merged #701 (947ad6de)",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499393350
      },
      "RMD-S41": {
        "id": "RMD-S41",
        "code": "S41",
        "wave": 5,
        "order": 1066,
        "title": "Team checkout offers to attach the new Team plan to an Enterprise workspace, which would turn it into Team",
        "issues": [],
        "rootCause": "The Team attach page lists every workspace the user owns or admins that is not already on Team (app/onboarding/team/attach/page.tsx:119 filters orgPlanTier !== \"team\"), so Enterprise workspaces are offered. Attaching runs app/api/subscriptions/team/attach/route.ts, which sets organizations.plan_tier to \"team\" (route.ts:30, :250), a paid step down from Enterprise.",
        "fix": "Leave Enterprise workspaces out of the attach list (and refuse them in the attach route), e.g. filter on walletThatPays(org) === \"user\" or isOrgPlanTier.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1312-bug-the-team-signup-page-lets-you-attach-team-to-an",
        "ticket": "VP-1312",
        "pr": {
          "number": 700,
          "url": "https://github.com/deepstation/vantagepost/pull/700",
          "title": "Keep Team from replacing an Enterprise workspace's plan on the attach page (VP-1312)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1312-bug-the-team-signup-page-lets-you-attach-team-to-an",
          "sha": "77d92688895026318d2135cb14d7d1dbe2b9d2ff",
          "ci": "none",
          "updatedAt": "2026-10-20T12:26:20Z"
        },
        "note": "PR #700 squash-merged into release/v0.1.7 (e04b3411); VP-1312 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792499186874
      },
      "RMD-S42": {
        "id": "RMD-S42",
        "code": "S42",
        "wave": 5,
        "order": 1067,
        "title": "Other keyword-research routes answer a non-member with a 500 instead of 403",
        "issues": [],
        "rootCause": "The same pattern VP-1311 fixed in clusters/[id] remains in the rest of app/api/keyword-research: they call the throwing verifyOrgMembership from lib/keyword-research (\"You do not have access to this organization\") inside a try whose catch maps only 'not found' (or nothing) to a client error, so a non-member gets 500. Routes: clusters (GET/POST), keywords (GET/POST), keywords/[id] (GET/PATCH/DELETE), keywords/recalculate, buckets (GET/POST), sessions (GET/POST), sessions/[id], discover, related, dashboard, overview, chat, recommend, recommend/stream. recommend/__tests__/route.test.ts currently asserts the 500.",
        "fix": "Use verifyOrgMembership from @/lib/auth-helpers and return forbidden() before the try, as clusters/[id] now does (PR #698). Test per route: non-member 403, member OK.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1314-bug-the-other-keyword-research-routes-return-a-server-error",
        "ticket": "VP-1314",
        "pr": {
          "number": 705,
          "url": "https://github.com/deepstation/vantagepost/pull/705",
          "title": "Answer someone outside the workspace with 403, not a server error, on the rest of the keyword research routes (VP-1314)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1314-bug-the-other-keyword-research-routes-return-a-server-error",
          "sha": "84fa70ed58c5725eee85482dde80c51d70253a98",
          "ci": "none",
          "updatedAt": "2026-10-20T12:46:47Z"
        },
        "note": "merged #705; VP-1314 Done; S43 filed for 12 routes outside keyword-research",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792500410088
      },
      "RMD-S43": {
        "id": "RMD-S43",
        "code": "S43",
        "wave": 5,
        "order": 1068,
        "title": "Article, copilot and assistant-session routes answer a non-member with a 500 instead of 403",
        "issues": [],
        "rootCause": "Found while building S42 (VP-1314). Twelve routes outside app/api/keyword-research still import the throwing verifyOrgMembership from lib/keyword-research and call it inside a try whose catch only maps a few messages (or nothing) to client errors, so a non-member gets a 500: app/api/articles/[id]/discover-keywords, app/api/articles/[id]/link-keywords, app/api/assistant-sessions, app/api/assistant-sessions/[id], app/api/copilot/articles, copilot/event-create, copilot/events-list, copilot/events, copilot/keyword-strategy, copilot/social-media, copilot/template, copilot/templates.",
        "fix": "Same as S39/S42 (PR #698 pattern): verifyOrgMembership from @/lib/auth-helpers and return forbidden() before the try. Test per route: non-member 403, member OK. Note __tests__/cross-cutting/membership-result-used.test.ts uses articles/[id]/discover-keywords as its control for a bare throwing-check call; once no bare throwing call is left, that control needs a fixture instead of a real file.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1315-bug-twelve-article-assistant-and-vince-routes-return-a",
        "ticket": "VP-1315",
        "pr": {
          "number": 706,
          "url": "https://github.com/deepstation/vantagepost/pull/706",
          "title": "Answer someone outside the workspace with 403, not a server error, on the article, assistant and Vince routes (VP-1315)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1315-bug-twelve-article-assistant-and-vince-routes-return-a",
          "sha": "d84c1d86d26f9d34e69d9305ca0ab3fb614e640e",
          "ci": "none",
          "updatedAt": "2026-10-20T12:54:25Z"
        },
        "note": "merged #706",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792500869004
      },
      "RMD-S46": {
        "id": "RMD-S46",
        "code": "S46",
        "wave": 5,
        "order": 1069,
        "title": "BUG: The PDF text-extraction integration test fails when integration tests are switched on (VP-1318)",
        "issues": [],
        "rootCause": "pdfjs-dist loads its fake worker via a dynamic import(), which jest blocks without --experimental-vm-modules, so the RUN_INTEGRATION_TESTS pdf-extract test fails.",
        "fix": "Make the test load the PDF worker in a way jest supports, without changing app extraction.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1318-bug-the-pdf-text-extraction-integration-test-fails-when",
        "ticket": "VP-1318",
        "pr": {
          "number": 707,
          "url": "https://github.com/deepstation/vantagepost/pull/707",
          "title": "Load the PDF worker the way jest allows in the PDF extraction integration test (VP-1318)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1318-bug-the-pdf-text-extraction-integration-test-fails-when",
          "sha": "6263f090c4564b2f65e09c84dc84a6d1112ed4ff",
          "ci": "none",
          "updatedAt": "2026-10-20T13:33:45Z"
        },
        "note": "Merged PR #707 (9d9df9d5); VP-1318 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792503228484
      },
      "RMD-S44": {
        "id": "RMD-S44",
        "code": "S44",
        "wave": 5,
        "order": 1070,
        "title": "A source whose page title has line breaks breaks the article's Sources list and adds a stray heading (VP-1316)",
        "issues": [],
        "rootCause": "Found in a real Engine v2 run of release/v0.1.7 (Claude Code topic): source 20's title came back as several lines with a '# Product overview' heading; buildMarkdown (lib/article-engine/build-markdown.ts) writes it into [title](url) as is, so the link breaks and a stray heading lands in the Sources list.",
        "fix": "Collapse source titles to one line of plain text when sources are saved (and defensively in buildMarkdown); fall back to the host name if nothing readable is left.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1316-bug-a-source-whose-page-title-has-line-breaks-breaks-the",
        "ticket": "VP-1316",
        "pr": {
          "number": 708,
          "url": "https://github.com/deepstation/vantagepost/pull/708",
          "title": "Write each source's title as one line of plain text in the Sources list (VP-1316)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1316-bug-a-source-whose-page-title-has-line-breaks-breaks-the",
          "sha": "03cc9c2fe6ece3eedc1061c6ace448f08fa9da41",
          "ci": "none",
          "updatedAt": "2026-10-20T13:36:09Z"
        },
        "note": "PR #708 squash-merged into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792503371796
      },
      "RMD-S45": {
        "id": "RMD-S45",
        "code": "S45",
        "wave": 5,
        "order": 1071,
        "title": "Links cited in an article keep tracking tags like ?via=, campaignId= and gh_src= (VP-1317)",
        "issues": [],
        "rootCause": "Research saves source URLs exactly as the search results gave them; samePageKey (lib/article-engine/link-address.ts) already ignores tracking/single-use tags for de-duplication but the kept link still carries them.",
        "fix": "Strip the tags samePageKey ignores when research saves a source; keep content-picking params; user-supplied links untouched.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1317-bug-links-cited-in-an-article-keep-tracking-tags-like-via",
        "ticket": "VP-1317",
        "pr": {
          "number": 709,
          "url": "https://github.com/deepstation/vantagepost/pull/709",
          "title": "Save research links without their tracking and single-use tags (VP-1317)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1317-bug-links-cited-in-an-article-keep-tracking-tags-like-via",
          "sha": "686a1bdc70e4f8f9a389288f366b8e167ca64681",
          "ci": "none",
          "updatedAt": "2026-10-20T13:42:54Z"
        },
        "note": "PR #709 squash-merged into release/v0.1.7",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792503778021
      },
      "RMD-S47": {
        "id": "RMD-S47",
        "code": "S47",
        "wave": 5,
        "order": 1072,
        "title": "BUG: The article's Sources tab still shows multi-line source titles on articles saved before VP-1316 (VP-1319)",
        "issues": [],
        "rootCause": "buildSourceList in lib/article-engine/source-list.ts shows stored source titles as-is, so articles saved before VP-1316 (#708) show multi-line titles with heading marks.",
        "fix": "Run titles through sourceTitleLine (added by #708) in buildSourceList.",
        "size": "S",
        "tags": [],
        "deps": [],
        "decisions": [],
        "kind": "side",
        "status": "merged",
        "blockedBy": [],
        "health": [],
        "lease": null,
        "branch": "micah/vp-1319-bug-the-articles-sources-tab-still-shows-multi-line-source",
        "ticket": "VP-1319",
        "pr": {
          "number": 710,
          "url": "https://github.com/deepstation/vantagepost/pull/710",
          "title": "Show source titles saved before VP-1316 on one line in the Sources tab (VP-1319)",
          "state": "closed",
          "merged": true,
          "base": "release/v0.1.7",
          "head": "micah/vp-1319-bug-the-articles-sources-tab-still-shows-multi-line-source",
          "sha": "755564853d728522932c1f7c5025cd013dc7ecc5",
          "ci": "none",
          "updatedAt": "2026-10-20T13:46:38Z"
        },
        "note": "merged as #710 (8bc12e14); VP-1319 Done",
        "verifiedAt": null,
        "verifiedBy": null,
        "verifyNote": null,
        "statusSince": 1792504004721
      }
    },
    "decisions": {
      "DEC-1": {
        "id": "DEC-1",
        "question": "Is Free a real plan? If so, what goes on its card (\"1 article + $2\")?",
        "issues": [
          32,
          48,
          49
        ],
        "status": "resolved",
        "answer": "No free plan and no trial for now. Remove Free, Start free and No card from the site and onboarding; signup goes to the paid plans. Free or a trial comes later.",
        "resolvedAt": 1792444516870,
        "by": "micah-interview"
      },
      "DEC-2": {
        "id": "DEC-2",
        "question": "Engine v2 pricing: charge for the writing calls, or keep them free and rewrite \"roughly 10 articles for $100\"?",
        "issues": [
          33
        ],
        "status": "resolved",
        "answer": "Keep the writing calls free and rewrite the article-cost copy to what articles really cost.",
        "resolvedAt": 1792444517279,
        "by": "micah-interview"
      },
      "DEC-3": {
        "id": "DEC-3",
        "question": "Free first article: waive the $0.13 outline research, or keep it and say so?",
        "issues": [
          55
        ],
        "status": "resolved",
        "answer": "Moot for now: there is no free first article without a free plan. Revisit with Free or a trial.",
        "resolvedAt": 1792444517503,
        "by": "micah-interview"
      },
      "DEC-4": {
        "id": "DEC-4",
        "question": "Overdraft: show a negative balance as owed, or stop at $0 and absorb the overshoot?",
        "issues": [
          10
        ],
        "status": "resolved",
        "answer": "Stop at $0: check the balance before a paid step and never go negative.",
        "resolvedAt": 1792444517737,
        "by": "micah-interview"
      },
      "DEC-5": {
        "id": "DEC-5",
        "question": "Which features, if any, are Enterprise-only? Nothing restricts CMS publishing today.",
        "issues": [
          34
        ],
        "status": "resolved",
        "answer": "Nothing is Enterprise-only for now; CMS stays on every plan. Revisit later.",
        "resolvedAt": 1792444517986,
        "by": "micah-interview"
      },
      "DEC-6": {
        "id": "DEC-6",
        "question": "X/Twitter: ship it (main has the newer X work) or remove it from the homepage copy?",
        "issues": [
          39
        ],
        "status": "resolved",
        "answer": "Ship X for paid plans once R0 brings main's X work into the release; keep the homepage copy.",
        "resolvedAt": 1792444518218,
        "by": "micah-interview"
      },
      "DEC-7": {
        "id": "DEC-7",
        "question": "Default new and free workspaces to 1 variation, with the cost shown first?",
        "issues": [
          58
        ],
        "status": "resolved",
        "answer": "Keep the 3-variation default for now. Revisit later.",
        "resolvedAt": 1792444518444,
        "by": "micah-interview"
      },
      "DEC-8": {
        "id": "DEC-8",
        "question": "Marketing site: help center contents, build or drop each of the 16 dead links, Vince video or rename, one signup destination that carries the plan.",
        "issues": [
          25,
          26,
          27,
          28
        ],
        "status": "resolved",
        "answer": "Build every page the links point to (Docs, Support, Contact, Status, Help, Getting started) so every homepage link works. Rename the Watch Vince work button to what it does.",
        "resolvedAt": 1792444518681,
        "by": "micah-interview"
      },
      "DEC-9": {
        "id": "DEC-9",
        "question": "Onboarding end: rename to \"Write my first article\" or go to /dashboard? Detect the time zone silently or ask, and fix existing LA orgs?",
        "issues": [
          50,
          51,
          63
        ],
        "status": "resolved",
        "answer": "Rename the last button to Write my first article and keep sending people to the writer. New workspaces take their time zone from the browser; existing ones stay as they are.",
        "resolvedAt": 1792444518873,
        "by": "micah-interview"
      }
    },
    "sources": {
      "github": {
        "ok": true,
        "lastOk": 1792508918251,
        "lastTry": 1792508918251,
        "error": null
      },
      "sync": {
        "lastRun": 1792508918251,
        "trigger": "cron",
        "durationMs": 1203
      }
    },
    "gap": {
      "mainAheadBy": 2,
      "releaseAheadBy": 623,
      "checkedAt": 1792508918251
    },
    "alerts": [],
    "updatedAt": 1792509001553
  },
  "events": [
    {
      "ts": 1792508485627,
      "item": "RMD-V1",
      "type": "info",
      "msg": "V1: fix-0079 (VP-1320): PR #714 CI Build and Type Check still running after 9 min; still polling",
      "actor": "fix-0079"
    },
    {
      "ts": 1792507928538,
      "item": "RMD-V1",
      "type": "info",
      "msg": "V1: fix-0079 (VP-1320): PR #714 into staging opened (release incl. #712 + #713, no conflicts, tsc + test typecheck clean). Waiting on CI.",
      "actor": "fix-0079"
    },
    {
      "ts": 1792507804801,
      "item": "RMD-V1",
      "type": "info",
      "msg": "V1: fix-0079: PR #713 (VP-1322) squash-merged into release/v0.1.7; VP-1323 (#712) already merged. Starting VP-1320 part 2: merge release onto a branch off staging",
      "actor": "fix-0079"
    },
    {
      "ts": 1792507218145,
      "item": "RMD-E3",
      "type": "info",
      "msg": "E3: fix-0079 (VP-1322): PR #713 open into release/v0.1.7 (https://github.com/deepstation/vantagepost/pull/713). tsc clean, migration-order OK, cross-cutting 55/55 suites green. No dashboard item exists for VP-1322, so the PR carries no Remediation line (so it doesn't relink E3). Waiting on CI, then squash-merge.",
      "actor": "fix-0079"
    },
    {
      "ts": 1792507090117,
      "item": "RMD-E3",
      "type": "info",
      "msg": "E3: fix-0079 (VP-1322): scratch DBs pass — on vp_scratch_0079a the new 0079 merged 3 duplicates and built the index; the result is row-for-row identical to running scripts/merge-duplicate-clusters.ts --apply on vp_scratch_0079b; on b (no duplicates left) 0079 changed nothing. Committing, then tsc + migration-order check + cross-cutting guards",
      "actor": "fix-0079"
    },
    {
      "ts": 1792507073353,
      "type": "done",
      "msg": "VP-1323 merged: PR #712 squash-merged into release/v0.1.7 (7f11e29f). typecheck:tests exit 0, tsc clean, 61/61 tests in the two files, cross-cutting guards 55/55 suites green.",
      "actor": "build-vp1323"
    },
    {
      "ts": 1792506937058,
      "type": "log",
      "msg": "VP-1323: typed the parsed page as Document in the import route test and gave the pre-status product a full OrganizationProduct type in the product-promotion test. typecheck:tests now exits 0 for the whole repo. Running the two files tests.",
      "actor": "build-vp1323"
    },
    {
      "ts": 1792506896101,
      "item": "RMD-E3",
      "type": "info",
      "msg": "E3: fix-0079 (VP-1322): wrote the merge into 0079 as a DO block that mirrors mergeClusterInto step for step, ahead of CREATE UNIQUE INDEX; installing deps in the worktree to test on scratch DBs",
      "actor": "fix-0079"
    },
    {
      "ts": 1792506775728,
      "type": "log",
      "msg": "VP-1323 (not on board): fixing 5 type errors in two test files so typecheck:tests passes. Worktree created; running bun install.",
      "actor": "build-vp1323"
    },
    {
      "ts": 1792506773745,
      "item": "RMD-E3",
      "type": "info",
      "msg": "E3: fix-0079 (VP-1322): read VP-1322 + VP-1320; worktree vp-1322 cut from release/v0.1.7; porting merge-duplicate-clusters service into migration 0079 as SQL ahead of the unique index",
      "actor": "fix-0079"
    },
    {
      "ts": 1792504005057,
      "item": "RMD-S47",
      "type": "release",
      "msg": "S47: released by build-s47: merged as #710 (8bc12e14); VP-1319 Done",
      "actor": "build-s47"
    },
    {
      "ts": 1792504004906,
      "item": "RMD-S47",
      "type": "done",
      "msg": "S47: PR #710 squash-merged into release/v0.1.7 (8bc12e14). VP-1319 set to Done. Releasing the lease.",
      "actor": "build-s47"
    },
    {
      "ts": 1792504004721,
      "item": "RMD-V1",
      "type": "status",
      "msg": "V1: blocked → ready",
      "actor": "sync"
    },
    {
      "ts": 1792504004721,
      "item": "RMD-S47",
      "type": "status",
      "msg": "S47: in review → merged",
      "actor": "sync"
    },
    {
      "ts": 1792503990112,
      "item": "RMD-S47",
      "type": "log",
      "msg": "S47: Pushed and opened PR #710 into release/v0.1.7. tsc exit 0; cross-cutting guards 55/55 suites green on the branch (up to date with release d927adb7). Merging next.",
      "actor": "build-s47"
    },
    {
      "ts": 1792503988207,
      "item": "RMD-S47",
      "type": "status",
      "msg": "S47: claimed → in review",
      "actor": "build-s47"
    },
    {
      "ts": 1792503988207,
      "item": "RMD-S47",
      "type": "note",
      "msg": "S47: PR #710 open; tsc 0, guards green",
      "actor": "build-s47"
    },
    {
      "ts": 1792503988207,
      "item": "RMD-S47",
      "type": "pr",
      "msg": "S47: PR #710 opened",
      "actor": "build-s47"
    },
    {
      "ts": 1792503988207,
      "item": "RMD-S47",
      "type": "branch",
      "msg": "S47: branch micah/vp-1319-bug-the-articles-sources-tab-still-shows-multi-line-source",
      "actor": "build-s47"
    },
    {
      "ts": 1792503888103,
      "item": "RMD-S47",
      "type": "note",
      "msg": "S47: fix in, article-engine tests green; tsc next",
      "actor": "build-s47"
    },
    {
      "ts": 1792503887970,
      "item": "RMD-S47",
      "type": "log",
      "msg": "S47: Tests first: 4 new cases in lib/article-engine/__tests__/source-list.test.ts failed on release (title came back as stored, # Print stayed). Fix in lib/article-engine/source-list.ts buildSourceList: the stored title goes through sourceTitleLine before displayTitle judges it. Now 48/48 in the two source suites and 969/969 across lib/article-engine. Running tsc.",
      "actor": "build-s47"
    },
    {
      "ts": 1792503878434,
      "item": "RMD-S47",
      "type": "status",
      "msg": "S47: in progress → claimed",
      "actor": "sync"
    },
    {
      "ts": 1792503878434,
      "item": "RMD-S47",
      "type": "branch",
      "msg": "S47: branch micah/vp-1319-bug-the-articles-sources-tab-still-shows-multi-line-source no longer exists on GitHub; cleared",
      "actor": "healer"
    },
    {
      "ts": 1792503847258,
      "item": "RMD-S47",
      "type": "log",
      "msg": "S47: Evidence holds on release d927adb7: buildSourceList takes source.title as stored (trim only) and passes it to displayTitle, so a pre-VP-1316 title with newlines and # marks shows as is. Plan: flatten with sourceTitleLine before displayTitle, keeping the URL-based fallback for titles with nothing readable. Worktree vp-1319 made; running bun install.",
      "actor": "build-s47"
    },
    {
      "ts": 1792503847098,
      "item": "RMD-S47",
      "type": "status",
      "msg": "S47: claimed → in progress",
      "actor": "build-s47"
    },
    {
      "ts": 1792503847098,
      "item": "RMD-S47",
      "type": "note",
      "msg": "S47: worktree made off release d927adb7",
      "actor": "build-s47"
    },
    {
      "ts": 1792503847098,
      "item": "RMD-S47",
      "type": "branch",
      "msg": "S47: branch micah/vp-1319-bug-the-articles-sources-tab-still-shows-multi-line-source",
      "actor": "build-s47"
    },
    {
      "ts": 1792503825208,
      "item": "RMD-S47",
      "type": "log",
      "msg": "S47: Added S47 for VP-1319 and claimed it. Read the ticket: run Sources-tab titles through sourceTitleLine in buildSourceList. Re-checking the code next.",
      "actor": "build-s47"
    },
    {
      "ts": 1792503825050,
      "item": "RMD-S47",
      "type": "note",
      "msg": "S47: ticket read",
      "actor": "build-s47"
    },
    {
      "ts": 1792503825050,
      "item": "RMD-S47",
      "type": "ticket",
      "msg": "S47: ticket VP-1319",
      "actor": "build-s47"
    },
    {
      "ts": 1792503824907,
      "item": "RMD-S47",
      "type": "status",
      "msg": "S47: ready → claimed",
      "actor": "build-s47"
    },
    {
      "ts": 1792503824907,
      "item": "RMD-S47",
      "type": "claim",
      "msg": "S47: claimed by build-s47",
      "actor": "build-s47"
    },
    {
      "ts": 1792503824767,
      "item": "RMD-V1",
      "type": "status",
      "msg": "V1: ready → blocked",
      "actor": "build-s47"
    },
    {
      "ts": 1792503824767,
      "item": "RMD-S47",
      "type": "added",
      "msg": "S47 added by build-s47: BUG: The article's Sources tab still shows multi-line source titles on articles saved before VP-1316 (VP-1319)",
      "actor": "build-s47"
    },
    {
      "ts": 1792503778361,
      "item": "RMD-S45",
      "type": "done",
      "msg": "S45: PR #709 squash-merged into release/v0.1.7; VP-1317 set Done. S44 and S45 both merged",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503778203,
      "item": "RMD-S45",
      "type": "release",
      "msg": "S45: released by build-s44-s45: PR #709 squash-merged into release/v0.1.7",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503778021,
      "item": "RMD-V1",
      "type": "status",
      "msg": "V1: blocked → ready",
      "actor": "sync"
    },
    {
      "ts": 1792503778021,
      "item": "RMD-S45",
      "type": "status",
      "msg": "S45: in review → merged",
      "actor": "sync"
    },
    {
      "ts": 1792503764720,
      "item": "RMD-S45",
      "type": "status",
      "msg": "S45: in progress → in review",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503764720,
      "item": "RMD-S45",
      "type": "note",
      "msg": "S45: PR #709 open",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503764720,
      "item": "RMD-S45",
      "type": "pr",
      "msg": "S45: PR #709 opened",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503743475,
      "item": "RMD-S45",
      "type": "log",
      "msg": "S45: Pushed. tsc 0; article-engine 1046 passed; related 1912 passed; cross-cutting guards 55/55 green on latest release. Opening PR",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503741815,
      "item": "RMD-S45",
      "type": "status",
      "msg": "S45: claimed → in progress",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503741815,
      "item": "RMD-S45",
      "type": "note",
      "msg": "S45: pushed; tsc 0; article-engine 76/76; related 140/140; cross-cutting 55/55",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503741815,
      "item": "RMD-S45",
      "type": "branch",
      "msg": "S45: branch micah/vp-1317-bug-links-cited-in-an-article-keep-tracking-tags-like-via",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503476657,
      "item": "RMD-S45",
      "type": "log",
      "msg": "S45: Fix: link-address.ts gets stripSingleUseTags (same rule samePageKey ignores, now incl. gh_src, campaignId, messageTypeId, and medium/source/content only beside a campaign id); research.ts saves links through it. Updated the VP-1296 test that asserted the ?os=0 tag was kept (the behavior this ticket reverses). Running tsc",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503476524,
      "item": "RMD-S45",
      "type": "note",
      "msg": "S45: fix in place: stripSingleUseTags in link-address.ts shares one tag rule with samePageKey; research saves through it. Running tsc + article-engine tests",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503439012,
      "item": "RMD-S45",
      "type": "log",
      "msg": "S45: Evidence re-checked: cleanResearchSources keeps the link as found (only utm-style tracking stripped). Note: samePageKey does NOT yet ignore gh_src or the help-centre campaignId/medium/source set, so those are added to the single shared tag rule. Wrote research-link-tags.test.ts from run sources 2,3,5,12,16,4; running it before the fix",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503377879,
      "item": "RMD-S45",
      "type": "note",
      "msg": "S45: claimed; ticket read",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503377879,
      "item": "RMD-S45",
      "type": "ticket",
      "msg": "S45: ticket VP-1317",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503377665,
      "item": "RMD-S45",
      "type": "status",
      "msg": "S45: ready → claimed",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503377665,
      "item": "RMD-S45",
      "type": "claim",
      "msg": "S45: claimed by build-s44-s45",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503372107,
      "item": "RMD-S44",
      "type": "done",
      "msg": "S44: PR #708 squash-merged into release/v0.1.7; VP-1316 set Done. Starting S45 (VP-1317)",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503371976,
      "item": "RMD-S44",
      "type": "release",
      "msg": "S44: released by build-s44-s45: PR #708 squash-merged into release/v0.1.7",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503371796,
      "item": "RMD-S44",
      "type": "status",
      "msg": "S44: in review → merged",
      "actor": "sync"
    },
    {
      "ts": 1792503356699,
      "item": "RMD-S44",
      "type": "done",
      "msg": "S44: PR #708 open into release/v0.1.7. Linking it on VP-1316, then squash-merging",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503354589,
      "item": "RMD-S44",
      "type": "status",
      "msg": "S44: in progress → in review",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503354589,
      "item": "RMD-S44",
      "type": "note",
      "msg": "S44: PR #708 open",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503354589,
      "item": "RMD-S44",
      "type": "pr",
      "msg": "S44: PR #708 opened",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503333276,
      "item": "RMD-S44",
      "type": "log",
      "msg": "S44: Pushed branch. tsc 0; article-engine tests 1039 passed; related tests 1696 passed; cross-cutting guards 55/55 green after merging latest release. Opening PR",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503331331,
      "item": "RMD-S44",
      "type": "status",
      "msg": "S44: claimed → in progress",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503331331,
      "item": "RMD-S44",
      "type": "note",
      "msg": "S44: pushed; tsc 0, article-engine 75/75 suites, related 121/121, cross-cutting 55/55",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503331331,
      "item": "RMD-S44",
      "type": "branch",
      "msg": "S44: branch micah/vp-1316-bug-a-source-whose-page-title-has-line-breaks-breaks-the",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503233053,
      "item": "RMD-S46",
      "type": "release",
      "msg": "S46: released by build-s46: Merged PR #707 (9d9df9d5); VP-1318 Done",
      "actor": "build-s46"
    },
    {
      "ts": 1792503232903,
      "item": "RMD-S46",
      "type": "note",
      "msg": "S46: PR #707 squash-merged into release/v0.1.7 as 9d9df9d5. VP-1318 set Done. Releasing S46.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503232703,
      "item": "RMD-S46",
      "type": "done",
      "msg": "S46: PR #707 squash-merged into release/v0.1.7 as 9d9df9d5. VP-1318 set Done. Releasing S46.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503228484,
      "item": "RMD-S46",
      "type": "status",
      "msg": "S46: in review → merged",
      "actor": "sync"
    },
    {
      "ts": 1792503212626,
      "item": "RMD-S46",
      "type": "note",
      "msg": "S46: Pushed and opened PR #707 into release/v0.1.7: https://github.com/deepstation/vantagepost/pull/707. Guards 55/55 green. Linking it on VP-1318, then merging.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503212436,
      "item": "RMD-S46",
      "type": "done",
      "msg": "S46: Pushed and opened PR #707 into release/v0.1.7: https://github.com/deepstation/vantagepost/pull/707. Guards 55/55 green. Linking it on VP-1318, then merging.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503210391,
      "item": "RMD-S46",
      "type": "status",
      "msg": "S46: claimed → in review",
      "actor": "build-s46"
    },
    {
      "ts": 1792503210391,
      "item": "RMD-S46",
      "type": "note",
      "msg": "S46: PR #707 open; tsc 0, integration on 9/9, off 8+1 skipped, guards 55/55",
      "actor": "build-s46"
    },
    {
      "ts": 1792503210391,
      "item": "RMD-S46",
      "type": "pr",
      "msg": "S46: PR #707 opened",
      "actor": "build-s46"
    },
    {
      "ts": 1792503210391,
      "item": "RMD-S46",
      "type": "branch",
      "msg": "S46: branch micah/vp-1318-bug-the-pdf-text-extraction-integration-test-fails-when",
      "actor": "build-s46"
    },
    {
      "ts": 1792503202893,
      "item": "RMD-S44",
      "type": "log",
      "msg": "S44: tsc exit 0. Running the article-engine tests (lib/article-engine + __tests__/article-engine), one worker",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503127673,
      "item": "RMD-S46",
      "type": "note",
      "msg": "S46: Committed 6263f090; branch is level with release/v0.1.7. tsc exit 0. Running the cross-cutting guards before push/merge.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503127363,
      "item": "RMD-S46",
      "type": "log",
      "msg": "S46: Committed 6263f090; branch is level with release/v0.1.7. tsc exit 0. Running the cross-cutting guards before push/merge.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503078666,
      "item": "RMD-S44",
      "type": "note",
      "msg": "S44: fix in place (sourceTitleLine in source-list.ts, used by research save + buildMarkdown); new test passes; running tsc",
      "actor": "build-s44-s45"
    },
    {
      "ts": 1792503077550,
      "item": "RMD-S46",
      "type": "note",
      "msg": "S46: Fix in the test file only: provideBundledPdfWorker() loads pdf-parse's bundled pdf.worker.mjs through Node's real loader (process.getBuiltinModule, because jest replaces module.createRequire) and sets",
      "actor": "build-s46"
    },
    {
      "ts": 1792503077340,
      "item": "RMD-S46",
      "type": "log",
      "msg": "S46: Fix in the test file only: provideBundledPdfWorker() loads pdf-parse's bundled pdf.worker.mjs through Node's real loader (process.getBuiltinModule, because jest replaces module.createRequire) and sets globalThis.pdfjsWorker so pdf.js skips its dynamic import. Also asserts the text contains 'HP OfficeJet Pro 9125e'. Integration run now 9/9. Running integration on, integration off, and tsc.",
      "actor": "build-s46"
    },
    {
      "ts": 1792503052293,
      "item": "RMD-S44",
      "type": "log",
      "msg": "S44: Evidence re-checked: buildMarkdown writes s.title raw; research saves it via cleanResearchSources. Wrote source-title-line.test.ts with run sources 19-20; running it before the fix",
      "actor": "build-s44-s45"
    }
  ],
  "meta": {
    "waves": [
      {
        "n": 0,
        "name": "Release blocker",
        "why": "Lands first. Several fixes touch the same files."
      },
      {
        "n": 1,
        "name": "Stop the harm",
        "why": "Invented facts that get published, wrong money, public draft data, wrong statuses."
      },
      {
        "n": 2,
        "name": "Plans, pricing and onboarding",
        "why": "Paid plans only for now, honest pricing copy, X for paid plans, onboarding fixes."
      },
      {
        "n": 3,
        "name": "Better sources",
        "why": "The PDF's top priority, and the deepest engine work."
      },
      {
        "n": 4,
        "name": "Keyword quality",
        "why": "14 issues collapse into 4 fixes."
      },
      {
        "n": 5,
        "name": "Site, polish and side tickets",
        "why": "Every linked page built, layout and accessibility, found issues, and the parked items."
      },
      {
        "n": 6,
        "name": "Prove it",
        "why": "The full list, re-run."
      }
    ],
    "issues": [
      {
        "n": 12,
        "text": "Fact check flags the article's own source as 'not retrieved'; '6/6 live' next to 6 warnings",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 18,
        "text": "Research misses the most relevant page even with domains restricted",
        "severity": "High",
        "verdict": "Likely",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 41,
        "text": "Knowledge library shows READY with 0 chunks",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 56,
        "text": "Writer invents statistics; article stays Complete",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 57,
        "text": "Flagged invented stats copied into social posts",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 75,
        "text": "No authority ranking; canonical docs never retrieved",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 78,
        "text": "Citations attached to the wrong page",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 8,
        "text": "Source listed under its Chinese title",
        "severity": "Medium",
        "verdict": "Likely",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 19,
        "text": "Fact-check note contradicts itself",
        "severity": "Medium",
        "verdict": "Likely",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 77,
        "text": "HTTP 403 shown as broken link",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 76,
        "text": "Asked for 20 sources, got 18, no explanation",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 40,
        "text": "Vibe Code promoted as a live course",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 1,
        "text": "Outline uses the brief's first line as title, ignores 70 chars",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 7,
        "text": "Pull quote appears twice",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 9,
        "text": "Same product pushed every piece; generic CTA",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 13,
        "text": "Meta title cut mid-sentence",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 16,
        "text": "82/70 title accepted before the paid step",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 5,
        "text": "New drafts show green Published badge",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 21,
        "text": "Generation fails silently; failed run charged",
        "severity": "High",
        "verdict": "Fixed",
        "evidence": "3-social.md"
      },
      {
        "n": 22,
        "text": "Story templates invent company anecdotes",
        "severity": "High",
        "verdict": "Likely",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 39,
        "text": "No way to connect X though homepage promises it",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 4,
        "text": "Variation preview shows only LinkedIn",
        "severity": "Medium",
        "verdict": "Likely",
        "evidence": "3-social.md"
      },
      {
        "n": 20,
        "text": "Draft images at public S3 links with org ID",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 23,
        "text": "Post cut off mid-word ('#DeepS')",
        "severity": "Medium",
        "verdict": "Fixed",
        "evidence": "2-writer-ai-content.md"
      },
      {
        "n": 42,
        "text": "Schedule offered with no account connected",
        "severity": "Medium",
        "verdict": "Fixed",
        "evidence": "3-social.md"
      },
      {
        "n": 58,
        "text": "Default 3 variations cost $0.27",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 59,
        "text": "Keyword strategy banner sends free users to paywall",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 60,
        "text": "Near-duplicate keywords not merged",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 61,
        "text": "Every keyword has Medium priority",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 64,
        "text": "Strategy wizard has no entry point once dismissed",
        "severity": "Medium",
        "verdict": "Likely",
        "evidence": "5-keywords.md"
      },
      {
        "n": 65,
        "text": "Wizard ignores existing clusters",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 67,
        "text": "A third of new keywords are close variants",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 70,
        "text": "Research chat surfaces other brands' terms",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 71,
        "text": "Existing-keyword lookup capped at 200",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 73,
        "text": "'Write NOW' goes to tiny KD-0 keywords",
        "severity": "Medium",
        "verdict": "Likely",
        "evidence": "5-keywords.md"
      },
      {
        "n": 66,
        "text": "Territory cards show no volume or KD",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 68,
        "text": "Wizard reports 80 keywords; only 70 new",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 69,
        "text": "'Untitled Session - Invalid Date'",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 72,
        "text": "Volume disappears between chat steps",
        "severity": "Low",
        "verdict": "Likely",
        "evidence": "5-keywords.md"
      },
      {
        "n": 74,
        "text": "Wizard, chat and planner disagree on clusters",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "5-keywords.md"
      },
      {
        "n": 32,
        "text": "'Free' promised but /pricing has no Free card",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 47,
        "text": "Website field accepts bare domain, then blocks Create",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 25,
        "text": "Help is a mailto; /help, /docs 404",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 26,
        "text": "16 dead homepage links",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 29,
        "text": "Signup page says only 'Sign in'",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 30,
        "text": "Terms and Privacy are plain text",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 33,
        "text": "'Roughly 10 articles' vs ~$0.20 per article",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 36,
        "text": "'Up next' shows Aug items as Queued",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 37,
        "text": "'Social posts: 6 scheduled' when all drafts",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "3-social.md"
      },
      {
        "n": 38,
        "text": "Checklist skips social connect; 'unlock publishing'",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 45,
        "text": "AI research returns products with no URLs",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 48,
        "text": "Free option is a small link under paid cards",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 50,
        "text": "'Start Creating' promised; last button 'Go to Dashboard'",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 52,
        "text": "$100/month upsell seconds after choosing free",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 53,
        "text": "'Research is charged' copy shown to free users",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 54,
        "text": "Red Low balance after one outline",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 27,
        "text": "'Watch Vince work' has no video",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 28,
        "text": "Two footers; signup CTAs differ; plan dropped",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 31,
        "text": "90px blank space in signup form",
        "severity": "Low",
        "verdict": "Likely",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 34,
        "text": "CMS listed as Creator and Enterprise",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 35,
        "text": "'Good morning, there'; bad possessive",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 43,
        "text": "Progress bar 4 steps, card lists 3",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 44,
        "text": "Hamburger covers step 1; can leave onboarding",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 46,
        "text": "Competitor research suggests Buildspace",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "1-sources-citations.md"
      },
      {
        "n": 49,
        "text": "Free credits never quantified",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 51,
        "text": "'Go to Dashboard' opens the article writer",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 10,
        "text": "Purchased balance -$0.20; totals disagree",
        "severity": "High",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 24,
        "text": "No per-action cost history",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 55,
        "text": "Free first article charged $0.13 for outline",
        "severity": "Medium",
        "verdict": "Confirmed",
        "evidence": "4-billing-plans.md"
      },
      {
        "n": 62,
        "text": "Duplicate topic; title in Cluster column",
        "severity": "Low",
        "verdict": "Likely",
        "evidence": "5-keywords.md"
      },
      {
        "n": 63,
        "text": "Calendar defaults to Los Angeles",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 3,
        "text": "Side panel unreachable at ~800px",
        "severity": "Medium",
        "verdict": "Live",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 2,
        "text": "Hamburger overlaps modal headers",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 6,
        "text": "Vince button covers Share",
        "severity": "Low",
        "verdict": "Likely",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 11,
        "text": "Domains input has no accessible label",
        "severity": "Low",
        "verdict": "NR",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 14,
        "text": "Tab title stale after title change",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 15,
        "text": "Tabs and icon buttons lack accessible names",
        "severity": "Low",
        "verdict": "Confirmed",
        "evidence": "6-onboarding-site-ui.md"
      },
      {
        "n": 17,
        "text": "Sticky step bar covers title while writing",
        "severity": "Low",
        "verdict": "Likely",
        "evidence": "6-onboarding-site-ui.md"
      }
    ],
    "closedOnRelease": [
      21,
      42,
      23
    ]
  }
}