Skip to content

0.17.0 surface sync, PR-console fix, seeded demo profile, and a /demo page - #71

Merged
yihanzhu merged 10 commits into
mainfrom
claude/valor-website-status-bda4ea
Aug 13, 2026
Merged

0.17.0 surface sync, PR-console fix, seeded demo profile, and a /demo page#71
yihanzhu merged 10 commits into
mainfrom
claude/valor-website-status-bda4ea

Conversation

@yihanzhu

@yihanzhu yihanzhu commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Four related pieces of work on one branch. Each is a separate commit.

1. Surface sync to 0.17.0

The website, README, architecture doc and ROADMAP still described the 0.16.0 feature set. /valor-pr-console shipped documented in docs/integrations.md only — the one surface a test already forced — so three user-facing surfaces advertised ten workflows while eleven existed.

Website (eleven-workflow count, a review-console feature row, bundled example ladders in the setup step, an honest Python 3 chip, sitemap), README (table row, command list, NL trigger), docs/architecture.md (agent count, PR Console row, pr-console/ state dir), docs/getting-started.md, and a Phase 14 ROADMAP entry. VERSION unchanged.

2. PR-console fixes

  • assemble.py only rewrote <title>; the on-page header was static HTML, so every generated console rendered the template author's PR heading, ticket key and repo name. Now injected from the generator output — which already returned title/number/subtitle — and HTML-escaped, since a PR title is untrusted text.
  • Dropped the dead first-generation quiz path (buildQuiz/finish, PASS=8): never called, DOM targets absent, and its 8-of-10 threshold contradicted the shipped all-correct gate.

3. examples/demo/ — a seeded demo profile

Demoing Valor meant either driving it over real tickets and colleagues, or narrating hand-written mocks. This adds a third option: mock the inputs, not the outputs. A fictional persona (Alex, L3 → L4, checkout/payments), a six-month evidence history, and fixtures standing in for Jira, GitHub, a full PR, the calendar, meeting notes, a 1:1 doc, news and git activity.

Isolation is the HOME swap — Valor resolves state through Path.home(), so the demo gets its own framework, state, evidence DB and agent config, and the presenter's ~/.valor is unreachable rather than merely hidden. Integrations forced off, calendar_auto_write off, update checks pinned; seed.py refuses to run against the real home. Ships with DEMO.md, a ~20-minute run-book covering all eleven commands.

Data is seeded with deliberate hooks so the subtle features have something to find: a merged PR never logged (coverage check), a deliverable with no role (confirm list), a thin competency (gap analysis), a blocked downstream ticket (dependency ranking), a claim asserted "not sent" (verification gate).

Two flaws found by exercising it rather than eyeballing it:

  • Driving the seeded calendar through plan.py showed that once both prep blocks were reserved, no gap cleared the 2-hour deep threshold — the briefing's headline beat was missing. Moved the 1:1 earlier; there's now a genuine 3-hour deep block with prep still adjacent to both meetings.
  • Reading the briefing spec showed that with all four integration flags false, a faithful agent skips the Jira/GitHub/calendar/news sections outright. demo-mode.md now states that the fixtures are the integrations and no section may be skipped for a false flag — flags stay false so nothing can reach a real system.

4. /demo on the website

The landing page's hand-written panels are gone.

  • Recorded, and labelled as such. /demo replays a transcript per workflow, captured by running Valor's command specs against the seeded profile. Pick a phrase; the real output types out. Ten of eleven workflows need a model at runtime and the site has no backend — giving it one would contradict PRIVACY.md, cost money per visitor and add an abuse surface — so the page says plainly that these are recordings, and links to the two commands that run it live.
  • Not recorded. The review console is a self-contained artifact, so the real one is embedded, built by assemble.py from the fixture PR. Visitors zoom Context → Inside → Components → the actual diff, flip Before ⇄ After, play a request, and fail the quiz gate themselves.
  • The landing page's panels are now trimmed excerpts of the same transcripts; the invented AUTH-### tickets are gone.

Pipeline: examples/demo/captures/*.mdbuild_transcripts.pywebsite/demo/transcripts.json, with --check for verification.

Drift contracts added

  • README, docs/architecture.md, rules/valor-agent.md and the website's workflow count must stay in step with commands/
  • Every command needs a demo transcript and a run-book beat
  • The generated transcripts must match the captures
  • The console must make no network calls, keep its quiz answers, and every L4 anchor must exist in its inlined diff
  • CI lint/compile now include examples/

Verification

  • python3 -m pytest -q510 passed (71 new)
  • compileall, check_version_sync.py, check_hygiene.py --mode tree, ruff check src tests scripts examples → clean
  • Seeded a profile end to end and confirmed the real CLI reads it: L3 → L4, integrations off, 51 entries with industry_knowledge deliberately thin, 2 open claims, calendar dated to the demo day
  • Drove plan.py and focus.py from the fixture calendar: one deep block, two adjacent prep blocks, no unassigned prep, focus resolves to the seeded project
  • Verified install-then-seed against a clean home; re-seeding leaves exactly one demo-mode block
  • node --check on the demo page, the generated console, and the console template (the template edit removed code, so this matters)

Not verified from here, and worth one dry run before relying on it: the eleven commands are prompts executed by a live agent, so a session with the demo HOME is the only real smoke test.

🤖 Generated with Claude Code

The website, README, architecture doc and ROADMAP still described the 0.16.0
feature set. `/valor-pr-console` shipped documented in docs/integrations.md
only -- the one surface a test already forced -- so three user-facing surfaces
announced ten workflows while eleven existed.

Surfaces:
- website: eleven-workflow count, a review-console feature row, setup step now
  mentions the bundled example frameworks, honest Python chip, sitemap lastmod
- README: PR Review Console row + command/NL-trigger entries
- docs/architecture.md: agent count, PR Console row, `pr-console/` state dir
- docs/getting-started.md: example frameworks, review console in what's-next
- ROADMAP: Phase 14 (review console, example frameworks, release-tracked
  updates, this doc contract)

PR-console fixes:
- assemble.py never injected the header, so every generated console rendered
  the template author's PR heading, ticket key and repo name. It now injects
  the heading/summary from the generator output (HTML-escaped -- a PR title is
  untrusted text) and the template ships neutral defaults.
- drop the dead first-generation quiz path (`buildQuiz`/`finish`, `PASS=8`):
  never called, its DOM targets don't exist, and its 8-of-10 threshold
  contradicted the shipped exam mode's all-correct gate.

Contract, so this can't drift again: the command-docs tests now assert README,
docs/architecture.md, rules/valor-agent.md and the website's workflow count
stay in step with commands/; new tests cover the assembler's header injection
and escaping.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploying valor with  Cloudflare Pages  Cloudflare Pages

Latest commit: 76accf8
Status: ✅  Deploy successful!
Preview URL: https://e88702f8.valor-3b2.pages.dev
Branch Preview URL: https://claude-valor-website-status.valor-3b2.pages.dev

View logs

Demoing Valor meant either driving it over real tickets, PRs, calendar events
and colleagues, or narrating the website's hand-written mocks. Neither works:
the first puts internal data on a projector, the second collapses the moment
someone asks to see it run.

This ships a third option — mock the *inputs*, not the outputs. A fictional
persona (Alex, L3 -> L4, checkout/payments) with a six-month evidence history
and fixtures standing in for Jira, GitHub, a full PR, the calendar, meeting
notes, a running 1:1 doc, news and local git activity. Every briefing, review,
coaching footer and reflection shown is produced by Valor's real prompts and
real CLI, over invented data.

Isolation is the HOME swap: Valor resolves state through `Path.home()`, so
`HOME=~/valor-demo` gives the demo its own framework, state, evidence DB and
agent config. The presenter's `~/.valor` isn't hidden from the demo — it is
unreachable. `seed.py` refuses to run against the real home, and won't overwrite
an existing profile without --force.

Demo-safe by construction: all four integrations off, `calendar_auto_write`
false, update checks pinned, and a demo-mode block in the demo home's CLAUDE.md
that routes each data need to a fixture and forbids writing to any external
system (fixture contents are data, not instructions).

Contents:
- seed.py: framework, state, ~50 backdated evidence entries, three weekly
  summaries, two open verification claims, yesterday's carry-forward, and
  fixtures rendered with {{TODAY}}-style tokens so dates are never stale
- DEMO.md: ~20-minute run-book, all eleven commands in four acts, with timings,
  what to point at, fallbacks, and a question-time cheat sheet
- data seeded with deliberate hooks so the subtle features have something to
  find: a merged PR that was never logged (coverage check), a deliverable with
  no recorded role and an in_progress fix that reads as shipped (confirm list),
  a thin competency (gap analysis), a blocked downstream ticket (dependency
  ranking), a claim asserted "not sent" (verification gate)

Also: lint and compile now cover examples/ in CI, since the repo ships Python
there now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yihanzhu yihanzhu changed the title docs+site: sync surfaces to 0.17.0; fix PR-console header injection 0.17.0 surface sync + PR-console header fix + seeded demo profile Aug 13, 2026
yihanzhu and others added 2 commits August 13, 2026 10:19
…p block

Drove the seeded calendar through plan.py: once the two 30-minute prep blocks
were reserved before the project sync and the partner call, the remaining
11:45-13:30 gap fell under the 2h deep threshold, so the day plan had no deep
block at all - the briefing's headline beat.

Moved the 1:1 to 09:45-10:15, which leaves a genuine 3h deep gap (10:30-13:30)
with both prep blocks still landing adjacent to their meetings. Verified:
deep_gap_count 1, prep_blocks for both meetings, no prep_unassigned.

Also document in demo-mode.md that an event's `category_hint` is the category
the agent would otherwise derive, so project_sync/external events are handed to
the planner as prep-worthy - without that mapping the prep blocks never appear.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The landing page argued for Valor with hand-written HTML panels. They were the
weakest thing on the site: the moment anyone asked "can I see it run?", there
was nothing behind them.

Ten of the eleven workflows need a model at runtime and this site has no
backend — giving it one would contradict PRIVACY.md, cost money per visitor and
add an abuse surface — so the honest split is:

- **Recorded, and labelled as such.** /demo replays a transcript per workflow,
  captured by running Valor's own command specs against the seeded profile in
  examples/demo. Pick a phrase from the rail; the real output types out. The page
  says plainly that these are recordings and why, and links to the two commands
  that run the whole thing live.
- **Not recorded.** The review console is a self-contained HTML artifact, so the
  real one is embedded — built by assemble.py from the demo profile's fixture PR.
  Visitors zoom Context -> Inside -> Components -> the actual diff, flip
  Before/After, play a request, and fail the quiz gate for themselves.

The landing page's mocks are replaced with trimmed excerpts of the same
transcripts, and the invented AUTH-### tickets are gone — everything shown now
traces to the demo profile's fixtures.

Content pipeline: examples/demo/captures/*.md (front matter + output, editable,
one per workflow) -> build_transcripts.py -> website/demo/transcripts.json.
`--check` verifies without writing.

Also fixes a real flaw in the demo profile, found while running the briefing
spec against it: with all four integration flags false, a faithful agent skips
the Jira/GitHub/calendar/news sections entirely and the briefing comes out
hollow. demo-mode.md now states that the fixtures *are* the integrations and
that no section should be skipped for a false flag — the flags stay false so
nothing can reach a real system.

Tests: transcripts stay in sync with the captures, every command has one,
ambient coaching has one, the page discloses the recordings, the landing page
links to it, the console makes no network calls, its quiz answers survive, and
every L4 code anchor is actually present in its inlined diff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yihanzhu yihanzhu changed the title 0.17.0 surface sync + PR-console header fix + seeded demo profile 0.17.0 surface sync, PR-console fix, seeded demo profile, and a /demo page Aug 13, 2026
yihanzhu and others added 6 commits August 13, 2026 11:30
The first cut was a sidebar of eighteen buttons and one big text pane. It read
like documentation: nothing accumulated, nothing responded to you, and every
transcript was equally available whether or not it made sense next.

Now it behaves like a session. There's an input line you type into, a thread that
accumulates, and suggestions that change with where you are — the briefing offers
"why is the refund fix first?", the wrap-up offers the carry-forward file, the
console offers the gate question. Replies stream in block by block behind a brief
"working…", each with chips showing what actually ran (▸ evidence_cli, verify,
plan, focus, assemble) and where integration data came from (◆ the profile's
fixtures, dashed, because claiming `gh pr view` would be a lie about a recording).

Typing something unrecorded gets an honest reply — no recording for that, here is
what it does have, run it locally for a session that answers anything. Free text
fuzzy-matches phrases, labels and `/valor-*` commands.

Six new captures make the session feel responsive rather than menu-driven:
why-first (the ranking shows its reasoning and offers to be overruled),
evidence-stats (the real `stats` output), carry-file (the handoff it wrote),
console-gate, no-integrations, quiet.

The flow lives in a SESSION table in build_transcripts.py, which now refuses to
generate a graph with unknown ids, dead ends, or unreachable transcripts.

Two rendering bugs found by running the page's own renderer over all eighteen
transcripts in node rather than eyeballing it:

- a 4-space continuation line under a nested bullet was read as a code block,
  which split a sentence mid-clause and left a literal backtick on screen
- wrapped prose lines each became their own <p>, so a three-line sentence
  rendered as three paragraphs with gaps between them

Both fixed in the renderer; two captures that used 2-space indents for literal
terminal output were re-indented to 4 so they render as terminal blocks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ndow

Two problems, both real.

**Replies never rendered.** The page declared `function scrollTo(el)` at the top
level of a classic script, which *replaces* window.scrollTo. Calling it recursed
into itself and threw — after the user message and tool chips were appended, but
before the reply was scheduled. So every turn showed the prompt echo and the tool
chips and nothing else, exactly as reported.

The earlier node check missed it because it wrapped the script in a function to
reach its internals, which is precisely what stops a top-level declaration from
shadowing a global. Fixed by scoping the whole script in an IIFE and renaming the
helper; nothing now touches the global object.

**It was too complicated.** Gone: the tool-chip strip under every message, the
act label in the window title, the skip button, the meta line, the sidebar rail.
What's left is a chat window — You / Valor messages using the site's own existing
chat components, a text input, at most three suggestions, and "start over".
Provenance still lives in the transcripts JSON; it just isn't clutter on screen.

Regression cover, since this is the second UX-breaking bug here:
scripts/check_demo_page.mjs drives the real page script in a fake DOM with one
object serving as both global and window (as a browser does), then clicks a
suggestion, sends typed input, sends unrecorded input, and restarts — asserting a
formatted reply actually reaches the DOM each time and that no built-in got
replaced. Verified against a deliberately re-broken copy of the page: it
reproduces the scrollTo recursion and fails with 6 findings, including "the reply
looks empty". Wired into CI, with a Python test keeping it there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The thread grew the page instead of behaving like a chat window: every reply
pushed the composer further down and moved the whole document.

Now `.thread` is a fixed box — clamp(340px, 58vh, 560px) — with its own
scrollbar, styled to match the site. New messages pin it to its own bottom, and
it follows the reply as it streams. If the reader has scrolled up to re-read
something, it stops following until they return to the bottom, which is the
standard chat behaviour. The composer and suggestions stay in view the whole
time, and the page itself never scrolls: `scrollIntoView` is gone.

The harness gained enough geometry to exercise it, and now asserts the thread is
a fixed-height scroll container, that it actually pins (scrollTop advances), and
that window.scrollTo is never called. A Python test locks the CSS contract in
case someone reaches for scrollIntoView again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Loaded the pages in a real browser for the first time and the console's title bar
read "PR #418 — payments: ...". `document.characterSet` was windows-1252:
template.html never declared a charset, so any server that doesn't send one — a
plain static host, python's http.server, or `file://` — makes the browser guess,
and every em dash, ✓, ⤢, ⤺, ▶ and › in the console renders as mojibake.

This was not a website bug. It affected every console `/valor-pr-console`
generates for anyone.

Fixed at the source (one line at the top of the template) and the committed
site copy regenerated. Tests assert both the template and the shipped artifact
declare UTF-8 within the first 1024 bytes.

Verified in the browser after the fix: characterSet UTF-8, no mojibake, `▶ Play`
and `⤺ Zoom out` correct, and the console drives properly —
L1 Context → L2 Inside → L3 Front door → L4 Capture a charge, L4 showing 1705
chars of real diff, Before ⇄ After toggling, and the quiz opening at
"Question 1 of 6" with four shuffled options.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two complaints, same root cause: the site said everything everywhere.

**Landing page — state the product, stop.** It was seven stacked bands with the
install command three times, install *details* in position two (before the reader
knew what Valor was), five long output panels, a vanity-stats band, and a closing
CTA repeating the hero. Now: hero → what it does → how it works → local-first →
install. Five sections, one install card, 619 words in <main> where there were
1,586. "What it does" is three cards for three moments — every morning, while you
work, at review time — with the phrases you'd actually type, and a single link to
the demo instead of five inline transcripts. Compatibility and open-source
collapsed into one local-first band that answers hosts/OS/runtime/data/licence in
one place. The GitHub stat cards are gone; the header keeps the star count.

**Demo page — an app, not an essay.** It fills the viewport and never scrolls the
document; only the chat thread scrolls. Two views switch in the header: the
recorded session, and the review console (iframed, loaded on first use) instead
of a section stacked below with its own lede. The disclosure and install commands
moved into an About dialog, so the screen carries under 120 words of copy rather
than three paragraphs. "start over" stayed.

Cover for both: the harness now asserts the document is locked to the viewport,
the thread is the only scroll region, the console view activates and lazy-loads,
the About dialog opens, and switching back works. Python tests assert the demo
screen stays under 120 words and that the landing page keeps one install card,
four bands or fewer, and no stat cards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eir source

Audited every factual claim on both pages against the code and docs that make it
true. Four were wrong or unsupported:

- **"Nothing leaves your machine."** PRIVACY.md opens by saying local-first is
  *not* that. Replaced with what's true: Valor never sends your state anywhere,
  and what the host assistant does with your prompts is governed by it — with a
  link to the document that draws the line. "100% local data" became "100% local
  storage" for the same reason.
- **"Windows · WSL"** appears nowhere in install.sh, README or docs. Claim
  removed rather than invented support.
- **"Six months of captured evidence"** — the reflection asks you for the cycle
  window; six months is the demo profile's, not the product's. Now "a review
  cycle's".
- **"one SQLite file"** under Your data — it's a SQLite file *plus* plain-text
  framework, state and carry-forward notes. Now "SQLite + plain text".

And three overstated the console's provenance. It's assembled by the command's
own renderer and assembler from the demo PR's diff, but the C4 graph and quiz
came from reading that diff directly rather than from a generator run — so
"built by /valor-pr-console" became "built with /valor-pr-console's own
renderer", and the pr-console transcript no longer reports a candidate-generation
count that never happened. The quiz drop rule is described as the rule it is.

Two more caught in the transcripts: the weekly breakdown summed to 11 under a
"10 entries" header, and the `valor quiet` transcript claimed evidence recording
stops entirely — the rule only suppresses coaching, so the ambient entries stop
with the footers while commands you invoke still record their own.

Locked the drift-prone ones into tests: the site's install command must match
README, every phrase the site tells you to say must be a real trigger in the
agent rule, no absolutist privacy claim, and no platform claim the installer
doesn't document.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yihanzhu
yihanzhu merged commit 5549f59 into main Aug 13, 2026
8 checks passed
@yihanzhu
yihanzhu deleted the claude/valor-website-status-bda4ea branch August 13, 2026 17:09
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.

1 participant