From 4f2ee456d1e3718d4354265bf476c701fd22a608 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Sat, 22 Aug 2026 10:22:37 +0200 Subject: [PATCH] Session close: preserve the repositioned copy, sync the ledger, record the one red The repositioned pilot copy lived only in a scratchpad that dies with the session, so it is now 20.09 with its apply checklist and the three claims still awaiting Paul. Ledger carries the positioning change, #566's result, and the residual Linux failure with the evidence that it is a stale baseline rather than flake - plus the two wrong diagnoses it defeated, so the next session does not repeat them. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011SP5gaqXEgUie8pdFrmbeJ --- .okf/log.md | 22 ++ .../20.06-clean-slate-v2-plan.md | 5 +- .../20.09-repositioned-pilot-copy.md | 316 ++++++++++++++++++ 3 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 docs/projects/2608-site-design-system/20-29-strategy/20.09-repositioned-pilot-copy.md diff --git a/.okf/log.md b/.okf/log.md index 68b716737..35860e9bb 100644 --- a/.okf/log.md +++ b/.okf/log.md @@ -51,6 +51,28 @@ make it green: restructure same-day entries under one heading, and add `timestamp` to the 23 concepts missing it (anchored to each file's last commit time, which is verifiable - never invented). +## 2026-08-22 - a re-record that fixed 21 of 22, and the one it could not + +#566 merged: 127 baselines re-recorded and the tolerance shield deleted. CI +Linux red went from 22 keys to 1. The residual, `mobile/blog/index/_pagination`, +is worth its own note because it defeated two wrong diagnoses in a row. + +**It is not flake.** Two runs of the same job returned difference_level +0.03960763888888889 to sixteen decimals. This file's own rule says identical +difference_levels across runs mean a stale committed baseline, not flaky +rendering - and that rule held, against an intuition that said otherwise (the +key had just been re-recorded 35 minutes earlier, which FEELS like flake). +A run-level `conclusion: success` was also misread as a passing re-run; the +job-level conclusion was `failure`. **Read the job, not the run.** + +**What it probably is, unverified:** the `workflow_dispatch` record path and +the `pull_request` test path build the site differently, so the baseline was +captured from a page the test run never renders. Blog-index pagination is +driven by the post count, which is exactly the kind of thing a draft-handling +difference would move. Whoever picks this up: diff the two runs' build steps +before touching a baseline. Re-recording it again without that answer just +buys the same failure at a different sha. + ## 2026-08-21 - three register pilots shipped; the comparison is controlled; Editorial recommended All three register pilots merged on the /next/ rail (#561 rescue-room, #562 diff --git a/docs/projects/2608-site-design-system/20-29-strategy/20.06-clean-slate-v2-plan.md b/docs/projects/2608-site-design-system/20-29-strategy/20.06-clean-slate-v2-plan.md index 330c47b65..360be9510 100644 --- a/docs/projects/2608-site-design-system/20-29-strategy/20.06-clean-slate-v2-plan.md +++ b/docs/projects/2608-site-design-system/20-29-strategy/20.06-clean-slate-v2-plan.md @@ -157,7 +157,10 @@ same commit · browser-measured AA + seams on anything touching a rendered page. | Pilot C (Engineered Precision) | **MERGED** #563 (`45780ad6f`); DOM-verified copy parity across all three | — | | Lightning demo | **BOARD LIVE** — `20.08`: pilot vote B 2/C 1/A 1; artifact head-to-head Editorial 4–1; fable rec = Editorial + graft package | **PAUL PICKS** on the live /next/ URLs | | Visual-gate repair | #560 merged (`e1882483c`): tolerance 0.0001 (was 50x blind), shield documented, fossilization + viewport-only + perceptual-floor documented; machine exonerated (reds = #540-stale baselines) | follow-ups: re-record ~36 macOS + 22-key Linux dispatch; below-fold coverage | -| Homepage build (Editorial) | Blueprint ready (CD `8eb98dd6` Homepage.dc.html, team section removed) | GATED on Paul: audit-exhibit sourcing (real/SAMPLE/rebuild) + "code audit" offer naming | +| Homepage build (Editorial) | Blueprint ready (CD `8eb98dd6` Homepage.dc.html, team section removed) | GATED on Paul: audit-exhibit sourcing (real/SAMPLE/rebuild) + "code audit" offer naming + its "Three ways in" section contradicts one-offer positioning | +| **POSITIONING CHANGED 2026-08-21** | Site sells ONE thing: an embedded team of senior self-managed full-stack developers. **No fractional-CTO / tech-lead title claims** (factual-accuracy rule). Pilot copy rewritten + canon-verified but NOT APPLIED - `20.09` | FIRST TASK NEXT SESSION: apply 20.09 to all three stubs, rename to `embedded-team`, re-record 6+6 baselines | +| Visual gate: baselines | **#566 MERGED** (`6420e644e`): 127 baselines re-recorded (50 macOS classified by pixel-transition histogram, 77 Linux CI-recorded then screened), SECTION_CONFIGS shield deleted on a measurement. macOS suite GREEN - first time since #540. CI Linux red went 22 keys -> 1 | see the residual row below | +| KNOWN RED: `linux/mobile/blog/index/_pagination` | Fails at difference_level **0.03960763888888889, IDENTICAL across two runs** - so per CLAUDE.md's own tell it is a stale/wrong committed baseline, NOT flake. It was already red before #566 and the CI re-record did not fix it; root cause NOT diagnosed (suspect: the `update-baselines` dispatch and the `pull_request` run build the page differently - e.g. draft handling changing the post count that drives pagination) | own investigation; do not whack-a-mole re-record | | PR-1: v2 rail | **MERGED** #555 (`703fee12c`) — rail live: `/next/` noindexed staging, qtest holes closed (root layouts + v2 registry-derived keys), ADR-0006, mermaid source-aware. Screenshot job red = the documented 16-key #540 handoff only, verified key-by-key. | — | | PR-2: styled pilot | **MERGED** #557 (`38f744805`) — full content ported (overview/faqs/tenure-derived stats), styled per D1, canon-exact Clutch proof line, browser-verified AA (button 5.13:1), −85.6% gzip CSS vs legacy page. Screenshot red = the same 16-key #540 handoff set, verified key-by-key. | compare links: `/next/services/fractional-cto/` vs `/services/fractional-cto/` | | PR-3: flip | BLOCKED on lightning-demo winner + Paul's live review | flip = `type: next` on the real page + delete stub; checklist in ADR-0006 §5 | diff --git a/docs/projects/2608-site-design-system/20-29-strategy/20.09-repositioned-pilot-copy.md b/docs/projects/2608-site-design-system/20-29-strategy/20.09-repositioned-pilot-copy.md new file mode 100644 index 000000000..c4e2adf4e --- /dev/null +++ b/docs/projects/2608-site-design-system/20-29-strategy/20.09-repositioned-pilot-copy.md @@ -0,0 +1,316 @@ +# 20.09 - Repositioned pilot copy (one offer, no title claims) + +**Status: DRAFTED, NOT APPLIED.** Written 2026-08-21 against Paul's positioning +decision of the same day; the three pilot stubs still carry the old +fractional-CTO copy. Applying it is the first task of the next session - see +the checklist at the end of this file. + +**The decision it implements** (Paul, 2026-08-21, verbatim): "The website sells +one thing: an embedded team of senior self-managed full-stack developers who +drive the development while the client runs the rest of the business. Chosen +over migration assurance, CRA, SOC 2 and umbrella positioning because it is the +only offer that has ever converted - Crosslake and Framework.fm are both placed +senior people, and every canon proof point (tenure, retention, five-year +relationships) is evidence for exactly this claim. **No fractional-CTO or +tech-lead title claims:** Paul was the lead tech at Crosslake, a PM opened the +engagement, and leadership was promoted from inside the team. Migration +assurance stays off the site until the r/msp test converts; /vibe-code-rescue +remains an SEO lander only." + +The title-claim ban is a FACTUAL-ACCURACY rule, not a style preference - the +same class as a fabricated testimonial. Verified before filing: the YAML block +below contains zero title claims and zero non-canon numbers. + +--- + + +Target files (all three carry byte-identical copy today; only `title`, +`description`, `register` and `font` differ): + +- `content/next/pilots/rescue-room/fractional-cto.md` +- `content/next/pilots/editorial/fractional-cto.md` +- `content/next/pilots/precision/fractional-cto.md` + +## Slug + +Rename the three files to `embedded-team.md`, giving +`/next/pilots//embedded-team/`. + +`test/unit/next_rail_test.rb` globs `next/pilots/**/index.html`, so the rename +is safe. `layouts/next/landing.html` keys the skin off `register`, not the +filename, so nothing else moves. + +## Title / description pattern + +The three stubs stay identical except for register: + +```yaml +title: Embedded senior team (Rescue Room pilot) +description: Design-register pilot A - warm humanist "Rescue Room" skin over the one-offer embedded-team landing anatomy. +``` + +```yaml +title: Embedded senior team (Editorial pilot) +description: Design-register pilot B - "Artifact Editorial" skin over the one-offer embedded-team landing anatomy. Same copy as pilot A; only the register differs. +``` + +```yaml +title: Embedded senior team (Precision pilot) +description: Design-register pilot C - "Engineered Precision" skin over the one-offer embedded-team landing anatomy. Same copy as pilots A and B; only the register differs. +``` + +## Paste-ready copy block + +Everything from `nav` down is identical across the three stubs. The four keys +above (`title`, `description`, `register`, `font`) keep their per-register +values. + +```yaml +nav: + links: + - name: Services + url: /services/ + - name: Use Cases + url: /use-cases/ + - name: Blog + url: /blog/ + - name: Course + url: /course/tech-for-non-technical-founders-2026/ + - name: Clients + url: /clients/ + cta: + name: Book a free consultation + url: /free-consultation/ + +hero: + eyebrow: An embedded senior team + headline: A senior development team you don't have to manage + subhead: Your last dev shop needed chasing, and you still couldn't tell whether the work was real. This one takes it from there and tells you every Friday what changed. + primary: + name: Book a free consultation + url: /free-consultation/ + secondary: + name: Book a 30-min call + url: /contact-us/ + derisk: You keep the written assessment whether or not we work together. + # Markdown, rendered inline - the bold carries the emphasis the blueprint + # gave . Clutch rating is linked to the profile (claims-canon). + stats: + - "**8+ years** average developer experience" + - No standups on your calendar + - "[**4.8**/5 on Clutch](https://clutch.co/profile/jetthoughts)" + +monthOne: + headline: What the team does in month one + items: + - Reads the codebase and tells you what state it's actually in + - Takes over the work in flight and finishes what's worth finishing + - Decides what gets rebuilt and what you can live with + - Writes the technical half of your investor update + - A Friday report from week one, in plain English + +comparison: + eyebrow: The choice + headline: The other option is building the team yourself + fractionalLabel: An embedded team + fulltimeLabel: Hiring in-house + rows: + - label: Getting started + fractional: You don't hire anyone. The team already works together. + fulltime: A job post, a hiring round, and a technical call you can't run. + - label: Who runs the day to day + fractional: They do. Work gets picked up, sequenced and shipped without you in the room. + fulltime: You do, or you hire someone else to. + - label: Telling if it's going well + fractional: You read the Friday report and click through what shipped. + fulltime: Nothing tells you whether the work is good except the people doing it. + - label: If it isn't working + fractional: You end the contract. + fulltime: Severance, then back to hiring. + - label: Best when + fractional: There's nobody technical inside and the product still has to move. + fulltime: You want these people on your payroll for the long haul. + +steps: + eyebrow: How it starts + headline: Four steps from first email to a plan you can act on + intro: You don't sign anything to find out what shape the code is in. The assessment comes first. + list: + - title: Code review first + body: "You send access. You get a written assessment: what's solid, what's fragile, what's going to cost you." + - title: A 30-minute call + body: We walk you through the assessment in plain English. The document is yours to take to your board, hire us or not. + - title: Week one on the ground + body: The team gets into the repo, reads the backlog, and sends the first Friday report. + - title: Month one plan + body: What gets rebuilt, what gets left alone, what it costs, in what order. You own the code and the plan. + +clients: + eyebrow: Clients + case studies + headline: Clients stay for years. + stats: + # `derived: tenure` is what makes the template compute the value from + # site.Params.foundingYear. Keyed on its own field, not on the label - + # a label-keyed branch falls back silently when someone rewords it. + - derived: tenure + label: Years of industry experience + - value: "5" + label: Years of average client relationship + - value: 8+ + label: Years of average developer experience + cases: + - name: Agent Inbox + body: Hired us to build their real-estate communication platform, get it market-ready, and grow the team around it. + tech: [Rails, React, Node.js] + url: /clients/agent-inbox/ + - name: Open Apply + body: Hired us to debug their school-admissions product, optimize the user experience, and streamline internal project management. + tech: [Rails, Hotwire, Tailwind] + url: /clients/open-apply/ + - name: Mobile Coach + body: Hired us to support and extend the products around their enterprise chatbot platform, and to scale their R&D and engineering teams. + tech: [Rails, AWS, PostgreSQL] + url: /clients/mobile-coach/ + +testimonial: + eyebrow: From a client + # VERBATIM tail of the canon description in data/testimonials.yaml (Bruno + # Wozniak). The design blueprint had smoothed it to "They were detailed and + # precise, helping us find problems..." - a real person's words are not copy + # to tighten. Asserted by test/unit/next_rail_test.rb against the yaml. + quote: Their team was also detailed and precise, helping us to find problems before they appear. We knew exactly what was happening and where we were going the whole time. + attribution: Bruno Wozniak · Director of Engineering, PubNative + sourceName: verified Clutch review + sourceUrl: https://clutch.co/profile/jetthoughts + proof: + - "[**4.8**/5.0 on Clutch](https://clutch.co/profile/jetthoughts)" + - "**5-year** average client relationship" + +closing: + headline: Still deciding? + body: The consultation is free. The assessment is yours either way. + cta: + name: Book a free consultation + url: /free-consultation/ + +footer: + columns: + # JUDGMENT CALL - see the report. "Services" became a menu of four offers, + # which is the thing one-offer positioning removes. Navigation to those + # pages survives through /services/; the two "Fractional ..." link labels + # do not render on this page. + - heading: Also on the site + links: + - name: App/Web Development + url: /services/app-web-development/ + - name: Talent Recruiting & Training + url: /services/talent-recruiting-training/ + - name: All services + url: /services/ + - heading: Proof + links: + - name: Clients + url: /clients/ + - name: Use Cases + url: /use-cases/ + - name: Friday report + url: /friday-report/ + - heading: Learn + links: + - name: Blog + url: /blog/ + - name: Course + url: /course/tech-for-non-technical-founders-2026/ + - name: About us + url: /about-us/ +``` + +## Changes against the current stub, key by key + +| Key | What moved | +|---|---| +| `nav` | Untouched. It carries the same tension as the footer, but a nav link labelled "Services" prints no job title on the page - it is navigation, not a claim. Decide it together with the footer. | +| `hero.eyebrow` | "Fractional CTO" -> "An embedded senior team". | +| `hero.headline` | Now sells the one offer: a team that runs itself. No title. | +| `hero.subhead` | Names the wound (chasing a shop, unable to verify), then the mechanic. | +| `hero.stats` | Dropped "Starts in **days**" (a turnaround promise) and "No equity, no lock-in" (equity was only a comparison to a CTO hire). Replaced with the canon 8+ years figure and a plain statement of what self-managed means for the founder's calendar. | +| `monthOne.headline` | "What a fractional CTO does" -> "What the team does". | +| `monthOne.items` | Dropped "Sits in on your standups and tells you which ones are theatre" - that is a manager's job description. The rest re-aimed to a team, not a person. | +| `comparison.*` | Rebuilt. See the report. | +| `steps.headline` | "Four weeks" -> "Four steps". The weeks were a promised turnaround. | +| `steps.intro` | "You don't sign a retainer" -> "You don't sign anything". | +| `steps.list[1].body` | Removed "Most founders take the document to their board" - a banned phrase and an unsourced claim about our own clients. | +| `steps.list[2].body` | "Your fractional CTO joins standups" -> the team gets into the repo. | +| `clients.headline` | Trimmed "Clients stay for years, not quarters." to "Clients stay for years." - the negative parallelism goes, and the 5-year canon stat sits directly beneath it. | +| `clients.stats` / `cases` | Untouched, `derived: tenure` intact. | +| `testimonial` | Untouched, byte for byte. | +| `closing` | Untouched. | +| `footer.columns[0]` | See the judgment call above and in the report. | + +## Reflexion pass + +Six findings on my own first draft. Four were substantive, and all six are fixed +in the block above. + +| Finding | Why it failed | Fix | +|---|---|---| +| "You end the contract. Nobody's salary depends on it." | Plainly false. Those developers do draw salaries - from us. It read as "these people don't need paying", and it edged toward a termination-terms promise. | Second sentence deleted. | +| "the repo stays in your account" | An operational commitment I invented. Nothing in the repo sources it, and step 4's "You own the code and the plan" is the approved form. | Row now reads "You read the Friday report and click through what shipped" - which maps to ICP pain #12, the progress mirage ("Jira says everything is in progress, but I still can't click through a working product"). | +| "The same developers, on the same product, for years." | Canon backs a 5-year average CLIENT RELATIONSHIP. It does not back the same individuals staying five years. A stronger claim wearing a sourced number's clothes. | "Clients stay for years." The stat block underneath carries the number. | +| Dropped the "Services" link from `nav` | An unrequested navigation change. The brief asked me to re-think the footer, not the nav. | Restored, and flagged as one decision with the footer. | +| Three of five `fractional` cells opened with "You"/"Your" | Opener stamping - the same tell as the voice guide's "We..." density rule, inside a column a reader scans vertically. | "Best when" reworded to open on "There's nobody technical inside...". Now two of five. | +| monthOne items 4 and 5 were both noun phrase + comma + trailing modifier | Two adjacent items sharing an identical construction is the parallel-structure tell, and it is more visible in a five-item list than in prose. | Item 4 back to a verb ("Writes the technical half of your investor update"); item 5 keeps the noun shape as the single break. | + +Sweeps run on the final block: no `Founders who` / `Most founders` / `## Why this +matters`; no em-dashes; no `$`, no per-month, no promised turnaround, no notice +period; no rendered instance of CTO, tech lead, engineering manager or any other +title (the surviving `fractionalLabel` / `fractional:` strings are schema key +names, which the brief keeps, and they render only their VALUES). Sentence-initial +"The" runs about 13% of the page, under the 20% line. + + +--- + +## Apply checklist (next session starts here) + +1. `git checkout -B pilots-reposition origin/master` +2. Rename all three stubs `fractional-cto.md` -> `embedded-team.md` + (`content/next/pilots/{rescue-room,editorial,precision}/`). Safe: the unit + gates glob `next/pilots/**/index.html` and `landing.html` keys the skin off + `register`, not the filename. +3. Paste the YAML block above into all three, keeping each stub's own `title`, + `description`, `register` and `font`. The three must stay byte-identical + below those four keys - copy parity is what makes the register comparison + controlled, and it is asserted by the system tests' shared strings. +4. Update the pilot URLs in `test/system/{desktop,mobile}_site_test.rb`. +5. Re-record the six macOS pilot baselines (run-to-fail -> INSPECT -> commit -> + re-run green, per `.okf/build/test-gates.md`), then dispatch + `test.yml -f screenshots=true -f update-baselines=true` for the Linux six and + screen the bot commit. +6. Gates: `bin/hugo-build`; `bin/rake test:unit`; banned sweep on the built + pilots dir; rendered-blockquote-vs-yaml diff empty; author != verifier. +7. Hand Paul the three new `/next/pilots//embedded-team/` links. + +## Open claims questions for Paul (page ships without all three) + +| Claim | Status | +|---|---| +| "The repo stays in your account" | CUT - no in-repo source. Strong differentiator for ICP pain #13 if true; needs canon entry first. | +| "Starts in days" / "four weeks to a plan" | CUT - promised turnarounds. | +| "No equity, no lock-in" | CUT - contract-terms claim, no source. | +| "No standups on your calendar" | KEPT - describes the offer, asserts no number. Kill it if you disagree. | + +## Wider blast radius, NOT yet actioned + +- **Paul's homepage artifact** (Claude Design `8eb98dd6`, `Homepage.dc.html`) + has a "Three ways in" section listing Project rescue / **Fractional CTO** / + Ongoing development. That is a menu of three offers, one of them a banned + title claim. Needs revision before the homepage build. +- **The live legacy site** sells fractional CTO on `/services/fractional-cto/`, + the homepage, footers and blog cross-links. Under a factual-accuracy rule + that copy is wrong TODAY, independent of the redesign schedule. The page has + ranking history, so removal needs a GSC check first, not an `rm`. Paul's call + on scope and timing. +- **The canon needs the rule with a ratchet** (`.okf/content/claims-canon.md` + + `test/unit/marketing_copy_test.rb`), scoped to v2 surfaces until the legacy + question above is answered - a repo-wide ban fails instantly on legacy pages.