Skip to content

Release 0.3.0 — company-health skill, docs site, Epic 0 analytics#8

Merged
scttbnsn merged 27 commits into
mainfrom
dev
Jun 28, 2026
Merged

Release 0.3.0 — company-health skill, docs site, Epic 0 analytics#8
scttbnsn merged 27 commits into
mainfrom
dev

Conversation

@scttbnsn

Copy link
Copy Markdown
Contributor

rolester 0.3.0

Feature release. Cuts dev (green, 912/912) to main for the v0.3.0 tag + npm publish.

Highlights

  • Company-health / sentiment skill — a role-scoped healthy | watch | risky rating (layoff risk, hiring momentum, financials, sentiment, leadership) that only dents the fit score where a poor dimension intersects a stated candidate need. Cost-gated firing (manual anytime; auto at the interview stage by default), persist-then-render to the tracker, internal signal only — never enters an outbound artifact. Card badge + drawer health section on the dashboard.
  • Docs site — Fumadocs documentation served at /docs (friendly + advanced tracks).
  • Epic 0: outcome analytics as SSOT — one persisted reevaluation block, read everywhere.
  • Demo overhaul — fixture rebalanced to a believable search, explicit company-logo field, evergreen date rebase, jobs-funnel honesty (Accepted terminus, round-depth, ghosted exit).
  • Website launch-polish — footer, docs links, scroll-reveal, favicon, demo embed, softened positioning copy, deploy:web pipeline.
  • License — back to MIT.

Quality

  • Full test suite green: 912 pass / 0 fail. The previously-deferred dashboard assertions were refreshed to the shipped redesign + overhauled fixture (verified stale, no regressions).
  • release-safety green (no personal sentinels, allowlist sane).
  • One moderate Dependabot advisory (nextpostcss) is in the website build chain only; next does not ship in the published rolester package.

Publish

Tagging v0.3.0 after merge triggers the OIDC Trusted-Publishing flow (npm provenance), shipping MIT.

CodesWhat added 27 commits June 26, 2026 18:07
…ed tracks)

Standalone Fumadocs static-export app at docs-site/ (mirrors the sockguard/docs
shell). Four sections: Getting Started, Guides, Advanced, Reference (20 content
pages + index), covering clone-canonical install, the agent contract, the data
model, privacy boundaries, the skills catalog, and BUSL-1.1 licensing. Builds to
a static export; not yet deployed. Standalone (own package-lock), not a root
workspace.
vercel.json pins framework=nextjs so `vercel build` detects the static export
(a bare project defaults the output dir to public/ and fails). Plus the
Vercel-added .gitignore entries so .vercel/ and .env* never get tracked.
Matches the sockguard/drydock convention: docs live under the marketing site,
not a separate subdomain/project. docs-site now builds with basePath:/docs +
trailingSlash (directory-style export so leaf pages resolve as clean static
URLs), and website's build:docs-content prebuild step copies the export into
website/public/docs/ so the single rolester-website deploy serves /docs.

Drops docs-site/vercel.json (no standalone rolester-docs Vercel project or
docs.rolester.codeswhat.com subdomain anymore). public/docs is gitignored
(generated by the build).
…exit

The Sankey branched Awaiting straight into both Going stale and Ghosted as
siblings, so a ghosted app read as a direct Awaiting exit (tooltip "Awaiting →
Ghosted") even though every ghosted app was stale first. The Ghosted node was
also unlabeled and got shoved under the 1st-round node, so its faded band
drooped down into nothing.

- 🔄 route the decay band forward as a progression: Awaiting → Going stale
  carries every pre-response quiet app, then the fully-ghosted subset continues
  Going stale → Ghosted. "Going stale" is now the cumulative quiet state
  (stale + ghosted), so its count includes the apps that went on to ghost,
  matching the round chain, which is already cumulative.
- 🎨 label the Ghosted exit and pin it to the top of its own column (2.25) so
  the faded band peels up off Going stale and leaks away, the mirror of
  Rejected, which sinks to the bottom.
…read everywhere

The reevaluation signal was computed in two places that could drift: the
read-only `analyze:outcomes` CLI that track-outcomes shelled out to, and the
dashboard. Consolidate onto the SSOT model — `tracker.json#analytics` is computed
once by `npm run analytics -- --write` (stamp:false, never moves the freshness
pill) and every consumer reads that one block. The per-family numbers require
role-family classification the browser can't do, so the persisted block is the
only correct source for them.

- 🐛 fix(analytics-cli): default the verb to `refresh` when flags are present but
  no verb is given, so the documented `npm run analytics -- --write` actually
  runs instead of printing help and exiting 1. Bare `npm run analytics` and
  `--help` are unchanged.
- 📝 docs(agents): add a conditional "refresh analytics" step to the Tracker
  Write Contract (after Verify, before Re-render). Outcome-changing skills run
  `npm run analytics -- --write` so the dashboard renders a fresh block; pure
  comms/scheduling writes skip it.
- 🔄 refactor(track-outcomes): STEP 6 reads `analytics.reevaluation`
  (due/dueReasons/sinceLastReview/thresholds) from the persisted block instead
  of running `analyze:outcomes` and hand-comparing YAML thresholds. The block
  applies the comparison; the skill reads `due` and trusts it.
- ✨ feat(dashboard): surface reevaluation progress in the strategy-review panel
  from the persisted block (read like compEstimate — never recomputed client
  side). Null-safe: older trackers without the block render nothing. Text/amber
  only, no left-accent strip.
- 🔧 config(demo): seed the analytics block into the demo fixture so the public
  demo shows the surfacing.
The demo fixture was thin — most rows were a status + 2-3 stub conversations with
artifact paths that pointed at files that didn't exist. Build it into a realistic,
lived-in job search for one persona (Riley Chen) so the dashboard demos with real
content: emails, interview notes, transcripts, prep dossiers, and a full offer-to-
accept arc. Depth scales with how far each job advanced.

- ✨ E Corp — Staff SWE (accepted) is the showcase: a 9-beat arc from referral to
  signed offer, the offer→counter→revised-offer→accept negotiation, an embedded
  interview dossier (live cue card + study layer), and a 10-message thread.
- ✨ the 7 DEEP rows (2 offers, 2 final rounds, onsite, loop, panel) get rich
  conversations, comms threads, embedded dossiers, a transcript each, and offer
  letters for the Aperture/Hooli comparison offers. 3 MEDIUM and 18 LIGHT
  (applied/screens/rejected/withdrawn) get just enough — a confirmation thread, a
  screen note, a rejection email — nothing heavy.
- ✨ 45 artifact files under examples/demo-workspace/workspace/ (13 JDs, 11 prep
  packets, 9 transcripts, 9 email-thread exports, 3 offer letters), all grounded in
  Riley's real track record (Meridian RAG + agentic workflow, Pulsar FDE deploys).
- 🐛 fix the candidate email everywhere to riley.chen@rolester.dev (a stray
  jane.candidate@example.test leftover in the old thread is gone).
- 🐛 normalize the generated fields to what the dashboard actually reads:
  compEstimate → floorK/askK (in $K), followUp → dueAt/note, benefits → the real
  BENEFIT_EMOJI keys; and fix 3 comm statuses that read as phantom "reply needed"
  CTAs (Abstergo → waiting, Weyland-Yutani / Massive Dynamic → scheduled). Only
  E Corp is accepted; 2 genuine needs-reply threads remain (decline Aperture,
  withdraw Black Mesa).
- 📝 docs(roadmap): add the interactive live-demo-on-the-site item to the public
  roadmap (the build this data renders).

Validates clean: schema --verify, verify:tracker (0 errors / 0 warnings), render.
Built via a 15-agent workflow (tiered generators → deterministic merge), reviewed +
field-corrected + committed by the orchestrator.
…ad scroll

The Jobs Sankey over-counted depth and had no celebratory endpoint. Three fixes,
all domain-neutral (help real searches too, not just the demo).

- ✨ add an "Accepted 🎉" terminal node — accepted offers flow out of their last
  round into a green celebratory sink, set apart from the live chain so the win
  reads instantly (was: an accept just sat anonymously at its deepest round).
- 🐛 roundCount no longer counts non-evaluative beats as interview rounds. A
  referral intro, offer call, negotiation, debrief, or reference check is real
  history but not a round, so an accepted loop was showing as a 9th-round outlier.
  New NON_ROUND_CONV_RE blocklist → only screens + interviews count (e.g. E Corp
  9 → 4 rounds, demo maxRound 9 → 5).
- 🗑️ remove the horizontal-scroll affordance (left/right buttons, scroll wrapper,
  fixed 1800px SVG width, click/scroll/resize handlers). The funnel SVG always
  scales to fit via preserveAspectRatio meet, so scroll never did anything — it
  fit even at 9 rounds. SVG is now width:100% responsive and centered.

Funnel + shell inline JS/CSS parse clean; client-script + styles guards green.
- 🔄 flip 22/29-interviewing → 66% ghosted / 34% heard back, keyed on real rolester-live ratios; funnel chain thins 6→6→5→3 (maxRound 4), 6 rejected, 1 withdrawn, 3 live
- ✨ E Corp = offer-in-hand (decision pending), no accept — offer letter is the freshest artifact, weighed against the live Cyberdyne onsite + Massive panel this week
- 🐛 fix a real-person de-id leak (recruiter name) + stale signed/DocuSign content the mechanical pass left, via QA fan-out + 6-agent per-row coherent rewrite (conversations + comm threads + dossiers all reconciled)
- 🔧 evergreen dates anchored to meta.demoAnchor=2026-06-26; channels normalized to board/referral/recruiter; analytics block regenerated
- ✨ feat(dashboard-data): avatarMarkup reads an explicit `logo` (app.logo /
  sourced.logo) ahead of logo.dev, else monogram; wire row.logo through every
  avatar call site (table, jobs explorer, cards) + applicationJobRow/sourcedJobRow
- 📝 docs(AGENTS): add "Company logos" convention — skill writes app.logo when it
  has one, dashboard reads it, else logo.dev-if-wired, else monogram
- 🎨 style(assets): normalize all 29 demo logos to uniform 256x256 white-padded PNG
  (drop mixed jpg/svg/webp); reconstruct Black Mesa ring+wedge mark
- 🔧 config(demo-logos): point DEMO_LOGOS at the .png files + reference the convention
- ✨ feat(demo-fixture): wire app.logo on all 29 applications + 2 sourced rows
… bundle

The .reveal CSS gate was already fail-open for no-JS, but the
IntersectionObserver that adds .visible lived in the bundled
SiteInteractions client component. If the inline gate script ran but the
bundle was blocked, html.js was set, content was hidden, and nothing
revealed it: fail closed.

Move the reveal observer into the same inline bootstrap that sets html.js
so the gate and the revealer share fate. A blocked bundle now still
reveals content. SiteInteractions keeps the squiggle, nav-active, and
header-pill enhancements.
…avicon, live-demo pipeline

- 🎨 style(website): port drydock-style footer (brand blurb + Product/Project columns + legal + CodesWhat sign-off pill), adapted to rolester warm palette
- ✨ feat(website): add Docs nav link + footer links to the Fumadocs site at /docs
- ✨ feat(website): footer reveals on scroll via the existing .reveal system; the html.js shim already gates it (no-JS = visible)
- 🎨 style(favicon): rat-headshot favicon across the marketing site, the live demo, and the locally-hosted dashboard
- ✨ feat(demo): build:demo + deploy:demo pipeline — rebase-demo-dates (evergreen) → render fixture → static bundle → prebuilt Vercel deploy to demo.rolester.codeswhat.com
Reverses the 0.2.4 BUSL-1.1 relicense (3b11cde). Restores the original MIT
text and flips every reference: package.json + lockfile license field, the
LICENSE file, docs/DISCLAIMER.md, the docs-site disclaimer + what-is-rolester
pages, and the marketing-site hero/footer strings (footer "License" links now
point at the repo LICENSE instead of mariadb.com/bsl11). Built docs output
(website/public/docs) regenerates MIT on the next docs build.
The launch-hygiene leak audit caught the demo deploy script naming the employer
org in a code comment — a de-id violation on a public surface. Rephrased the
--scope warning to keep the operational guardrail (always pass --scope; never
let the CLI default account receive the deploy) without naming the account.
Caught + fixed before any push, so it never left the machine.
…muddy strategy card

- 🐛 Stop the slide-in drawers casting a shadow while parked off-screen: their
  Tailwind shadow-2xl plus a custom -18px left shadow bled ~40-68px back onto
  the page's right edge on every view. Shadow now only renders while open.
- 🎨 Drop the white diagonal card sheen in dark mode (it composited to a harsh
  light→dark diagonal over the dark surface).
- 🎨 Re-tint the strategy card for dark mode: the "Next Steps" recommendation
  banner (peach→dark coral), the review panel (mint→dark teal), and the outcome
  learning bar tracks (bumped off the surface colour so they actually read).
Replace the static mascot in "Meet your sidekick" with a framed, click-through
preview of the real dashboard — a looping screen-recording (Dashboard → Jobs
funnel → Calendar → Library) captured at a fixed viewport so there's no padding
jank, linking out to the standalone live demo.

Adds the DemoEmbed component + .demo-* styles, and the Playwright capture
scripts (record-demo-video.mjs drives the tour → webm → ffmpeg GIF;
capture-demo-frames.mjs is the fixed-viewport frame fallback).
Rescope the local-first messaging so it reads as what the self-host version
gives you, not an anti-cloud creed — leaves clean room for a hosted version
later without contradicting the page.

- Hero CTA "it's yours, and it's free" → "free & open source"
- "The whole loop. Nothing sold separately." → "The whole loop, end to end."
- Privacy section: drop "belongs in a cloud database" / the anti-freemium jab;
  reframe h2 to "Self-host it, and your data stays your own."; "no cloud" chip
  → "runs locally"
- Get section: drop "no account, no cloud"; final CTA scoped to self-host
Command snippets like `-g` and `@anthropic-ai/...` were rendering their hyphens
as long ligature dashes. Pin `code` and `.terminal-sticker` to the mono face
with ligatures/contextual alternates disabled so hyphens read as hyphens.
…atch

The inline bootstrap added `visible` to .reveal nodes before React hydrated,
which mutated server-rendered markup and triggered a hydration mismatch. Move
the IntersectionObserver into SiteInteractions (post-hydration) and leave the
inline script to only set the `js` gate plus a post-load failsafe for the
blocked-bundle case. Reduced-motion now resolves purely in CSS.
…e publishing

The demo's E Corp offer story used $225K as the initial base, which collides
with a known production comp sentinel (225K/225000/220000) — i.e. a real number
the release-safety guard bans from tracked files. Shift the fictional initial
offer to $222K everywhere it appears (offer doc, tracker activity + comms
thread) and adjust the one derived figure ($7K→$10K improvement, ~$362K→~$359K
Y1 TC) to stay coherent. Also retire the $220K tactical floor in the Weyland
packet (same banned value, K-form the grep missed). release-safety test green.
Mirrors deploy:demo's Build Output API approach (prebuilt, --scope
codeswhat) so the marketing site + /docs ship to rolester.codeswhat.com
without tripping the Next-16 static-export vercel-build 404 bug.
SKILL.md + config + routing (scoring/UI wiring follows). The skill
web-searches role-scoped layoff/financial/sentiment/leadership signals,
scores a healthy|watch|risky rating with provenance, persists companyHealth
to the tracker, and cross-cuts the fit score only where it hits a stated
candidate need (else it stands alone).

- .agents/skills/company-health/SKILL.md — firing cost-gate (auto at the
  interview stage by default, manual anytime), per-dimension research,
  standalone-rating + selective cross-cut scoring, derive→persist→render,
  internal-signal-only honesty rail.
- config: company_health block in modes.schema.json + modes.example.yml
  (auto / fire_at_stage / manual_always / recheck_days).
- routing: AGENTS.md intent table + Intent Routing + config-consumer,
  Activity Pulse, and fan-out tables; CLAUDE.md routing line; package.json
  files allowlist. install-skills globs the dir (23 skills discoverable).
…o fit

STEP 6 applies the role-scoped cross-cut: fitDelta is 0 when the rating
didn't hit a stated candidate need and a small negative when it did (like
benefits feed fit only where valued). Never a hard kill on its own; a stale
rating is informational only. No companyHealth = no change.
Card carries a compact Watch/Risky pill (role-scoped detail in the title,
healthy stays silent); drawer gets a Company health section — rating-for-
function, provenance, as-of, per-dimension rows, and a collapsible evidence
list with http(s)-only source links. No left-accent strip; dark-mode re-tints
the teal/amber/coral so the rgba literals don't go muddy over dark surfaces.
Healthy/Watch/Risky across E Corp, Massive Dynamic, Cyberdyne so the live demo
shows all three states + the stability cross-cut (Cyberdyne's fresh RIF hit the
ML org, fitDelta -5). Dates anchored to demoAnchor so the rebase keeps them
evergreen; no comp numbers or banned sentinels in any note.
…n + fixture

Greens the full suite (912/912) ahead of the 0.3.0 cut. All 24 deferred failures
were stale assertions tracking the pre-redesign dashboard + pre-overhaul demo
fixture, not regressions — verified each: renamed classes/CSS-var swaps, fixture
count/date rebalances, the interviewPacket→interviewDossier artifact contract, and
the minified website hydration bootstrap. No source or fixture files changed.
Feature release: role-scoped company-health/sentiment skill, Fumadocs /docs site,
Epic 0 outcome analytics, demo-fixture overhaul, website launch-polish, MIT relicense.
Full suite green (912/912). Ships MIT.

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Release contents verified — green suite, release-safety clean, MIT. Approving.

@ALARGECOMPANY ALARGECOMPANY left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second approval — looks good to ship 0.3.0.

@scttbnsn scttbnsn merged commit e3fca4e into main Jun 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants