0.17.0 surface sync, PR-console fix, seeded demo profile, and a /demo page - #71
Merged
Conversation
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>
Deploying valor with
|
| 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 |
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>
…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>
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-consoleshipped documented indocs/integrations.mdonly — 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 3chip, 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.VERSIONunchanged.2. PR-console fixes
assemble.pyonly 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 returnedtitle/number/subtitle— and HTML-escaped, since a PR title is untrusted text.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 profileDemoing 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
HOMEswap — Valor resolves state throughPath.home(), so the demo gets its own framework, state, evidence DB and agent config, and the presenter's~/.valoris unreachable rather than merely hidden. Integrations forced off,calendar_auto_writeoff, update checks pinned;seed.pyrefuses to run against the real home. Ships withDEMO.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:
plan.pyshowed 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.demo-mode.mdnow 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.
/demoon the websiteThe landing page's hand-written panels are gone.
/demoreplays 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 contradictPRIVACY.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.assemble.pyfrom the fixture PR. Visitors zoom Context → Inside → Components → the actual diff, flip Before ⇄ After, play a request, and fail the quiz gate themselves.AUTH-###tickets are gone.Pipeline:
examples/demo/captures/*.md→build_transcripts.py→website/demo/transcripts.json, with--checkfor verification.Drift contracts added
docs/architecture.md,rules/valor-agent.mdand the website's workflow count must stay in step withcommands/examples/Verification
python3 -m pytest -q→ 510 passed (71 new)compileall,check_version_sync.py,check_hygiene.py --mode tree,ruff check src tests scripts examples→ cleanindustry_knowledgedeliberately thin, 2 open claims, calendar dated to the demo dayplan.pyandfocus.pyfrom the fixture calendar: one deep block, two adjacent prep blocks, no unassigned prep, focus resolves to the seeded projectnode --checkon 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
HOMEis the only real smoke test.🤖 Generated with Claude Code