fix(web,api): P3 polish — preferences metric, fallback description, dollar inputs#86
Merged
Merged
Conversation
1. "How well I know you" stat now counts preferences, not just inferences. Previously a user with 5 explicit preferences and 0 inferences saw 0% even though the twin had real knowledge. Combined preferences and inferences in the overall confidence calculation in /confidence endpoint, and weight explicit/corrected preferences as 'confirmed' (the user told us directly). 2. Twin preference descriptions no longer show "Travel: find_travel_deals = i love travel deals" as the fallback. The generic describePreference() helper now treats string values as the preference itself: "Travel: i love travel deals". Boolean and numeric values keep the key for context. 3. Spending guardrails inputs accept dollars instead of cents. Inputs now show "$" prefix and decimal step. Pre-fills with dollars (cents/100). Saves by rounding dollars*100 back to cents to avoid float drift. Domain-policy badge also shows "max $X/action" instead of "Yc/action". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR bundles three UX-polish improvements across the web settings page and API “twin”/“evals” endpoints, aimed at making learning confidence and preference descriptions more intuitive and making spend guardrails editable in dollars.
Changes:
/api/evals/:userId/confidencenow incorporates both preferences and inferences (explicit/corrected preferences treated as “confirmed”).describePreference()generic fallback produces more human-readable descriptions (especially for string values).- Settings spend limits now display/edit in dollars and convert back to cents on save; domain policy badges display
$X/action.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| apps/web/public/js/pages/settings.js | Show spend limits as dollar inputs and convert back to cents on save; display policy max as dollars. |
| apps/api/src/routes/twin.ts | Improve generic preference description formatting (strings/booleans/numbers). |
| apps/api/src/routes/evals.ts | Update confidence metric to count preferences + inferences and add totals to response. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+438
to
+443
| // Inputs are dollars; convert to cents for the API. Round to avoid | ||
| // float drift (e.g. 100.10 → 10010, not 10009.999...). | ||
| const dollarsToCents = (id) => Math.round(parseFloat(document.getElementById(id).value) * 100); | ||
| await updateAutonomySettings(userId, { | ||
| maxSpendPerActionCents: parseInt(document.getElementById('max-per-action').value, 10), | ||
| maxDailySpendCents: parseInt(document.getElementById('max-daily').value, 10), | ||
| maxSpendPerActionCents: dollarsToCents('max-per-action'), | ||
| maxDailySpendCents: dollarsToCents('max-daily'), |
Comment on lines
+321
to
325
| if (typeof value === 'string' && value.trim().length > 0) { | ||
| // The string IS the preference — surface it directly so it doesn't read | ||
| // like a config file ("find_travel_deals = i love travel deals"). | ||
| return `${domainLabel}: ${value.trim()}`; | ||
| } |
Comment on lines
326
to
328
| if (value !== null && value !== undefined) { | ||
| return `${domainLabel}: ${key.replace(/_/g, ' ')} = ${String(value)}`; | ||
| return `${domainLabel}: ${humanKey} — ${String(value)}`; | ||
| } |
This was referenced Apr 26, 2026
jayzalowitz
added a commit
that referenced
this pull request
Apr 27, 2026
…h work (#87) Captures eight PRs (#77, #78, #79, #81, #82, #83, #84, #85, #86) under an [Unreleased] section. No code changes — pure documentation. Bumping VERSION + cutting a tag is left as a separate decision so the release moment stays explicit. Co-authored-by: Claude Opus 4.7 <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.
Summary
Three small P3 polish items from #53. All independent, bundled because they're each ~5-15 lines.
1. "How well I know you" now counts preferences, not just inferences. A user with 5 explicit preferences and 0 inferences was seeing 0% even though the twin clearly had real knowledge. The `/confidence` endpoint now combines both signals, and explicit/corrected preferences weight as `'confirmed'` (the user told us directly).
2. Generic preference description no longer reads like a config dump. Was: "Travel: find_travel_deals = i love travel deals". Now: "Travel: i love travel deals" — string values surface as the preference itself. Booleans and numerics still include the key for context.
3. Spending guardrails accept dollars, not cents. Inputs now show a "$" prefix and decimal step. Pre-fills as dollars, saves by rounding dollars*100 back to cents (avoids float drift). The domain-policy badge also shows "max $X/action" instead of "Yc/action".
Test plan
Refs #53 (P3)
🤖 Generated with Claude Code