AI Kanban
Todo
5#116
Evaluate: do the ai-rules workflows need custom sub-agents?Investigate/decide whether the workflows in the ai-rules repo (e.g. orchestrated-feature-dev, orchestrated-reasoning, review-changes, scout/gather/plan nodes, etc.) would benefit from dedicated CUSTOM sub-agent definitions rather than the current generic Sonnet/Opus/Fable role prompts. Consider: which workflow roles (gatherer, investigator, behavior-risk cataloguer, planner, adversarial verifier, etc.) recur enough to warrant a named custom agent with its own system prompt/tool policy/model; the maintenance + reuse trade-off vs. inline role prompts; how custom agents compose with the existing node-based structure; and any platform constraints (Claude Code subagent registry, cursor/antigravity variants). Deliverable: a recommendation (which agents to create, if any) + rationale, then a follow-up implementation card if the answer is yes.P0
2 months ago
#117
Build monthly automation: AI architecture review of active projectsCreate an automation (e.g. a monthly cron job driving an AI agent) that reviews the ARCHITECTURE of each active project and reports back improvement + refactor suggestions tailored to the project's current situation. Scope to nail down: (1) which projects count as \"active\" and how to detect them (recent git activity? an explicit list? AI-Kanban cards?); (2) what the agent inspects — repo structure, module boundaries, dependency graph, hotspots/churn, tests, tech-debt markers, recent direction; (3) output format — a per-project written report (top issues, concrete refactors, risk/effort) delivered to Telegram and/or filed as AI-Kanban cards; (4) cadence + delivery via the OpenClaw cron/isolated-agent mechanism (monthly, per project or batched). Prefer reusing an existing review/orchestrated-reasoning workflow over building from scratch. Deliverable: the scheduled automation + a sample report on one real project.P0
2 months ago
#222
LMS: no rate limiting on public self-registration (/join/[token])Follow-up from card #218 (course join requests). The user explicitly chose to SHIP WITHOUT rate limiting, with the exposure quantified — this card tracks the accepted debt.
EXPOSURE (measured, not estimated):
- /join/[token] is the app's first unauthenticated WRITE path. Anyone holding a valid invite link can create accounts in a loop; username uniqueness is satisfied by incrementing a counter.
- The invite token never expires (D2). The only kill switch is disableInviteToken, which breaks the link for every legitimate student too.
- Cost per account: 5 documents written — user, account (password hash), session (created then discarded, since nextCookies() is not configured, so it is pure garbage), student, course_join_request.
- Plus one scrypt hash at N=16384 r=16. Memory is 128*N*r = 32 MiB and ~70ms CPU for Node's NATIVE scrypt; better-auth uses the pure-JS @noble/hashes implementation, typically several times slower. This is the sharp end — a few dozen concurrent requests pin a CPU and push memory hard.
- better-auth SHIPS a rate limiter but it runs in the HTTP router's onRequest hook. The server action calls auth.api.signUpEmail IN-PROCESS, so the router never runs and the limiter is bypassed entirely. proxy.ts's ALLOW_PUBLIC_SIGNUP kill-switch likewise only gates POST /api/auth/sign-up/email — this action creates accounts regardless of that setting.
- Where the junk lands: StudentService.listStudents is a bare find({}).sort() with no pagination (the admin students page renders every row). UserRoleService.listUsers caps at 100 but still sorts on an unindexed email field. The join-request queue (step 27) has no pagination either, and every flooded request lands on the SAME course.
RECOMMENDED MITIGATION (declined for now): a per-course cap on outstanding pending requests, enforced in joinSignupAction before registerStudent — one countDocuments, refuse above ~200 with the generic invalid-invite message. No new infrastructure, no index, and it refuses BEFORE the scrypt hash so it caps the CPU lever rather than just the row count. A time-windowed variant (requestedAt > now-1h) is strictly better but wants an index on requestedAt, which would be this repo's first (there is no index-bootstrapping mechanism today).
NOT recommended: IP throttling in proxy.ts — Next middleware is stateless across instances, so it needs external state to mean anything.P0
4 weeks ago
#287
LMS: test status ignores an open redo; expired timed test that never auto-submitted can't be submittedFound during research for card #284 (visual-QA fixes), deliberately left out of that run (decisions D9 / S6, D18).
1. During an active redo, the student and admin still see "Graded" or "Submitted" — test-status-service.ts does not read redo state.
2. If a timed test's auto-submit never fired (tab closed), the expired test can never be submitted and is stuck forever.
3. (RA6) A redo on a timed test whose clock ran out long ago: the countdown opens at 00:00, the automatic submit deletes the old submission and is then refused with "Time limit exceeded" — the student ends with no submission and no way to answer. After #284 lands, this student reads In Progress instead of Submitted.
4. (RA7) After a redo resubmission, old free-text grades survive: status can jump straight to Graded, and with a test-wide release the student sees old feedback on new answers.
Details: lms/tmp/visual-qa-fixes/RESEARCH_FOLLOWUP_logic.md ("Follow-ups found outside the 52 findings") and BEHAVIOR_RISKS.md RA6, RA7.P0
last week
In Progress
0Staled
58#28
Take over Vince's tasksTake over Vince's tasks (handover). No deadline specified yet. Next step: get the list of Vince's tasks/responsibilities so they can be broken out into individual cards. Note: no custom fields for deadline/assignee yet, so extra detail lives here in the description.P0
3 months ago
#86
Research simple beginner robots for kids (easy build + simple coding)Research simple robots that can be built easily by kids following instructions, and that involve simple/beginner coding. Produce a shortlist of kits/projects with: build difficulty, age range, cost, what coding is involved (block-based vs text), and where to get instructions.P0
3 months ago
#106
Audit orchestrated-feature-dev + rules against Graph EngineeringResearch the "Graph Engineering" framing (Steinberger tweet Jul 2026, LangGraph/ADK/AutoGen GraphFlow prior art) and audit the existing skill system — orchestrated-feature-dev nodes/routing, feature-dev-lite, orchestrated-reasoning, scout-and-plan, and .claude/rules — for how well it holds up as an explicit stateful graph. Output: findings + improvement proposal. No file changes this pass.P0
2 months ago
#111
UBET-4202 FE: send referral code on comment/vote/reactionClose the FE half of UBET-4202 (found during testnet verification on card #105): the backend accepts `referralCode` on /commentOnMarket, /voteOnMarketOutcome and /comments/:id/reactions and establishes the market_referee link from it, but the frontend only ever attaches the stored code to BETS (usePlaceBetMutation). A referred user who engages without betting earns their referrer nothing.
Worktree: upredict-frontend-ubet-4202, branch feat/UBET-4202-fe-referral-code-on-interactions off origin/main aff515bd.
Decided approach (user's call): extract a shared getStoredReferralId() helper and read it INSIDE the fetch functions (createComment, toggleCommentReaction, voteOutcome), and refactor usePlaceBetMutation to use the same helper instead of its inline localStorage read.P0
2 months ago
#112
Local Claude Code context/cost readout: parser + status script + skill (+ VSCode bridge)Build a LOCAL (no network) readout of Claude Code context + cost, as one shared parser feeding three consumers. Remote sync + dashboard is a separate card.
## Deliverables (build in this order)
1. **Parser library** — reads the live session transcript, returns context size, per-turn cost, subagent cost, session total. Prototyped + validated 2026-08-01.
2. **Status script** — standalone, prints ONE line to stdout. Wire to `statusLine.command` (works in terminal today).
3. **Skill** — deep on-demand view, same parser. Works in BOTH terminal and VSCode extension today, so it unblocks the ambient-display problem.
4. **VSCode status bar bridge extension** — thin wrapper that shells out to the status script and renders stdout in the native status bar. Works in VSCode + Cursor. Build only if the skill proves insufficient.
## Verified mechanics
- Transcript path: `~/.claude/projects/<cwd with / replaced by ->/<$CLAUDE_CODE_SESSION_ID>.jsonl` — verified working.
- **Context size = the LAST assistant record's `input_tokens + cache_creation_input_tokens + cache_read_input_tokens`.** NOT a sum across turns (that gives cumulative usage, ~15x larger and wrong).
- **CRITICAL: dedupe by `(requestId, message.id)` keeping MAX `output_tokens`.** Claude Code rewrites each assistant message to the JSONL repeatedly while streaming; early copies hold partial counts (e.g. 7 then 1505). Taking the first/last naively misreports the headline number by up to ~200x. This is the single highest-risk bug in this card.
- `input_tokens` being ~0 is CORRECT — nearly all context arrives as cache_read. Do not "fix" it.
- Subagent transcripts: `~/.claude/projects/<slug>/<session-id>/subagents/agent-*.jsonl` (nested one level deeper; a one-level glob misses them entirely — they were 27% of historical spend).
- Pricing: cache read 0.1x input; cache write 5m 1.25x, **1h 2.0x** (`usage.cache_creation.ephemeral_{1h,5m}_input_tokens`). Sonnet 5 is on intro $2/$10 per MTok **until 2026-08-31** (list $3/$15).
- Context windows: 1M for Opus 5/4.8/4.7, Sonnet 5/4.6, Fable 5; 200K Haiku 4.5. Model string may carry a `[1m]` suffix — strip before lookup.
## Status line format
`◐ 43.8% (438K/1M) · turn $0.28 (+$0.11 sub) · carry $0.22/turn · ⚠ cache miss`
- context % + absolute vs the model's real window
- last turn cost, subagent broken out separately with `+`
- **carry cost** = `context * input_price * 0.1` — what the NEXT turn costs before you type anything. The headline insight: context is a recurring bill, not a capacity gauge. On a live 438K-token session, 78% of each turn's cost was just re-reading context.
- warnings: cache-prefix invalidation (large cache_creation + small cache_read => that turn cost up to 20x the cached equivalent), and context crossing a threshold
## Locked decisions
- Status line REPORTS AND WARNS (not purely informational).
- Subagent cost DISPLAYED, broken out separately (not silently rolled in).
- Skill covers CURRENT SESSION ONLY, fully local, no network.
- Scope is claude-code only — dropped the original cross-agent mirroring to cursor/antigravity (transcript format, session-id env var, and cache-tier accounting have no equivalent there).
## Performance note (VSCode bridge)
Watch the project dir and read only the TAIL (~256KB) of the transcript — do not re-parse a multi-MB file on every append. Still apply max-output_tokens across copies in the tail, or the status bar flickers through partial streaming values before settling. The bridge cannot ask Claude Code which session is active (no API); infer via newest-mtime `.jsonl` in the workspace's project dir.P0
2 months ago
#114
Z-score ladder mean-reversion strategy (scaling-in variant)New z-ladder mean-reversion strategy distinct from single-entry MeanReversionStrategy: tranche into adverse moves at increasing z deviation, basket stop on averaged entry, exit all on reversion. Needs engine multi-tranche position state + averaged stop + cross-tranche solvency budget. Falsifiable bake-off vs single-entry on same walk-forward + DSR harness. Built via orchestrated-feature-dev.P0
2 months ago
#118
Cross-machine Claude Code usage sync + dashboard UIAggregate Claude Code usage from BOTH machines into one remote DB, with a web UI for visualisation. Sibling of card #112 (local readout) — reuses the SAME parser library; build #112 first.
Motivation: ccusage is accurate but per-machine by construction, and the JSONL contains NO account/org/machine identity — so cross-machine and per-account attribution can only be solved at sync time, never reconstructed later.
## Sync behaviour (locked)
- **Triggers: `SessionStart` (inline upload) AND `UserPromptSubmit` (dirty-marker only, detached).**
- `SessionEnd` is REJECTED — does not fire on tab close, crash, or kill -9.
- `UserPromptSubmit` must NOT do network I/O inline: it runs BEFORE the model sees the prompt, so it is in the per-turn latency path and a hung connection stalls the session. It writes a dirty marker and exits (~5ms); upload happens detached. Needs a real detach — `& disown` is not always enough since Claude Code can wait on inherited fds.
- `UserPromptSubmit` structurally never syncs the last turn of a session; `SessionStart` catches it on next launch.
- **No cron, no launchd, no daemon.** The JSONL on disk is the durable source of truth and survives every failure mode; the hooks are freshness, not delivery. Staleness is bounded by "when you next open Claude Code on that machine" — an idle machine generates no new usage anyway.
- **On failure: do nothing, exit silently.** No error surfaced into the session, no retry logic.
## Data rules
- **Aggregates ONLY — transcripts NEVER leave the machine.** The JSONL contains source code, file contents, and all tool output. Ship token counts per message. Entire history is ~46K rows.
- **PK `(request_id, message_id)`** — globally unique. Makes re-sync a no-op: no watermark, no "what did I already send" state to corrupt, no harm in overlapping ranges.
- **Self-healing upsert** — `on conflict (request_id, message_id) do update set output_tokens = greatest(excluded.output_tokens, usage_events.output_tokens)`. This makes the streaming-partial bug IMPOSSIBLE TO PERSIST: a row written from a partial record is corrected upward on any later sync. Build this in rather than trusting the reader.
- **Stamp at write time: `machine_id`, `account_uuid`, `org_uuid`** — none exist in the JSONL. `machineID` + `oauthAccount.{accountUuid,organizationUuid}` come from `~/.claude.json`.
- **Store `cost_usd` computed at sync time**, plus a separate `pricing` table for audit. Do NOT compute cost at query time from current prices: Sonnet 5 intro pricing ($2/$10 vs list $3/$15) expires **2026-08-31**, and query-time pricing would silently reprice all pre-expiry history.
- Include `is_subagent` (subagent transcripts are nested at `<session-id>/subagents/agent-*.jsonl`; ~27% of historical spend).
## Backfill
One-shot script per machine over existing history (~46K rows, ~$5.9K of usage). Same parser, same idempotent upsert.
## Dashboard UI
Web app over the synced data. Wanted views:
- cost per day / per machine / per project / per model
- subagent share of spend over time
- cache efficiency (read vs write ratio) — spikes indicate prefix invalidation
- session drill-down
- optional: join `~/.claude/usage-data/session-meta/*.json` (tool counts, git commits, lines added/removed, interruptions, response latency) for cost-per-commit style metrics. NOTE: only covers 134 of 175 sessions and looks like a one-off snapshot from 2026-07-01 — verify it still regenerates before depending on it.
## Open (deferred by user until behaviour was settled)
1. **DB host** — recommend a NEW dedicated Supabase project (Supabase MCP already wired; Postgres over REST means the sync is a plain curl with no client library on either machine; RLS keeps it private). Alternatives: existing mainnet/testnet project (mixes personal telemetry into something else), or Neon via personal-infra Pulumi (consistent with existing IaC, but needs a PR/deploy cycle and free tier has a 6h retention cap).
2. **Account topology** — do both machines run under the same Anthropic account (`b7bc187e-7b55-4c62-8977-c069bffdfd83`), or is one a work account? Decides whether `account_uuid` is a constant or a real schema dimension. Recommend modelling it as a first-class column regardless, so adding a work account later needs no migration.P0
2 months ago
#122
Fix near-bankrupt sleeve inflating the 1/N blended book (fake +9193% bar)Run #28 showed a single +9193% bar (equity 5,254 -> 488,352 in one hour). Root cause found: on 2021-04-16 22:00 dogeusdt's fold equity fell 2,045 -> $1.62 (Doge squeeze over a naked short), then recovered to $1,329 = +82,002% in one bar; _blend_1n averages the 9 coins' RETURNS index-wise so that became +91.1 blended.
TWO compounding causes: (1) the S4 bankruptcy floor is a knife-edge at exactly equity<=0, so a sleeve at $1.62 of $10,000 is economically dead but treated as fully alive with astronomically leveraged percentage returns; (2) _blend_1n averages percentages, implicitly re-funding every sleeve to a full 1/N each bar, so a dead sleeve's +82,000% is credited as if earned on real capital.
DAMAGE: run #28 reads +409% total but that ONE bar is 92.9x — everything else is -94.5%; mean-of-fold Sharpe was -1.105 and the DSR gate still PASSED at 0.970. Run #27 (the z-ladder research run behind the "scaling-in beats single-entry, +0.366 stitched" conclusion) has the SAME artifact from the same Doge event (+1292% bar = 13.9x; everything else -87.2%), so that headline is NOT supported and the project memory + docs/features/zscore-ladder-mean-reversion/spec.md are now wrong.
FIX (user approved both): (1) insolvency threshold instead of a knife-edge — liquidate and hold dead below a fraction of starting capital; (2) blend DOLLARS not percentages so a dead sleeve contributes its actual negligible capital. Then re-run #27/#28 configs for honest numbers and correct the memory + spec.P0
2 months ago
#123
Trade chart: panel titles + TradingView-style zoom/panThe two charts inside the run page's "Trade detail" card are untitled: the price+markers ComposedChart and the net-exposure AreaChart. Add clear titles to both. Also add TradingView-style interaction: scroll-wheel zoom anchored at the cursor, drag to pan, and a reset. Both panels MUST share one x-domain so markers stay aligned with the exposure step, and the y-axis should rescale to the visible window. Equity/Drawdown cards already have titles (CardTitle) and use a string-category x-axis, so they are out of scope unless asked.P0
2 months ago
#136
Template-clone the test database fixture instead of rebuilding per testBranch perf/test-db-template, stacked on fix/anvil-fixture-flakes (PR #717). Follow-up to card #109: the dbFixture hook timeout was MASKED there (15s->30s), not fixed. Root cause is that testDbFixture runs with each:true and each run does initdb + boot a whole postgres server + replay ~3116 lines of schema DDL + seed mock data - measured 3114ms - for EVERY test, with 4 jest workers doing that disk-heavy work concurrently. That contention is what blew the hook in a run whose lint/compile times were completely normal.
Measured with a scratch probe: full build 3114ms vs `create database ... template` clone 242/317/349ms (mean 303ms) = 10.3x on database provisioning alone.
Approach: hide the whole mechanism inside lib/core so dbFixture's returned shape (adminClient, pgInstance, db, readOnlyDb - used in ~96 places across the suites) is unchanged. makePostgresInstance now lazily builds ONE server + template database per (worker, preamble) and clones per call; PostgresTestInstance.kill() drops the clone rather than killing the server. New shutdownPostgresTemplates() export, called from an afterAll registered inside testDbFixture, so template lifetime is per test FILE - matching how anvil and the seed data already work.
Rejected alternatives, with reasons: each:false (trades away the per-test isolation ~660 tests are written against; marketRoute alone asserts an exact count of closed markets, so cross-test pollution would surface as order-dependent failures - a nastier flake class than the one being fixed). Schema-per-test (user's own objection, correct: it still replays all the DDL into the new schema and re-seeds; only saves initdb+boot. Template skips the DDL entirely because it is a file-level copy).P0
2 months ago
#137
DCA intramonth entry-timing rule — basket dip-watch (STRATEGY_NOTES §6)Add an intramonth entry-timing rule to the monthly DCA (stocks/funds/crypto), to fix repeatedly buying on a fixed calendar date and missing mid-month dips (2026-07: caught the recovered price ~10% above the low). Separates AMOUNT (§5, unchanged) from TIMING. Rule: ONE buy/month, triggered when the held BASKET (not the index) closes ~5% below its trailing 20-day high, else a month-end backstop; single-name −12% override; crypto ~10% per clip. Numbers distribution-set from 15 months of VNINDEX (2/3 of months dip ≥5%; median deepest −6.1%, range −0.2%..−15.4%). Daily check = price-only on ~9 held names (Claude's job); name-selection stays at the monthly buy via §3.0/§3.1.P0
2 months ago
#145
Quant: prune ML artifacts, fix picker sort order, design engine upgrades (regime/multi-TF/trailing exits/sampling)Three asks from the user on quant-trading:
1. CLEANUP — tmp/pooled_direction_artifacts holds 531 top-level fold_* dirs (44MB) plus run_1/ (3 folds, newest). Prune to only the latest set. Other tmp/ml_artifacts* dirs total ~430MB and are also scan candidates (QUANT_ARTIFACT_ROOT defaults to "tmp").
2. SORT BUG — /ml/artifacts picker shows 2020-trained folds on top. Root cause: scan_artifacts (src/quant/ml/prediction/artifact.py:144) sorts by manifest.json MTIME, but the UI label reads "trained <window>". Walk-forward writes fold_000 (2020) -> fold_529 (2026) chronologically; a partial re-run on Aug 4 re-wrote folds 000-002 only, so the OLDEST training windows got the NEWEST mtime and float to the top.
3. ENGINE UPGRADES (design + build) — user's four directions: (a) more knowledge/features into training; (b) randomised/regime-stratified training windows so the model isn't only trained on bull and tested on bear; (c) feed BOTH daily and hourly bars + their MAs so the model can see the current regime; (d) trailing exits instead of a fixed TP at a predicted barrier price.
Context: prior memory says single-asset direction ML has repeatedly FAILED honestly (v1/v2/v3, pooled-panel all negative). Any engine change must be judged against that, not assumed to rescue it.P0
2 months ago
#146
UBET-4243 Subscribed notification tab — flat per-event list (react/reply/mention), BE APISplit from UBET-4239 "make notification platform API support new notification UI". Ticket text: a reaction (emoji) or reply to YOUR comment goes to `Subscribed`; commenting/replying on a market subscribes you to that market; tagging/@mention also goes to `Subscribed` (UBET-4239 had said `Mention` — 4243 overrides that); interactions on a market YOU created must NOT also appear under Subscribed; mystery box + streak claimable notifications go to `All`. Backend notification-platform API work in upredict-backend. Adjacent in-flight work: card #141 / PR #727 (feat/UBET-4216-notification-feed-unread-first, grouped Comment/Vote feed leg, unmerged) and card #140 (UBET-4057 claimable notifications, unpushed) both rewrite the same unified feed. Following orchestrated-feature-dev; workspace tmp/ubet-4243.P0
upredict-backend·feat/UBET-4243-subscribed-notification-group2 months ago
#154
UBET-4179 merge duplicate comments (BE) — collapse identical comments + return who said itTicket UBET-4179 (epic UBET-3691 "BM - Our Own Comments"): a market shows too many duplicate comments. Merge identical comments into one entry and return an object listing the people who posted the same comment, so the FE can render "+10" with hover to see who. Backend (upredict-backend / belief_locker), worktree workspace/upredict-backend-ubet-4179, branch feat/UBET-4179-merge-duplicate-comments off origin/main 2d3e69e5. Running orchestrated-feature-dev; workspace tmp/UBET-4179. User wants to stop after the implementation plan for review.P0
2 months ago
#155
review-changes: auto-tier the pipeline by diff size to cut token costThe claude-code review-changes skill spawns 10-12 sub-agents per review (1 holistic + up to 6 lenses + 2-4 verifiers + 1 merge). Each sub-agent pays ~30k input tokens of fixed overhead (system prompt + tool schemas ~12k, injected repo CLAUDE.md + .claude/rules/* ~12-15k, node file + lens-common.md ~2.5-4.5k, HOLISTIC.md ~2k) BEFORE reading any diff => ~300-360k tokens of pure overhead per run. Holistic gates lenses on applicability (does the diff touch auth / a migration) but never on SIZE, so a 40-line diff costs about the same as a 3000-line one.
DECISION (user, 2026-08-07): auto-tier inside the existing skill (no separate lite skill, no manual override arg), and group the lenses on the cheap path.
Tier ladder, decided by holistic (which already emits an eligibility verdict):
- stop / single-inline-pass — unchanged, 1 agent
- compact (small diff, neither security nor architecture fired) — 1 grouped reviewer covering all applicable lenses, capped verify, sonnet merge => ~3-4 agents
- grouped (medium, or small+risky) — 2 agents: `mechanical` (correctness+quality+tests+performance, sonnet) and `deep` (security+architecture, session default) => ~5-6 agents
- fan-out (large: >~25 files or >~1000 changed lines) — today's 6-lens pipeline, unchanged
Security/architecture never share an agent with the mechanical lenses when they fire, preserving the skill's existing "never discount security" rule.
Scope: claude-code variant (skills/claude-code/review-changes/). Cursor variant shares the node files and may be ported; antigravity is a single-agent inline design with no fan-out, so the tier ladder does not apply the same way.P0
2 months ago
#156
Balance BE jest CI shards by measured duration instead of file-count hashDistinct follow-up to card #136 (template-clone fixture, PR #725) — same goal of cutting BE CI time, different mechanism.
upredict-backend CI splits ~107 belief_locker test files across 4 shards using jest's DEFAULT sharder, which sorts files by SHA1 of their rootDir-relative path and takes an equal-COUNT slice. It has no knowledge of runtime. Reproduced the hash assignment in Python: 107/107 files matched the observed CI split exactly.
Measured on run 31163619775 (branch perf/test-db-template): per-shard work is 1742 / 1366 / 1907 / 1802 seconds — a 40% spread. Shard 3 is the critical path at 521.9s of jest, 647s of job wall-clock.
Second, independent defect: within a shard, jest's sort() falls back to FILE SIZE descending when no timing cache exists (always true on a fresh CI runner). On shard 3 that dispatched serverNoBets.referrals.test.ts (3.8KB but 86.4s) last, at t=435.5s, extending the shard from ~436s to 521.9s.
A 4-worker list-scheduling simulator driven by file-size order reproduces all four observed shard wall-clocks to within 2.8s (shard 3 to 0.1s), so the mechanism is confirmed rather than inferred.
Projected: duration-balanced shards + duration-desc ordering gives a 427.5s critical path vs 521.8s today — 94s / 18.1% — within 1.4s of the theoretical floor (total work 6817s / 16 lanes = 426.1s).
Hard ceiling: server.reveals.advanced.test.ts alone is 403.8s, so no shard or worker count beyond 4x4 buys anything until that one file is split.P0
2 months ago
#157
Mirror testnet config + migration into production for release 20260805.2 (upredict-infra #700)Production release PR https://github.com/SportsFI-UBet/upredict-infra/pull/700 upgrades production 20260731.4 -> 20260805.2. It currently only bumps ci/configs/production/pipeline-config.json; the testnet-side config + migration changes for that window still need mirroring into production.
Release window commits (testnet): 20260804.2 (#694), 20260805.1 (#696), 20260805.2 (#697).
Scope determined from git history + the PR's own PostgresMigrationCheck comment:
1. Migration: copy Terraform/testnet/postgres/migrations/20260801015000_add_user_alias_source_backfill_and_not_null.sql -> production dir byte-identical, then `atlas migrate hash`.
2. Config: remove dead `defaultTrendingMarketSize` from config/production/belief_locker/belief_locker-config.yaml (backend #726 dropped the field from HomePageConfig).
EXCLUDED deliberately: 20260805000000_add_reaction_market_interaction_type.sql — verified the 'Reaction' value of market_interaction_type_enum first appears at backend tag 20260807.1 (commit c488d2b3, UBET-4243), NOT in 20260805.2. Belongs to the next release.
Working in worktree ubet-devenv/worktrees/infra-deploy-700.P0
2 months ago
#165
Quant: broad-universe VN equity arm (survivorship-free universe + MR/momentum/value)Follow-on to the vn-market-arm FAIL (card #151/#163, run 37: strategy -0.4443 vs basket +0.9855). That arm's own stated caveat was that it exists to test cross-sectional BREADTH (~400 names) but ran on 30 — and those 30 were today's VN30 projected backwards, i.e. known survivors.
Operator ask (2026-08-10): build an arm that picks stocks from a much LARGER basket and does NOT depend on today's VN30 to choose names 20 years ago. Instead: take whatever stocks were actually available/listed at each point in time, then run a cross-sectional strategy family over them — mean reversion, momentum, or value-style holding (buy cheap + business doing well; sell when rich if a cheaper name is available).
Workspace tmp/vn-broad-universe-arm. Running under orchestrated-feature-dev, operator asked NOT to gate on review between phases (2+ defensible-behaviour product decisions still get escalated).
Reuses the pluggable MarketConventions built in the previous arm (sell tax, T+2, lots, long-only, 250-bar year).P0
2 months ago
#168
RISE-15476 — Standard Setting: control assessment stakeholders by organization status & typeOrchestrated-feature-dev run for RISE-15476 (epic RISE-15475, DF `release_org_type_sm`, precondition DF `supplier_management`).
Redesign the Standard Settings > Assessment "Restrict Organization for assessment stakeholders" block:
- New layout/text; sections: Assessed Organization (2 radios: One Assessed Organization only [default] / Assessed Organization and partners), Selected Partner (appears only for the "and partners" radio), Executor Organization (NEW).
- Each section gets 2 optional checkboxes: "Filter by organization status" and "Filter by organization type". Unchecked by default; once checked, at least 1 value required (multi-select dropdown). Values sourced from SM (org status / org type).
- View mode: hide any filter whose checkbox was not selected.
- Auto-share block: only available when "One Assessed Organization only"; first toggle enabled by default and uneditable; NEW checkbox "Share with organization type(s)" behaving like "Filter by org type".
- Technical notes: log assessment settings in Std configuration in DB; Assessment settings needs a link to navigate from other pages.
Blocks RISE-15478, RISE-15510, RISE-15479, RISE-15477, RISE-15482.P0
2 months ago
#171
RISE-15509 — Allow creating associations between new ORG_TYPES from SMWiden RSC's write API so SM can push org + relationship changes for the new SM-aligned org types. Epic RISE-15475, implements PRP-2222. Sibling ticket RISE-14815 (dup epic RISE-14821) proposes the same endpoint with fuller AC — confirm which is live.
SCOPE (clarified by operator, not in the ticket):
- RSC OWNS association + org-type data. Not mirroring SM's schema, not reading associations from CDC.
- CDC read-side work (RISE-14881 etc.) is a separate track.
- RISE-15515 (Kafka) is the same payloads async, deferred — the REST contract designed now is what that consumer reuses.
- Write path is DF-gated; reject when DF off.
- RSC adopts SM's org-type names. Direction for symmetric pairs: SM decides, RSC stores as sent.
THE CORE MISMATCH: SM stores org type once per ecosystem (ecosystem_organization.type). RSC stores it once globally (organizations.type). RSC has no per-ecosystem type slot.
BLOCKERS TODAY:
- RSC validator rejects most pairs: partnerId in {partner,inspection_service,agency}, factoryId in {factory,partner}, ecosystemId must be retailer (validators.js:240-246).
- SM drops most pairs before sending: should_process_rise_sync requires exactly {SUPPLIER,FACTORY}, silently (rise_association_trigger.py:11-17).
- Adding org types touches PG enum organization_types used by 3 columns (organizations.type, onboarding_organizations.type, plans.org_type) AND needs plans rows seeded or subscription creation fails.
Design doc (309 lines, all PRE measurements): /Users/quan.vo/Documents/git-repos/inspectorio/RISE-15509_SM_RSC_ORG_MODEL.mdP0
rs-backend·feature/RISE-15509/allow-associations-new-org-types2 months ago
#179
CCP environments phase 2: GCS zipball storage, 10MB streaming cap, build-queue + claim, fire-and-forget auditFollow-on to card #147 / PR #114 (ConcreteEngine/ccp, branch feat/environments-async-build, worktree ccp-environments-async-build/). PR #114 shipped POST validation + HTTPS-only GitHub URL check + PUT /:envKey build reports. This card covers the scope that arrived afterwards.
SIX PIECES OF WORK
1. 10 MB cap on the zipball, enforced WHILE STREAMING to disk (Readable.fromWeb + byte counter + AbortController). Verified empirically: GitHub zipball 302s to codeload and sends NO content-length for real repos (express/react/linux); only a toy repo did. Repo metadata `size` is not a substitute — express reports 9843 KB but its HEAD zipball is 220,607 bytes (46x over) because size covers full git history.
2. Store the zipball in GCS (2sync bucket, alongside models/user.js createUserDirectory convention); keep only the object path on the Mongo doc.
3. GET /environments/:envKey/zipball — separate URL from build-queue so the queue payload stays small. Must stream actual bytes through CCP (NOT a signed GCS URL) because the rig can only reach CCP.
4. GET /environments/build-queue — read-only LIST of queued environments (mirrors GET /jobs/queued), employee-gated. Plus a separate POST claim endpoint that transitions queued -> building, conditionally so a second rig gets 409.
5. Unzip + Dockerfile audit (models/docker.js DockerfileAuditor is currently dead outside tests). Failure is RECORDED as a status + buildNotes, never a failed request. No unzip lib in package.json yet.
6. Delete the GCS object on the terminal PUT (success or failure).
DECIDED
- Zipball storage: GCS.
- Audit: fire-and-forget after the POST response. Operator chose this over inline-non-fatal after being told the work is lost on restart and errors have nowhere to surface in the response. Mitigation: outcomes land on the environment doc as buildStatus + buildNotes.
- Cleanup: on terminal PUT only, so a rig can re-fetch after a failed unzip.
- build-queue returns a LIST, not one item.
- Claim is an explicit POST by ICP, never a mutation on GET — ICP can die between read and build.
- Lease / reset for environments stuck in Building: DEFERRED to a later ticket.
- Status vocabulary: keep lowercase and add statuses as needed; revisit casing after development.
- origin/docker-auditor-refactor: leave alone entirely. NOTE it cannot merge as-is (drops 'inprogress' while the route still writes it -> every create 500s). Stray tracked environments/test-env-1772721276469/Dockerfile stays.
- Rig uses the zipball, not git clone — it has no network access beyond CCP. shell-client PR #25's clone_env_repo must be replaced, and repoToken should NOT appear in the build-queue payload.
CONTEXT
- CCP has NO background job mechanism (no cron/scheduler/worker) — confirmed by grep.
- Base.upsert appends a full doc copy to log[] on every write, which is why bytes cannot live on the Mongo doc.
- Precedent: GET /jobs/queued (routes/jobs.js:112) + Job.getQueued (models/job.js:83), employee-gated via auth.email.endsWith('@concreteengine.com'). Note jobs uses 401 there while our PUT uses 403.
- ICP proxy (icp PR #37, middleware/environments.js) pipes CCP response bodies through via Readable.fromWeb().pipe(res), so binary streaming works end to end unchanged.P0
ConcreteEngine/ccp·feat/environments-async-build2 months ago
#194
UBET-4241 BE: comment sorting — boost new-user comments, then meaningful commentsTicket UBET-4241 (epic UBET-3691 "BM - Our Own Comments"), assignee Quan Vo, status Todo. Current sort: 1) engagement, 2) chronological. Change: replace the chronological tiebreak with a) new-user comments meeting condition (**), then b) meaningful comments (heuristic: comment length).
Condition (**): received no previous replies; within their first few meaningful comments; wrote a substantive, non-repetitive comment; not showing obvious farming behavior.
Ticket metric line: Why? A+ / How? A / What? B.
Every threshold in the ticket is unquantified ("first few", "substantive", "obvious farming") — requirements need clarification with the user. Driven via orchestrated-feature-dev; workspace tmp/ubet-4241.
Related board cards in the same sort path: #37 UBET-4156 (sort by interactions, DONE — the engagement tier this builds on), #185 UBET-4184 (own-reply-on-top, need_review, unpushed branch), #154 UBET-4179 (duplicate comment merge, staled branch).P0
2 months ago
#196
SSI FastConnect ingestion + vnstock corporate-action adjustment auditTwo workstreams off the back of card #165's SSI probe (F49-F51).
(0) Build scripts/pull_vn_ssi.py and ingest SSI FC Data DailyStockPrice 2020->present for the 954-name roster into a NEW data/vn_ssi/ store. Carries SSI's unique fields: CeilingPrice/FloorPrice, full foreign flow (ForeignBuyVolTotal/ForeignSellVolTotal/NetBuySellVol/NetBuySellVal/ForeignCurrentRoom), ClosePriceAdjusted. ~73k requests at a 30-day window cap; real rate limit must be MEASURED, not assumed.
(1) Audit whether vnstock's prices (data/vn_broad/, the bars every VN arm has ever run on) are corporate-action adjusted, by comparing SSI ClosePrice vs ClosePriceAdjusted vs vnstock close over the 2020-2026 overlap. HIGH VALUE: long_term_reversal uses a 1000-day lookback, so unadjusted splits would make a 4-year return meaningless. Precedent for vnstock defects exists (B32 padded bars, B80 silent truncation).
Neither reopens card #165's FAIL verdict (pre-registration clause (a)/(e)); this tests its INPUTS.P0
2 months ago
#197
Fix CI hangs from apt/Ubuntu-mirror stall in Setup PostgreSQL (upredict-infra + upredict-backend)Root cause (confirmed): the `Setup PostgreSQL` step (`tj-actions/install-postgresql@v3`) runs `apt-get update`. Since 2026-08-18 `azure.archive.ubuntu.com` is intermittently unreachable from GitHub-hosted runners; apt returns `Ign:` ~25x with backoff, falls back to `https://archive.ubuntu.com`, then stalls indefinitely (no apt timeout configured). Proof: run 32227794374, shard 1 = 28s (azure mirror `Hit:`) vs shards 2+3 = 45m (azure `Ign:` -> fallback -> wedge), 27 seconds apart on the same run.
Not a repo change: build.yml untouched since 2026-08-03, release-workflow.yml since 2026-07-19.
Hang duration == each job's timeout ceiling, which is why infra was far worse than backend: backend python job `timeout-minutes: 10` -> 591-603s hangs; backend ts shards `timeout-minutes: 45` -> 43-45m hangs; infra release-workflow had NO `timeout-minutes` -> ran to GitHub's 6-hour default (run 32161546065 = 360 min).
DONE: cancelled 4 wedged infra runs (32216545766 stuck 3h45m, 32225834718, 32230013499, 32231468988). Added `timeout-minutes: 10` + one-line comment to the 5 runs-on jobs (release-workflow.yml LintTypescript + PostgresMigrationCheck, validate_configs.yml validate-config, terraform_apply.yml terraform, common-workflow.yml config-images). `timeout-minutes` is illegal on a reusable-workflow caller, so the cap goes on runs-on jobs only; every `uses:` chain terminates in one of those 5, so coverage is complete. Rebased deploy-20260819.2-to-production onto origin/main (bd755c8, clean) and force-pushed with lease; commit 4523cc6 on PR https://github.com/SportsFI-UBet/upredict-infra/pull/720. Verified run 32233433516 progressing normally.
BLOCKER on the requested follow-up: a `pgvector/pgvector:pg15` **service** container will not work in either repo. `upredict-infra/ci/scripts/typescript/src/postgresDiff.ts` and `upredict-backend/typescript/lib/core/src/postgresTestInstance.ts` both call `pg_config | grep BINDIR`, then `initdb <tmpdir> --auth=trust`, then `spawn(postgres, -p <randomPort>)` — they need postgres BINARIES on the runner and deliberately use a random port per instance so matrix targets / test shards run in parallel. A service container supplies a networked server on a fixed port and no binaries.
Also note `terraform_apply.yml` has the same apt exposure via `sudo apt-get install colorized-logs`, and `Install pgvector` shells the pgdg apt script in both repos.P0
2 months ago
#210
RISE-15592 — Revalidate assessment stakeholder orgs on edit-save and follow-up requestOrchestrated-feature-dev run for RISE-15592 (epic RISE-15475). Split from RISE-15478, which delivered CREATION-time filtering; this ticket covers the EDIT-time half.
Requirement: when a requester edits+saves an assessment, or requests a follow-up, revalidate Assessed Organization, Executor and Selected Partner against the Standard's CURRENT org type/status requirements. Failing slot shows "Invalid organization" beneath it plus the alert "Some selected organizations have been removed because their organization status or organization type doesn't meet this Standard's requirements. Please review and select valid organizations to request the assessment." Assessed Organization is read-only on follow-up/edit, so a failure there blocks the flow with no in-app remedy — the error must still be shown.
Precondition: dark features `release_org_type_sm` AND `supplier_management_attributes_rsc` both on; with either off both flows behave exactly as today.
Prior art (both merged to master): RISE-15478 (creation-time Assessed Org / Selected Partner / auto-share filtering) and RISE-15479 (creation-time Executor filtering + placeholder claim). Workspaces: tmp/RISE-15479/ (full run artifacts), kanban card #193 for RISE-15478.P0
last month
#211
UBET-4282 In-App Currency Betting — currency model design (brainstorm)Epic UBET-4282 "In-App Currency Betting" / task UBET-4270 "Review betting code & planning". Both Jira issues are EMPTY (no description, no comments) — every requirement is derived from code or from the PO conversation.
Settled: betting with in-app currency runs OFF-CHAIN in Postgres. On-chain gas is currently paid by the platform; shifting it to users needs the embedded wallet, which is not ready. Off-chain removes the cost entirely.
Key code findings: payout math is ALREADY off-chain (get_bet_payout_calculations_from_result, sql_schemas/upredict_index_view_function.sql:1702) so the whole settlement layer is reusable; betting is parimutuel so the platform has no book risk — liability is only at the mint. market_bet has NO user_id (bets join to users by EVM address) and its commitment/salt/nonce/deadline-block columns are all NOT NULL, so off-chain bets need schema work regardless of the currency answer. point_ledger already carries negative rows (BetVolumeReversal), has unique(source_type, source_id) for free idempotency, but points is double precision and the display clamps greatest(0, ...), which would hide an overdraft rather than prevent it.
Structured brainstorm docs in workspace/tmp/UBET-4282/ (brainstorm-in-app-currency.md = Level 0, level-1-currency-model.md = Level 1). Level 2 NOT started — needs explicit approval.
PO answers so far: BP may be bet and lost, and losing rank that way is intended; play money for now; a BP bet earns no BP; betting currency is meant to run out and engagement refills it; one earning mechanism only (no separate faucet).P0
last month
#213
Brainstorm: Explanation docs for Concrete Engine (AI-updatable, Diátaxis)Structured brainstorm for the "explanation" quadrant of a 4-kind doc set (specs / how-to / tutorial / explanation) covering the Concrete Engine platform. Requirement: docs must be updatable by AI when code changes.
Workspace: tmp/system-explanation-docs/ — brainstorm-explanation-docs.md (index), level-0-widest-view.md, level-1-structure-alternatives.md.
User decisions: audience = new engineers onboarding; location = all at concrete_engine/ root; AI update trigger = deferred ("maybe CI, later"), so design structure for it but don't build it; existing README.md + 7 repo_knowledge/ folders stay untouched (new layer alongside).
Level 0 settled: purpose is onboarding-first with decision-record as the distinguishing content; the requirement is verify + partially-update + protect reasoning, NOT regenerate (explanation is the one Diátaxis kind not derivable from code); the defensible niche vs existing docs is cross-cutting "why"; intent is the doc spine with intent-vs-actual divergences marked inline (research/job-dispatch-gaps.md says the job path is broken end to end).
Level 1 settled: structure = layered hybrid (00-orientation.md narrative → concepts/ → decisions/), chosen because the three layers have different volatility, which is the seam that makes partial AI updates safe. Rejected per-service mirroring since repo_knowledge/ already occupies it. Updatability = provenance anchors in frontmatter + in-file derived/reasoned zones + deferred .doc-state.yml SHA snapshot, yielding a 5-step update procedure whose step 4 is "flag reasoned-zone conflicts for a human, never rewrite".
Key constraint discovered: 7 independent git repos under a non-git root, so there is no system-wide diff — docs must carry their own provenance.P0
last month
#214
calm-tantrum: calming vent-card PWA with shared-passphrase access and web pushNew greenfield app inspired by the "Paper Tantrum" novelty notepad: a user posts a structured vent (checkbox feelings/causes/requests + free text) and everyone else who installed the PWA gets a web push notification. Emotional goal is the INVERSE of the paper card — the UI calms the writer down (no alarm-red).
Confirmed: shared-passphrase access (no accounts); MongoDB; deployed via the existing personal-infra Pulumi IaC; Next.js latest + shadcn on Base UI; lavender/soft-blue theme the user can switch between; mobile-first STAGED wizard vs web all-at-once, with the two layouts branched as separate component trees from the top (not responsive CSS); every component styled when introduced.
v1 scope (all four in): (1) post+push+feed, (2) acknowledge/respond, (3) draft + calm-down pause step, (4) history & patterns.
Running the orchestrated-feature-dev pipeline; workspace tmp/calm-tantrum/.P0
4 weeks ago
#215
OpenClaw health: Chat watcher blocked by tool cap + 4 latent breakagesInvestigation triggered by the "Google Chat watcher couldn't run — no shell/exec tool" failure reported from an OpenClaw cron session.
# Root cause of the reported failure — two independent walls
**Wall A (the actual blocker): job ea9f9707 has no `exec` in its stored tool cap.**
Created 2026-09-03 from the Telegram conversation; snapshotted a 42-tool default allowlist with `toolsAllowIsDefault: true` that omits all of `group:runtime` (exec/process/code_execution) and `group:fs` (read/write/edit/apply_patch). It keeps dir_list/file_fetch/file_write, which are NODE file ops, not host shell.
`openclaw doctor` names this job and explicitly REFUSES to widen the cap ("doctor will not silently widen or rewrite it") — so `doctor --fix` does not repair it. Supported path is `openclaw automations edit <id> --tools <list>`.
**Wall B: the node fallback is dead too, for a different reason.**
Agent fell back to the `nodes` tool and called `dir.list`; gateway log 11:00:17 and 15:03:56 both: `INVALID_REQUEST node command not allowed: "dir.list" is not in the allowlist for platform "macOS 26.6.2"`. Live node runs OpenClaw.app 2026.8.1, which advertises `fs.listDir` — renamed; gateway (npm CLI) is 2026.9.1, a version ahead. Even `system.run` would fail: node `bins` = claude,git,gh,gog,node,curl,python3,jq — no bash/sh.
Evidence it never once worked: `.chat-state/snapshot.txt` still holds the 01:14 seed from `init`; no poll has advanced it.
# Other findings (unrelated to the reported error)
- **Anthropic auth profile vanished.** `auth.profiles` is `{}` in openclaw.json; all four backups have `anthropic:claude-cli` (oauth). `openclaw models auth list` → "Profiles: (none)"; `secret_store_entries` empty. Breaks `skill-collection-review-main` every run and the remote model catalog refresh. Agent turns survive only because models are pinned to `agentRuntime: claude-cli` (Claude Code's own login).
- **Telegram delivery dropping cron output.** Calendar digest ran ok 07:43 but all 4 retries failed `Network request for 'sendMessage' failed!`. Calendar new-meeting watch + Birthday notifier also `not-delivered`.
- **Version skew:** OpenClaw.app 2026.8.1 vs npm CLI/gateway 2026.9.1 — the direct cause of the dir.list/fs.listDir mismatch.
- **23:00 evening briefing** errored with "Legacy workspace setup state requires migration" — but that was its 00:58 run during the crash-loop window; the 01:08 `doctor --fix` resolved it and the 08:45 morning briefing ran clean. Expected to self-heal; watch tonight.
- Minor: 1 dead-lettered telegram ingress event; no backup ever recorded; gateway service PATH missing /opt/homebrew/opt/node/bin; plaintext gateway.auth.token + telegram botToken in openclaw.json.
# Done this session
- Truncated `~/Library/Logs/openclaw/gateway.log` (830 MB → 0; last 2 MB kept in session scratchpad). This is the launchd StandardOutPath, which has NO rotation — OpenClaw's own 100 MB `logging.maxFileBytes` rotation does not cover stdout capture, so it will regrow.
- Fixed the watchdog install mechanism. `openclaw-ops/watchdog/install.sh` symlinked the script into ~/Documents, which macOS TCC blocks for launchd's child — `watchdog.err.log` was full of "Operation not permitted" and the watchdog silently never fired until someone hand-copied the file at 01:10. install.sh now `install`s real copies of both script and plist, with the WHY in a comment. Re-ran it: watchdog live (wedge-count 0). **UNCOMMITTED** on openclaw-ops master.
# Open
1. Repair job ea9f9707 (needs a decision: command payload vs agentTurn + exec).
2. Restore the anthropic auth profile.
3. Update OpenClaw.app to 2026.9.1 to clear the node command skew.
4. Commit the install.sh change.
5. Consider a durable rotation for gateway.log (newsyslog or periodic truncate).P0
4 weeks ago
#219
Cross-project visual UI QA: screenshot every state, agent reviews for layout defectsTrigger: LMS `AddQuestionForm` renders its status `<output>` and error `<div>` as direct children of the sidebar/form FLEX ROW instead of inside the form panel, so the success banner becomes a third flex column that stretches full height and squeezes the form into a narrow strip. Same bug duplicated in add-pool-question-form.tsx. Unit tests passed (they assert message text, not placement); e2e passed (behavior, not appearance); lint/tsc cannot see it.
Generalized failure class: the state exists, is reachable, is functionally correct, and is visually broken.
Brainstorm workspace: AI-rules-repo/tmp/visual-qa-agent/ (brainstorm-visual-qa-agent.md + answers.md + prior-art.md + zoom-1/2/3).
DECIDED: capture by snapping inside existing Playwright e2e specs + assertion-free tour files for gap states; judge via deterministic in-page layout probes (overflow / overlap / empty-giant / sibling-anomaly / squeeze / contrast) feeding a NAMED-DEFECT rubric, with a vision pass only on probe suspects + pixel-changed states + a small random sample; absolute judgment now, accepted shots become baselines so later runs go quiet; ship as an AI-rules skill ONLY (no npm package); emit a human contact sheet alongside the report as the zero-cost fallback.
PRIOR ART: nothing does this end-to-end. github/awesome-copilot@web-design-reviewer (13.3K installs) has a strong ~60-item visual checklist worth harvesting, but its workflow is live/interactive with no archive, no batch mode, no measurement layer. software-mansion/argent@argent-screenshot-diff (14K) is baseline diffing — the shape of phase 2, unusable today with no baselines.
KEY INSIGHT: a vision model asked "does this look right?" is unreliable. It becomes reliable when the question turns factual — ship layout measurements alongside the pixels, give a closed rubric of named defects rather than an open prompt, and require every finding to name an element or be dropped. The trigger bug then reads as "`<output>` is the 3rd flex child of a row, 42% width, 4% ink coverage" instead of "looks weird".P0
4 weeks ago
#221
RISE-15510 — Request Bulk Assessment: filter Assessed Org / Selected Partner by standard's org type & statusOrchestrated-feature-dev run for RISE-15510 (epic RISE-15475). The BULK half of the org type/status filter that RISE-15478 shipped for the SINGLE request — 15478 explicitly scoped bulk out (D37: "the Activation List tab ships unfiltered... Operator declined the fix at Phase 5b triage. Consequence: TC-016 does NOT pass"). This ticket closes that bypass.
AC1: selecting an Activation list for Assessed Organization lists only matching orgs, shows a warning with matched/excluded counts, and offers a "Download log file" CSV (Organization ID | Name | Type | Status) of the excluded ones.
AC2: the per-row Selected Partner dropdown lists only matching orgs.
AC3: if the Admin narrows the settings while the form is open, clicking Request auto-removes the now-invalid orgs and shows an alert.
Prior art already on master: stakeholder_org_restriction.service.js (buildStakeholderOrgRestrictionPredicate, 4 slots), organizations.sm_type/sm_status (RISE-15577), the RISE-15673 ecosystem-owner status exemption. Unmerged prior art on the RISE-15592 branches: BE validateStakeholderOrgRestrictions aggregate validator, FE orgQualificationRule.ts + InvalidStakeholderOrgAlert.
Workspace: tmp/RISE-15510/ (TICKET.md, CONTEXT.md written). QA posted 28 manual test cases on 2026-09-06 (Jira comment 516664).
KNOWN CONFLICT to resolve with the PO: RISE-15478 and RISE-15592 both settled on keep-and-flag a disqualified org, never clear it. AC3 here asks for auto-removal. The alert copy is byte-identical across all three and already says "have been removed".P0
rs-backend·feature/RISE-15510/bulk-request-org-type-status-filter +24 weeks ago
#224
UBET-4297 BE: capture profile SEO/embed image once a dayTicket UBET-4297 "Profile img embedding capture once a day" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo, Sprint 118, 1d estimate, epic UBET-4272 "propagation"). NO description and no comments in Jira — requirements derived from code.
Running the orchestrated-feature-dev pipeline. Workspace: workspace/tmp/UBET-4297.
ESTABLISHED FROM CODE (2026-09-08):
- Existing pipeline is markets-only: upredict-backend/typescript/services/seo_image_generator is a Lambda that puppeteer-screenshots {originUrl}/markets/{id}/place?preview=true, waits for .preview-content, uploads JPEG q85 to S3 via presigned URL, inserts into market_seo_image. Cron cron(2/5 * * * ? *) every 5 min, lambda timeout 900s.
- It is CAPTURE-ONCE-EVER: selection query guards on `not exists (market_seo_image row) and m.status = 'Open'`. Nothing in this codebase re-captures on a schedule — "once a day" is genuinely new behavior.
- Public profile URL EXISTS on FE main (daa1daf): canonical /@<alias> (ROUTES.PROFILE = "/@:userAlias"), src/app/[alias]/page.tsx resolves alias->userId server-side then renders <ProfilePage userId>. Legacy /profile/<alias> 302s there.
- FE profile page has NO generateMetadata (metadata = {}), and NO preview render (MarketPreviewProvider / .preview-content are market-only). Those are UBET-4273 (Nick Mai) and UBET-4301 (Nick Mai), NOT this ticket.
- Backend has NO user_seo_image table — only market_seo_image (market_id, image_url, inserted_at, unique(image_url)).
- Backend already serves public GET /users/:userId/profile and GET /users/resolve-id (routes/userProfile.ts).
SCOPE PER USER: backend only. The generator loads the profile URL with ?preview=true appended; FE will handle that param later if changes are needed.
PRIOR ART ON THIS GENERATOR: card #212 (reel SEO image captures TikTok consent dialog; notes the never-retry behavior) and card #220 (UBET-4323 reel thumbnails in SEO images).P0
4 weeks ago
#227
Explanation docs: prompt evaluation + ConcreteEngine/documents repo with Gemini CIPhase 1 deliverable from tmp/system-explanation-docs/phase-plan.md: "Prompt: how to read the source repos; what belongs in the map versus in specs; house voice; the divergence marker rule."
User asked to (1) write several prompt versions, (2) spawn Haiku sub-agents to generate the docs with each, (3) rate the prompts. Credential/GH-Actions setup explicitly out of scope per user.
Experiment design: 3 variants forming a LADDER so the rating isolates which layer of prompt engineering earns its keep.
- V1 Brief — intent only (~15 lines), trusts the model. Baseline.
- V2 Contract — V1 + output skeleton, per-section content contract, explicit exclusion list, divergence-marker syntax + gap-ID table, house voice.
- V3 Procedure — V2 + mandated reading order/grep targets + every claim carries file:line + a self-check pass.
Fairness controls: identical harness preamble (role, cwd, output path, forbidden reads), same model (haiku), same 7 source repos. Root README.md and */repo_knowledge/** are FORBIDDEN reads for all three — a real runner only checks out source repos, and letting agents read the hand-written README would grade paraphrase rather than generation. Reading-strategy guidance is deliberately kept OUT of the preamble since that is exactly what V3 tests.
Target artifact: the system map (architectural half only per D1 — what calls what + user flows; no rationale, no mechanism).
Grading ground truth: root README.md + research/job-dispatch-gaps.md (gaps G1-G8, S1-S6) read into context this session.
Workspace: scratchpad/prompt-eval/ (prompts/, runs/v1..v3/).P0
4 weeks ago
#229
RISE-15634 — Spike: AI Autofill from Network Profile to RSC assessmentSpike RISE-15634 (epic RISE-15559 "[NP→RSC] AI Auto-fill Assessment from Network Profile", siblings RISE-15560 UI story + RISE-15562 Mixpanel). Deliverables: finalize technical approach, agree how many RSC question types can be read from NP, estimation + dev order.
Idea: serialize the executor org's Network Profile into JSON in GCS and feed it to the DS `rise-document-intake` service as if it were an uploaded document — the same trick phase 2 (RISE-15436, merged) already uses for autofill-from-existing-assessment.
Key refs: product brief https://inspectorio.atlassian.net/wiki/spaces/RS/pages/130810022 · API spec https://inspectorio.atlassian.net/wiki/spaces/IDS/pages/20216039 · predecessor spike RISE-15442.
Workspace: rs-backend/tmp/RISE-15634/ (DECISIONS.md, JOURNAL.md). No code written — investigation only.P0
4 weeks ago
#231
Fix Instagram reel display in the viewer appInstagram reels render badly in the normal app (not the SEO preview): the embed header overlaps itself — avatar, username and the "View profile" button collide — and the video sits pillarboxed inside Instagram's chrome.
Root cause is measured, not guessed: Instagram's embed declares min-width 326px, while REEL_CONTAINER_CLASSNAME gives it w-52 (208px) on mobile / w-64 (256px) on sm+. The embed lays itself out for a width it never gets.
Reproduced four variants side by side (scratchpad/ig-embed): (A) today at 208px — header overlaps, matches the user's screenshot; (B) iframe rendered at its natural 326px then CSS-scaled down to 208px — header renders correctly, pure CSS, no API and no backend; (C) scaled plus header cropped away — closer to full-bleed but depends on Instagram's internal pixel layout and clips the video; (D) natural 326px — renders correctly but is a wider, taller card than the TikTok/YouTube reel slots.
Related but separate: the cover-image route (og:image, 361x640 portrait, verified) would make Instagram match the TikTok/YouTube full-bleed look, but it needs a server-side UA-spoofed fetch — instagram.com sends no CORS header and the og:image tag only appears for a facebookexternalhit UA. See UBET-4323 JOURNAL F37/F38.
Distinct from UBET-4323, which only ever changed ?preview=true rendering; Instagram SEO images generate fine in production.P0
4 weeks ago
#234
Entry-timing backtest — does the §6 dip-watch beat buying on the 1st? (30 names × 8 years)Pre-registered backtest of STRATEGY_NOTES §6 intramonth entry timing, scaled up from the inconclusive D17 run (14 names × 56 months) to 30 names × ~95 months (2018-09 → 2026-08, the VCI free-tier 8-year cap).
Question: (Q1) does any dip-timing rule beat buying on the 1st trading day; (Q2) does "buy the 3 names that dipped most" beat "buy the 3 best by value score"; (Q3) what is the most efficient dip rule.
Plan + pre-registration: BACKTEST_ENTRY_TIMING_PLAN.md. Adversarial review by a Fable subagent in flight.
Key design choices: anti-survivorship cohort split (14 current winners vs 16 dropped/failed names); random-day Monte Carlo as the true null (missing from D17); whole-lot budget constraint (40M buys only ~3-8 names on HOSE, so concentration is forced, not chosen); point-in-time value score with a 45-day reporting lag.P0
3 weeks ago
#238
Quality Register — filter businesses once a year, monthly run checks only news + priceUser's directive: stop re-asking "is this a good business?" every month. Answer it once per name, cache for ~12 months, and let the monthly DCA run touch only news + price on the resulting PASS pool. WATCH/EXCLUDED names are not looked at monthly at all — they return only on a named trigger.
Wave 1 built in QUALITY_REGISTER.md from data already measured this session (v2_gate.py panel, audited vnstock statements, deep dives on IDC/SCS/FPT/VNM + §4 bank bands). 20 names classified: 7 PASS, 7 WATCH, 6 EXCLUDED, 4 NOT ASSESSED.
Still to do: propagate the new order into DCA_CANDIDATE_DISCOVERY.md (the Stage 0-4 funnel) and the monthly-dca-research skill, so the monthly flow actually reads the register instead of re-deriving business quality. Not done yet — shape needs the user's sign-off first.P0
3 weeks ago
#244
RISE-15635 — Spike: Autofill Certifications from NP to 3P questions (Epic 2)Investigation for Epic 2 (RISE-15635 / story RISE-15652): deterministic certificate picker that prefills RSC DATA_INTEGRATION (3P) questions from the Network Profile. Distinct from card #229 (Epic 1, the AI path). No spike ticket exists in Jira for this epic.P0
3 weeks ago
#245
RISE-15514 — e2e tests for assessment visibility by "Share with organization types"Write Playwright e2e coverage in unified-health-check for RISE-15514 (backend-only, already merged): a Standard's "Share with organization types" setting now controls who really has visibility of an assessment, its report and its CAPA. Gated on release_org_type_sm + supplier_management.
Two independent enforcement points must both be asserted: the precomputed assessment_orgs_visibility table (drives the assessment list) and the live checkAssessmentBusinessPartner guard (drives direct open / report / CAPA).
Two visibility modes are separate SQL statements and need separate tests: "share to all associated organizations" (business-partner predicate) and "share to individual organizations" (specific-share predicate).P0
unified-health-check·master +13 weeks ago
#247
Tier-1 spec docs: prompt evaluation for connection-level specsPhase 2 of tmp/system-explanation-docs/phase-plan.md. Same flow as the explanation doc (card #227): pre-registered rubric, prompt versions, sub-agents generate from an isolated copy of the source repos, rate, then land the prompt in ConcreteEngine/documents/prompts. CI deferred.P0
3 weeks ago
#250
RISE-15756 + RISE-15762 — correct the release_org_type_sm DF gate and define Inactive-org precedenceCross-cutting correction over epic RISE-15475's shipped work. Two linked tickets, both BACKLOG:
- RISE-15756 (Story, High, reporter Will, unassigned) — "[SM] Correct the release_org_type_sm DF gate and define precedence with the Inactive-organization rule". 9 ACs.
- RISE-15762 (Bug, High, assignee Will) — the same gate defect observed on PRE v1.426.0: with supplier_management_attributes_rsc OFF the stakeholder restriction still runs.
PROBLEM 1 (wrong flag): RISE-15476 specifies DF `release_org_type_sm` with precondition `supplier_management_attributes_rsc`. The code instead pairs `release_org_type_sm && supplier_management` everywhere.
PROBLEM 2 (no precedence): the Durians Inactive-org rule gates on `supplier_management_attributes_rsc` (via `smOwnsOrgStatus`), the Mangos restriction on the other pair. Neither reads the other, so a type-only Standard still silently loses Inactive orgs. Enforced at the picker query and at the create-time guard `assertRequesteeOrgsActive`.
Worktrees: rs-backend-RISE-15756 and rs-frontend-RISE-15756, both on branch `chore/RISE-15756/df-gate-precedence` off master (BE 3f35c4501, FE 51344f9862).P0
3 weeks ago
#253
orchestrated-feature-dev: coverage-dedup gate — don't write a test for a behavior already coveredStructural gap found on the UBET-4337 run: the pipeline turns EVERY planned behavior into its own test + commit, and no phase asks "is this already covered?". Phase 3b only adds behaviors, node-bdd-step writes one test per behavior by construction, and the quality gate reviews test QUALITY but never test REDUNDANCY.
Concrete failure: an 82-line integration test (commit f7c7488a, since dropped) that composed two facts each already proven elsewhere — settlePointsMarkets.treasury.test.ts:187 already asserted isSystemAccount === true, and `not au.is_system_account` in generate_leaderboard was pre-existing untouched code. User rejected it in review: "we already have tests for this, do not need to add new tests here for the sake of behaivor right?"
Fix = a coverage-dedup gate that runs BEFORE the test is written (the cost avoided is the test + the commit + the review round). Test: "would this test fail if I deleted it and changed nothing else?" Distinguish "already covered" from "covered only in combination" — two CHANGED components meeting for the first time IS worth a test; one changed + one unchanged already-tested thing is NOT. A no-test behavior must be explicit in IMPLEMENTATION_PROGRESS.md naming the covering test, and gets no commit.
Related: card #230 (write-time integration-first default), card #236 (review-time necessity gate). This is the write-time REDUNDANCY filter neither covers.
Target path given by the user: sports_inference/ubet-devenv/workspace/.claude/skills/orchestrated-feature-dev/ — but that is a CLI-synced consumer copy, byte-identical to AI-rules-repo/skills/claude-code/orchestrated-feature-dev/, so it will be overwritten on the next sync. Durable fix belongs in AI-rules-repo source + cursor/antigravity mirrors.P0
3 weeks ago
#260
UBET-4355 — default chain migration to belief chainJira UBET-4355 "default chain migration to belief chain" (Task, Todo, Sprint 119, 4h, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-4282 "In-App Currency Betting"). NO description and NO comments in Jira — every requirement is derived from code.
EPIC STATE at pickup: 4334 Done, 4335 Done, 4336 IN PROD, 4337 Review (PR #785 open), 4338 Review (PR #790 open, based on #785). Two NEW siblings created after 4338: UBET-4348 "Give 10 BP to new users once they register and complete category interest selection" (Todo, Quan) and UBET-4346 "in-app betting" (In Progress, Nick Mai — the FE half). So the epic is being driven toward launch.
FINDINGS (read-only, from origin/main):
1. THE FRONTEND PICKS THE DEFAULT CHAIN BY LOWEST CHAIN ID. CommonServerDataProvider.tsx:72 does `Object.keys(chainsResponse.data.chains)[0]`, and chainRoute.ts returns `Object.fromEntries(...)` keyed on the chain id as a string. JS orders integer-like object keys ascending, so the first key is the numerically smallest chain id — not insertion order, and get_tokens.sql has no order by anyway.
2. THE BELIEF POINTS CHAIN ID IS INT4 MAX. beliefPointsTestHelpers.ts: BELIEF_POINTS_CHAIN_ID = 2147483647. 2147483647 is still a valid JS array index (< 2^32-1), so it sorts ASCENDING LAST behind 56/8453 (prod) and 97/84532 (testnet). The belief chain can therefore NEVER be the FE default as the code stands, even with beliefPointsConfig.enabled on.
3. THE LOGGED-IN PATH CANNOT REACH THE POINTS CHAIN AT ALL. All four resolution sites (HomePage:100, ActivitiesSidebar:22, RecommendedMarkets, utils.server.ts getInitialChainId:62) read `isAuthenticated ? wagmiChainId : (anonymousChainId ?? wagmiChainId)`, and wagmiChainId comes from SUPPORTED_CHAINS (constants.ts:50 = bsc/base or bscTestnet/baseSepolia), which can never contain the points chain. This is FE1 in tmp/UBET-4282/ticket-breakdown.md, never ticketed — likely UBET-4346's job.
4. THERE IS NO BACKFILL OF POINTS TWINS. insert_points_market_twin.sql is called from exactly two places in createMarketService.ts (:504 creation, :603 resurrection — and UBET-4338 D35 removes the resurrection one). Nothing ever twins a market that was already open when beliefPointsConfig went on. So on the day the belief chain becomes the default, the landing feed shows only questions created after the flag flipped.
5. Re-iding the chain is not a plain UPDATE. blockchain.chain_id is the PK (upredict_backend.sql:100) with `unique (name)`, and three tables FK to it with no `on update cascade`: collateral_token.blockchain_id (:109), the homepage blacklist (:293), and a query table (:810). A re-id has to be insert-new / repoint-children / delete-old under a temporary name.
BLOCKED ON DATA: both supabase MCP servers (testnet and mainnet) fail every call with `TypeError: fetch failed`, so the live state is unverified — whether the BP chain is seeded per env, its collateral_token id, and how many open money markets lack a twin.P0
2 weeks ago
#261
UBET-4339 add Discord + Twitch social login (committed on worktree branches; Supabase config + R26 decision outstanding)Ticket UBET-4339 "Adding Tiktok & Insta login" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo). NO description and no comments in Jira. Read-only investigation, no code changed.
HOW LOGIN WORKS TODAY: FE SignInDialog -> signInSupabase -> supabase.auth.signInWithOAuth (Supabase Cloud, project qbosayukigxebyotpnel, GoTrue v2.197.0) -> /auth/callback exchanges the PKCE code -> FE posts the Supabase JWT to BE POST /auth/socialLogin -> SocialAuthService verifies against the Supabase JWKS -> findOrCreateUserBySocialId keys the app user on the Supabase `sub` UUID. Separately AlchemyAutoLogin mints an Alchemy JWT (sub = Supabase user id) to provision the embedded wallet.
BE NEEDS NO CHANGES. Every downstream identity is the Supabase `sub`, which is provider-agnostic. SocialLoginInfo.email is extracted but never read anywhere (verified by grep). Alias seeding uses user_metadata.user_name/name and already falls back to a random alias.
FE IS SMALL: widen the provider union in features/auth/actions.ts (currently the literal "twitter" | "google" | "facebook"), add a button + svg + i18n key, optionally a PostHog flag mirroring FACEBOOK_LOGIN.
TIKTOK — doable but needs a shim, not a config toggle. Not a Supabase built-in. Supabase Cloud does now support Custom OAuth2/OIDC providers (dashboard, unlimited on Pro), BUT TikTok uses `client_key` instead of `client_id` on BOTH the authorize and token endpoints, and Supabase reserves `client_id` as non-overridable. authorization_params can patch the authorize step; the token exchange is not configurable at all. So a plain custom-provider config cannot talk to TikTok — it needs a small OAuth-compliant facade we host that translates client_id -> client_key. TikTok also returns no email, so the provider needs email_optional:true, and AlchemyAutoLogin's `if (!supabaseUser?.email) return;` guard would silently deny those users an embedded wallet — that gate must move to supabaseUser?.id. No email also means Supabase cannot auto-link identities, so a user who previously signed in with Google gets a second account and a second wallet.
INSTAGRAM — not buildable as specified. Instagram Basic Display (the only personal-account login path) reached EOL 2024-12-04. Its replacement, "Instagram API with Instagram Login", works only for Business/Creator accounts, and Meta does not approve apps using Instagram purely for authentication. Nearest available substitute is Facebook Login, which is already wired and enabled behind the `facebook-login` flag.
ALSO: supabase-js must be bumped — installed @supabase/auth-js 2.87.1 has a closed Provider union with no `custom:${string}`; 2.116.0 adds it (and splits 'x' OAuth2 from the OAuth1.0a 'twitter' we currently use).
TESTNET USAGE for context: google 153 identities, twitter 33, facebook 1.P0
last week
#268
Visual QA run on LMSFirst real application of the visual-qa skill to the LMS project: wire up playwright.visual.config.ts + snap.ts + visual-qa.json, rank states by harm, write tour files reusing the existing e2e auth/seed setup, capture, review with subagents, and write qa-visual-defects/ into the repo.P0
2 weeks ago
#280
Strategy breadth program: shared harness, regime/correlation report card, market-neutral screensChange the research question from "predict one coin's next move" (answered no, cards #258/#269) to strategies that need breadth and are market-neutral — where a systematic operator beats a manual one. Plan: docs/research/2026-09-strategy-breadth/ (00-overview, 01-harness-todo, 02-strategy-todo). Prototype report card: scripts/research/report_card.py.
Operator constraints (2026-09-26): $10k capital to start; drawdown tolerance up to 80% (ceiling for leverage sizing, not a target); HIBT venue — perp taker 5 / maker 3 bps, spot on the same venue, no testnet; minimum orders ~$300-$670 on majors, 81/82 perps <= $1,000; a 20-leg book at 2x = $1,000/leg fits.P0
last week
#281
Check the VN value-DCA strategy and design a VN + US backtest (ai-price-action)Review the fundamental buy-and-hold DCA rules in ai-price-action (STRATEGY_YEARLY/MONTHLY) using numbers only (no news layer), and propose a mechanical backtest for VN stocks and US stocks with reliable data.P0
last week
#283
claude-usage: cost tool undercounts (subagent tail read, Opus 5.5 / Fable 5.1 unpriced, stale Sonnet 5 rise)Found during the LMS visual-QA cost breakdown (card #219). Official prices from platform.claude.com/docs/en/about-claude/pricing (fetched 2026-09-27).
- subagentCostSince tail-reads only the last 256 KB of each subagent transcript; the report asks for the whole session (since 1970), so earlier subagent turns are dropped.
- claude-opus-5-5 ($4/$20, cache read 0.05x) and claude-fable-5-1 ($10/$50, cache read 0.025x) are missing from PRICES and CONTEXT_WINDOWS → $0 and 0% context.
- Sonnet 5's scheduled 2026-09-01 rise to $3/$15 was cancelled; $2/$10 is standard. The table still applies the rise.
- CACHE_READ (0.1x) is global; it must become per-model (carry cost in status.mjs/session.mjs, turnCarrySplit, cacheSavings).P0
last week
#288
LMS: real-Gemini e2e for AI question import + keep highlighted answer keys from .docxIn /Users/quanvo/Documents/git-repos/personal/lms. Opt-in `pnpm test:e2e:real-ai` Playwright run that uploads a real teacher exam (.docx, Sinh 10 HK1 — gitignored at e2e/fixtures/private/, repo is PUBLIC) through "Import Questions with AI" against the REAL Gemini key (from gitignored .env.e2e-real.local; Vercel pull returns it empty — user must paste it). Checks: known questions present in Vietnamese, spare ("Sơ cua") questions included, known correct answers ticked. Bug found: browser extraction (mammoth.extractRawText) drops the yellow highlight the teacher uses to mark correct answers, so every MC imports with no answer key → fix extraction to keep a highlight marker + tell the prompt. Cost rule: one paid Gemini call per run, save raw output each run, diagnose + change before any rerun.P0
last week
#303
LMS: multi-tenant support (orchestrated-feature-dev)Orchestrated-feature-dev run in /Users/quanvo/Documents/git-repos/personal/lms-multi-tenant (worktree, branch feat/multi-tenant from main c8de024). Workspace: lms-multi-tenant/tmp/multi-tenant/. REQUIREMENT (user, verbatim): "add multi ternant feature for lms project". User pre-approved every gate: no questions, agent decides autonomously and reports at the end.P0
5 days ago
#324
VN30 index futures (phái sinh): pluggable backtest + paper-trading module with UIOperator request 2026-09-30: build a backtest AND paper-trading module for Vietnamese index futures (VN30F, HNX). Hard constraints: modular/pluggable (plug in and out, never baked into the engine), and visualized on the dashboard UI. Diverged from card #198 (paper engine, now stopped per D214).P0
quant-trading·main4 days ago
#326
UBET-4352 — Weekly leaderboards ignore betting on BP marketsOrchestrated-feature-dev run for Jira UBET-4352 "weekly leaderboard point system update" (Task, Todo, Sprint 119, 4h, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-4061 "weekly leaderboard"). On a BP market: betting action = no points anywhere (all-time, top-right, weekly); betting payouts + rewards = excluded from all three weekly leaderboards but still counted in the user's top-right points. Slack: C03062ZGP3M p1790744386567919. Overlaps UBET-4353 (card #286, need_review). Workspace: workspace/tmp/UBET-4352.P0
4 days ago
#331
October 2026 monthly DCA run (ai-price-action)Month-start buy plan for October 2026 across stocks, funds, gold and crypto per STRATEGY_MONTHLY + monthly-dca-research skill. Output CANDIDATES_2026-10.md; flag-for-review, the owner trades. Step 0 read 2026-09-30: VNINDEX 1,768.62 vs SMA200 1,795.72 (-1.51%, inside hysteresis → 1×); BTC +12.5% over EMA200 → 1×.P0
4 days ago
#337
RISE-15850 — Bulk ASM request: fix message for Executor Org invalid per standard settingOrchestrated-feature-dev run for RISE-15850 (Bug, BACKLOG, labels SM_Epic_Issues / SM_Relationship_Org_Type_Org_Status). "[SM-Request Bulk ASM-Executor] Need to change the message displayed when selecting Executor Organization but it's not valid as standard setting." Workspace tmp/RISE-15850/.P0
3 days ago
Blocked
0Need Review
96#97
Plan + build Data Structures & Strings lessons (Python + C++)Two parallel bilingual lesson pages on collections & text. Python (programming-python/data-structures-strings): recap lists → tuples, dicts, strings (core+methods+f-strings). C++ (new programming-cpp/data-structures-strings): self-contained arrays+std::vector → pair/tuple, std::map, std::string, modern C++11+. Both: teaching + exercises + challenge. Two-phase: manifests first → approval → page.tsx.P0
2 months ago
#134
Audit Notion Notification Wiki against implementationCompare the Notion "Notification Wiki" page (366ff947974d8026b761c443ef8fc03f, a verbatim copy of workspace/NOTIFICATIONS_INVENTORY.md from 2026-05-21) against the real notification implementation in upredict-backend and upredict-frontend at origin/main, then write replacement wiki markdown locally. Explicitly NOT writing back to Notion.P0
2 months ago
#140
UBET-4057 refine streak & mystery box notifications (claim-time, not post-claim)Act on Daniel Im's Slack feedback on the Notification Wiki: notify when something is CLAIMABLE, not after it was claimed. "Claim Your Mystery Box" (not "Mystery Box Opened"), "Claim your 7D Streak" (not "Streak Claimed"). Plus: remove the point-change feed category (wiki section 1a — "it's a log, not a notification"), and make every push have a matching feed row that deep-links to the right destination. Worktrees upredict-backend-ubet-4057 / upredict-frontend-ubet-4057, branch feat/UBET-4057-refine-streak-mystery-notification off main.P0
2 months ago
#147
CCP environments: async build handoff — POST creates model + zipball only, add PUT for buildStatus/buildNotesVia orchestrated-feature-dev. Workspace: ccp-environments-async-build/tmp/environments-async-build/. Branch feat/environments-async-build off origin/main (worktree ccp-environments-async-build/).
PROBLEM: POST /environments currently validates, creates the Environment model, clones the repo, audits the Dockerfile, AND builds the Docker image — all inside one web request. This does not work; the build must be out-of-band.
TARGET WORKFLOW: user submits details -> CCP retrieves a shallow (HEAD-only) zipball of the chosen repo and stores it (currently a temp dir; should probably live in the data model) -> on its tick cycle a compute node finds a build request -> icp-shell-client pulls the zip, unzips, builds the container, and reports progress back through the ICP environments proxy to CCP.
THIS TASK (CCP only):
1. POST /environments: validate inputs, retrieve zipball, create initial Environment model. Remove clone/audit/build from the request path.
2. Add validation: GitHub URLs must be HTTP(S) — SSH URLs unsupported.
3. Add PUT handler accepting buildStatus and buildNotes from the build process.
4. Update tests as needed.
REFERENCE WORKTREES (read-only):
- ccp PR #113 "Added zipRepo functionality" — MERGED, already in origin/main (utils/zipRepo.js)
- icp-pr-37/ — ICP PR #37 "implemented environments proxy middleware" (middleware/environments.js)
- icp-shell-client-pr-25/ — shell-client PR #25 "initial docker image build implementation" (modules/docker.py)
Test command: npm run will_test (needs local Mongo :27017 + `docker compose up -d gcs-emulator`).P0
2 months ago
#151
Quant: add Vietnam stocks (SSI FastConnect + VN30F1M) as a second marketUser (Vietnam resident) wants to extend quant-trading beyond crypto to Vietnamese equities, asking specifically about SSI's APIs.
USER DECISIONS (2026-08-06, via AskUserQuestion):
1. GOAL = "Research now, trade later" — build the research layer but pick vendors assuming eventual execution.
2. INSTRUMENT = BOTH cash equities (cross-section) and VN30F1M futures.
3. ACCESS = has an SSI trading account (FastConnect key not yet confirmed); explicitly wants other vendor options kept open (vnstock/DNSE/TCBS), not an SSI lock-in.
RESEARCH DONE THIS SESSION (needs writing up):
- SSI FastConnect Data endpoints confirmed (DailyOhlc, IntradayOhlc 1-min, DailyStockPrice w/ ceiling/floor + foreign flow, Securities, IndexComponents, DailyIndex; pageSize max 1000; markets HOSE/HNX/UPCOM/DER/BOND). Auth = consumerID/secret -> AccessToken; RSA+SHA256 for trading. Requires SSI account + FIXED IP registration + 1-yr renewable term. Rate limits enforced but UNPUBLISHED. History depth UNDOCUMENTED — the #1 open question.
- Free alternative: vnstock (VCI/TCBS/DNSE). DNSE caps minute data at 90 days, daily 10y. Legacy Vnstock class EOL 2026-08-31.
- VN mechanics that break the engine: T+2 settlement hold-lock; no short selling in cash equities (SSC roadmap 2026-2028); ~60bps round trip (SSI iBoard 0.25%/side + 0.1% PIT on SELL proceeds regardless of P&L) vs crypto's 24bps; price bands +-7% HOSE / +-10% HNX / +-15% UPCoM; lot size 100; sessions 9:00-11:30 + 13:00-14:45 w/ ATO/ATC auctions; ~250 trading days/yr vs BARS_PER_YEAR["1d"]=365 (Sharpe inflated 1.21x).
- VN30F1M: T+0, shortable, multiplier 100,000 VND/index point, IM 17% (VSDC), fees ~2,700 HNX + 2,550 VSD + 1,000-3,000 broker per contract, PIT = 0.1% x price x multiplier x qty x IM (~1.7bps effective). Circular 87 (eff. 2026-07-01) is the current derivative-tax rule.
- TIMING FLAG: FTSE Russell upgrade Frontier -> Secondary Emerging effective 2026-09-21 — an index-inclusion flow event and regime break; must be embargoed in any backtest.
STRATEGIC POSITION (from the repo's own track record): every single-asset directional arm has FAILED honestly (ML v0-v3, cross-section on 9 coins, funding-carry gate, pooled-panel). Only always-on carry ever beat B&H. So do NOT re-run single-asset direction on VN. The argued case for the port is CROSS-SECTIONAL BREADTH: ~400 liquid HOSE names vs 9 coins directly attacks the "~83-sample starvation" diagnosis, plus foreign-flow is a VN-specific factor with no crypto analogue.
Engine transfers mostly unchanged (loop is index-based, assert_no_gaps is crypto-ingestion-only, every verdict runner already takes a bpy= override). What breaks: cost model is symmetric with no sell-tax, no settlement lock, no long-only constraint, no lot rounding, no ceiling/floor fill gate, BARS_PER_YEAR is 24/7.P0
quant-trading·main2 months ago
#162
Code review: upredict-backend PR #732 — UBET-4234 market_recommend Lambda timeout fixReview https://github.com/SportsFI-UBet/upredict-backend/pull/732 ([UBET-4234] Fix market_recommend Lambda timing out on every run, quangtran-sportsinference, ubet-4234-fix-market-recommend-timeout -> main, 2 files +108/-109). Checked out in worktree workspace/upredict-backend-pr-732 (branch pr-732, head 2ab080aa). Changes: de-correlate get_market_features.sql (LEFT JOIN LATERAL per user x market_spec -> group-by aggregates joined in), plus a new index idx_market_user_view_count_user_id_updated_at in upredict_index_view_function.sql. Deliverable: /review-changes findings AND a from-zero-knowledge explanation of the fix for the user.P0
upredict-backend·pr-7322 months ago
#163
VN cross-section verdict: fix --help crash + execute pre-registered real runTask 1: fix argparse %-formatting crash in scripts/run_vn_cross_section_verdict.py --help (test-first). Task 2: execute the SEALED pre-registered real Vietnam cross-section verdict run (n_trials=5, brokerage=30bps, frozen geometry train=500/test=120/embargo=5) against real data/vn + data/vn_index, report the verdict verbatim without editing docs/research/vietnam-market/05-pre-registration.md.P0
2 months ago
#164
Mirror testnet reaction-enum migration into production for release 20260807.1 (upredict-infra #701)Production release PR https://github.com/SportsFI-UBet/upredict-infra/pull/701 upgrades production 20260805.2 -> 20260807.1. Today it ONLY bumps ci/configs/production/pipeline-config.json.
Release contents (upredict-backend): #730 [UBET-4246] weekly ranking counts only markets created this week; #728 [UBET-4243] Subscribed notifications tab API.
FINDING: production is missing Terraform/production/postgres/migrations/20260805000000_add_reaction_market_interaction_type.sql (present on testnet). It adds 'Reaction' to upredict_backend.market_interaction_type_enum and seeds notification_watermark for source_type 'MarketInteractionReaction'.
Why it is required at 20260807.1 (not at 20260805.2, so prod is not broken today):
- marketInteractionsWorker.ts inserts market_interaction_log rows with interactionType 'Reaction'; the column is market_interaction_type_enum, so the insert errors without the value. All of comment/reply/mention/vote notification inserts + push notifications run in ONE queryWithTransactionHandled, so the whole notification pipeline rolls back every tick.
- appSql get_unified_notification_feed / get_unified_notification_unread_count / get_subscribed_notifications / update_market_interaction_log_read_subscribed all compare interaction_type against 'Reaction' -> invalid input value for enum, so the notification feed + unread count + the new Subscribed tab endpoint all 500.
- The watermark seed matters too: without the row the worker starts at cursor 0 and would replay every historical comment_reaction.
Why CI does not catch it: apply_sql.sh only wholesale-applies upredict_metric_views.sql, upredict_index_view_function.sql and config.sql. sql_schemas/upredict_backend.sql (which declares the enum) is never applied, and PostgresMigrationCheck/pgdiff is informational and does not diff enum labels. All 15 checks on PR 701 pass.
NOT needed for this release: 20260806000000_add_follow_notification_log.sql and the followNotificationCooldownDays config key are only referenced at tag 20260807.2, which this PR does not deploy.
Also verified in sync / no action: Terraform testnet vs production is structurally identical (last shared change 589a38a); config.ts unchanged across the release range so no new required config keys; production already has the point-ledger source types, user_follow, point_ledger.meta and user_alias migrations; frontend has not consumed the Subscribed notifications API yet.
Precedent: PR #700 shipped the same shape (migration .sql + atlas.sum + config in the deploy PR). Sibling card #157.P0
2 months ago
#166
claude-usage: repo drill-down is dead for claude-usage and quant-trading (label maps disagree)Reported 2026-08-10 with a screenshot: https://claude-usage.quanvo.dev/split/repo/personal%2Fquant-trading?preset=90d renders "No data in this range" even though quant-trading obviously has spend.
# Measured on production (HTTP probes with the session cookie)
Repo tab, single day 2026-08-08:
- row `personal/quant-trading` = $136.00 / 1853 events
- row `personal/claude-usage` = $124.54 / 1728 events
- row `(unattributed)` = $9.22 / 111 events
Drill-downs for the same day:
- `/split/repo/personal%2Fclaude-usage` -> EMPTY
- `/split/repo/personal%2Fquant-trading` -> EMPTY
- `/split/repo/git-repos%2Fpersonal` -> $128.67 / 1783 events (a label the repo tab NEVER offers)
- `/split/repo/(unattributed)` -> $3.09 / 45 events (its own row says $9.22 / 111)
Per-day sweep: only 2026-08-02 and 2026-08-08 are broken; every window containing either of those days is broken, which is why 7d/30d/90d/all all fail and `today` works. Only claude-usage and quant-trading are affected — every other repo on those days drills down fine.
# Root cause
Two different code paths compute the repo label from two different row sets, and they disagree.
- `costPerDay` (src/server/usage-queries.ts) groups by (day, projectSlug) and carries `repoKey: { $first: "$repoKey" }`. One slug can legitimately carry SEVERAL repoKeys (or a mix of present/absent) since per-turn attribution, so `$first` silently drops the rest — and it is unordered, so which one survives is arbitrary.
- `repoKeyForLabel` (same file) groups over EVERY (projectSlug, repoKey) pair where repoKey exists.
Both then apply `repoLabelsAcrossRange` (shortest projectSlug wins). Because the second sees strictly more pairs, it can pick a SHORTER label. Here the slug `git-repos/personal` (19 chars) beats `personal/claude-usage` (21) and `personal/quant-trading` (22), so the drill-down's map names both repos `git-repos/personal` while the dashboard still renders `personal/claude-usage` -> the label lookup finds nothing -> MATCHES_NOTHING -> "No data in this range".
The `git-repos/personal` + repoKey pairing comes from `bin/sync.mjs:105-115`: the fallback attribution takes `projectSlug` from the project directory's own recorded cwd but `repoKey` from `resolveRepoKey(projectDir)`, so a turn with no evidence gets a parent-folder slug glued to a real repo's key.
# Three defects, one cause
1. Dead link — the dashboard renders a drill-down link that resolves to nothing.
2. Under-counted repo rows — claude-usage's row is missing $4.13 / 55 events on 08-08; they fall into `(unattributed)` instead.
3. `(unattributed)` row ($9.22/111) disagrees with its own drill-down ($3.09/45) for the same reason.
Latent: `$first` without a `$sort` is arbitrary, so repo labels can flip between runs.
# Open decisions (blocking)
- Naming rule when one repo has several folder names. Today "shortest wins" (D20), which lets a generic parent folder hijack a repo's name AND collide two repos onto one label.
- Whether the sync CLI's fallback pairing is fixed too (stops new bad data; old rows only correct on a re-sync, since both fields are `$set`).P0
2 months ago
#167
Fix get_markets_by_creator statement timeout (restrict the view scan)Prod: /users/{id}/marketsByCreator 500s with 57014 statement timeout for mega-creators (e.g. user 11849: 1444 specs / 21277 market×lang rows / 3046 markets). EXPLAIN ANALYZE (warm) = 2.2s but touches ~1.38M buffer pages (~11GB logical) — buffer-bound, so it tips over the 120s ceiling under refresh/market_recommend cache contention. ~65% of buffers = the 3 correlated scalar subqueries (totalParticipants/totalVolume/creatorFees) each re-scanning the expensive market_description_view per row (SubPlan4/totalVolume alone = 585k buffers); ~32% = latest_market_rounds nested loop over-producing 556k rows then deduping to 3046. Fix: de-correlate the 3 subqueries into one creator-scoped CTE grouped by (marketSpecId, collateralId, languageTag, marketStatus), LEFT JOIN. Worktree upredict-backend-markets-by-creator-perf, branch fix/markets-by-creator-timeout off main (580b479e). File: typescript/services/belief_locker/src/appSql/get_markets_by_creator.sql. Tests: routes/tests/marketsByCreator.test.ts (+ publicMarketsByCreator.test.ts, shares the query).P0
2 months ago
#169
claude-usage: a container folder inside a repo steals its sub-repos' spend (ubet-devenv 40%)Operator report 2026-08-10 (screenshot, Repo tab, last 30 days): `sports_inference/ubet-devenv` is the #1 repository at $1971.32 / 12799 events. The operator does not work on devenv — it is a workspace container; the real work is in upredict-backend / -frontend / -infra and their ticket worktrees.
# Layout
`ubet-devenv` IS a git repo (SportsFI-UBet/ubet-devenv). Its .gitignore contains `workspace/*`. Inside `ubet-devenv/workspace/` live upredict-backend, upredict-frontend, upredict-infra plus ~45 ticket worktrees, each its own repo. All 63 UBet transcripts run with cwd = `.../ubet-devenv/workspace`.
# Root cause
Three pieces collide:
1. `resolveRepoAt` runs `git rev-parse --show-toplevel`, which walks up to the nearest .git and does NOT consult .gitignore. `workspace/` has no .git, so git answers `ubet-devenv` — correctly, for the question asked.
2. `attributeTurns` gives cwd precedence over files ("a turn run inside one repository while READING a file from another is working on the first").
3. That precedence assumes a container folder resolves to NOTHING, letting the files decide. True for `~/Documents/git-repos/personal` (not a repo). False for `ubet-devenv/workspace`, which is inside one.
Measured with the real parser over the real transcripts: 5,305 of 13,293 turns (39.9%) attribute to devenv. 5,014 turns record `.../workspace` as their literal cwd.
Files cannot rescue it: of those 5,305 turns, 94.1% touched NO resolvable file (they ran a command or just replied). Only 4.2% would move on file evidence.
# Rules measured (13,301 turns, devenv share)
- current: 39.9%
- A, cwd is gitignored by its repo: 2.1% — but depends on the operator having happened to gitignore the container; REJECTED by operator as too narrow (the personal dir has no .gitignore).
- B, cwd directly holds nested repos: 16.4% — REJECTED, actively harmful. It discards a GOOD cwd on 3,297 turns in upredict-backend alone, because `upredict-backend/contracts` is itself a repo. Cannot distinguish "container of repos" from "repo that vendors a sub-repo". B+C (13.3%) scores worse than C alone.
- C, ancestor never overrides: 4.7% — CHOSEN.
# Chosen rule
A repository that strictly contains another candidate never overrides it. If the cwd resolves to a repo whose root is a path-prefix of either (a) the repo the session is already in, or (b) the repo this turn's files point at, the cwd answer is discarded as less specific.
Cheap (string prefix compare on two already-resolved paths), no filesystem scan, no .gitignore dependency, and it cannot discard evidence unless a MORE specific answer exists.
Residual 4.7% is mostly session-start turns before a sub-repo is established, plus genuine devenv work. Left alone deliberately.
# Scope
Parser fix + spec + a full `bin/backfill.mjs` re-run to repair stored history (fields are last-writer-wins). The backfill does NOT need a deploy — it runs locally and re-uploads corrected attribution. Past days' figures will visibly move, and every project is re-tagged, not just UBet.P0
2 months ago
#170
claude-usage: mobile UX/UI — dashboard is unusable on a phoneOperator report 2026-08-10 with an iPhone screenshot of https://claude-usage.quanvo.dev: "the ui on mobile is bad, follow orchestrated feature dev to make a good mobile ux ui for this app. should check what is industry standard for components like what we have".
Visible in the screenshot alone:
- The whole page scrolls horizontally — content is wider than the viewport, so cards are cut off on the right.
- The Machine sync card renders a full 64-char machine hash on one line, blowing out the page width by itself.
- The Cost-per-day chart tooltip is wider than the screen and clips; its legend and the totals table below repeat the same untruncated hash.
- The dimension tabs (Machine / Project / Model / Repo) and the range picker sit on one row and are near the edge.
- Chart x-axis labels (full ISO dates) collide at phone width.
Scope: every dashboard surface — KPI cards, machine sync, range picker, cost-split (chart + tabs + totals table), efficiency charts, session list/table, and the /split drill-down — plus the login page.
Run via orchestrated-feature-dev. Workspace claude-usage/tmp/mobile-responsive-ui/.P0
claude-usage·main2 months ago
#172
UBET-4216 follow-up: return read counts (not just unread) for grouped vote/comment market notificationsFollow-up to UBET-4216 (IN PROD), which made read market groups appear in the notification feed. Those groups' vote/comment counts currently only reflect UNREAD interactions, so a fully-read market shows zeros. Add read counts alongside the unread counts for the market-creator group vote + comment notifications.
Repo: upredict-backend, worktree workspace/upredict-backend-ubet-4216-read-counts, branch feat/UBET-4216-read-counts (off origin/main @ 580b479e).
Method: orchestrated-feature-dev. Workspace: workspace/tmp/ubet-4216-read-counts/. Prior run of UBET-4216 itself lives in workspace/tmp/UBET-4216/ (recall context, do not overwrite).P0
2 months ago
#173
Cut post-compact context cost: session pointer rewrite in pre-compact-flush + stop double-reading decisionsMeasured two real sessions. Post-compact re-orientation cost ~16,200t in ubet-devenv session d7543d8a: list_cards 1,300 + adopt_card 5,847 + get_card_context 9,078.
Root causes found:
1. The session pointer (~/.claude/kanban-session-state/$SESSION.json) was absent after compact, so the agent fell through to a board search + adopt instead of the documented pointer short-circuit. pre-compact-flush never writes the pointer — its Flow is locate ws -> scan -> append -> mirror -> card state note -> report.
2. Decisions are deliberately mirrored to BOTH <ws>/DECISIONS.md and the card; a resume can read both in full.
Scope of THIS card (skill-text only, no code):
- F1: pre-compact-flush verifies/rewrites the session pointer as its last flow step.
- F2: resume path reads decisions from ONE home, not both.
Out of scope (separate card, AI-Kanban repo): the write-echo fix in toCardResult and a lean `resume` view for get_card_context.P0
2 months ago
#174
AI-Kanban: stop echoing the whole card on writes, add a lean resume view, cap entry lengthServer-side half of the post-compact context work (skill-text half was card #173). Three changes to the dispatch MCP layer, all in src/mcp/.
Measured evidence from two real sessions:
- Kanban tool results were 31.6% (claude-usage 33a644a2) and 43.1% (ubet-devenv d7543d8a) of ALL tool output — above Read and Agent in the second.
- src/mcp/tools.ts toCardResult returns the ENTIRE card (full description + all decisions[] + all progress[]) from every write tool. Consecutive append_decision results on one card grew 597 -> 791 -> 965 -> 1332 -> 1625 -> 2934 -> 4905 -> 5314 -> 5847 tokens. The 9th decision cost 5,847t to record.
- get_card_context on card #140 = 9,078t (12 decisions 4,479t + 8 progress 4,286t). Card #141 carried MORE decisions (15) in 2,907t — same schema, 3.5x better entry discipline.
S1 - Writes acknowledge instead of echo. New toCardAckResult returning {id, number, status, decisions: count, progress: count}. Applies to append_decision, append_progress, update_card, set_status, claim_card, adopt_card, create_card, mark_decision_outdated. get_card_context keeps the full card.
S2 - Lean resume view. get_card_context gains a view param defaulting to "resume": header + nextAction + ACTIVE decision headlines (no why) + latest progress note only + counts. Trims superseded decisions, all why prose, older progress notes, description, and the metadata tail. Estimated 9,078t -> ~2,400t on #140, 2,907t -> ~900t on #141. Add a detail fetch so an omitted why is one call away.
S3 - Length validation on append_decision: decision <= ~200 chars, why <= ~400, ERR_VALIDATION reporting the actual length so the agent rewrites shorter rather than truncating silently. Pairs with the template added to pre-compact-flush in #173.
Ordering: S1 and S3 are independent; S2 depends on nothing but touches the same file. Existing tests: src/mcp/dispatch-tools.test.ts, src/mcp/dispatch-server.test.ts, app/api/mcp/route.test.ts. CI = lint + tsc --noEmit + tests.P0
2 months ago
#175
Card gate: revisit test + repo-scoped reuse-first lookup in ai-kanban-track-sessionStop the board over-creating cards in the ai-kanban-track-session skill. Two failures: (1) cards for work nobody revisits — #129 migration mirror, #130 and #148 code reviews, #150 one chart bug — because the gate is "substantive and multi-step", which is true of nearly everything an agent does; (2) one request fanned into several cards — #158/#159/#160 — because the only pre-create check is a keyword search for the SAME task, so nothing looks for neighbouring open work on the same repo. Design is two questions in order: WHETHER a card exists = "would you want to revisit this in a week?" (a card is a handoff device, default off); WHERE the work goes = list open cards carrying this repo's tag, reuse by default, split only when genuinely separate. Measured constraint: repo identity must come from git, NOT .ai-rules.json — claude-usage and quant-trading have no such file, and AI-rules-repo and personal-infra carry scope "personal" only, which identifies no repo. No AI-Kanban server changes needed since repo identity rides on tags. User constraint: NO enumerated skip list, the gate is a principle plus rationale. Plan in tmp/kanban-card-gate/PLAN.md, 8 steps; only step 5 (hook wording + tests/hooks/kanban-track.test.ts) has automated coverage. Split from #113 (need_review), which built the current search rung, forceNew narrowing and hook reminder for a different failure mode (cross-session duplicates of the same task).P0
2 months ago
#176
FE guard: drop notification rows with an unrenderable MarketInteraction typePostHog issue 019f6aff-7918-7de2-9b3e-33a3e9105574 "Unknown MarketInteraction type". BE #728 (UBET-4243, 2026-08-07) started emitting interactionType "Reaction"; the shipped FE build had configs only for Comment/Vote/Reply/Mention, so MarketInteractionPageRow/MarketInteractionBellItem hit the !config branch, fired captureException on every render and rendered null.
FE #685 (UBET-4166, merged 2026-08-12, main eb2342a) already added the Reaction enum member + config, so the specific row now renders. This card handles the GENERAL case the user asked for: no unrenderable interactionType should ever reach a renderer again.
Two seams carry MarketInteraction rows and neither guards interactionType:
- useUnifiedNotifications (All tab) -> filterRenderableNotifications guards only the OUTER NotificationFeedItemType (added by #701 / UBET-4057), not the inner interactionType.
- useSubscribedNotifications (Subscribed tab) -> no filter at all, and every row there is a MarketInteraction (Reply/Mention/Reaction) - the highest-risk surface.
Decision: guard only, do not add new rendering/copy (user's call). Scope: shared predicate in utils.ts used by both seams, plus the rawCount pagination pattern for the subscribed hook so a fully-filtered page does not end pagination early.
Worktree: workspace/upredict-frontend-notif-guard, branch fix/notification-unknown-interaction-type, based on origin/main eb2342a.P0
upredict-frontend·fix/notification-unknown-interaction-type2 months ago
#177
claude-usage: name a repo after its main checkout, resolved from git (worktree labels)Operator report 2026-08-12 (screenshot, Repo tab, last 7 days): the top row is `workspace/upredict-backend-ubet-4179` ($897.44) and another is `concrete_engine/ccp-environments-async-build` ($81.44) — both ticket-branch worktrees, named as if they were the repository.
# Diagnosis (verified this session, read-only)
The GROUPING is already correct. All 44 `upredict-backend-*` dirs under `sports_inference/ubet-devenv/workspace/` are real `git worktree` checkouts sharing one origin (`SportsFI-UBet/upredict-backend`), as is `ccp-environments-async-build` off `ConcreteEngine/ccp`. Same remote → same `repoKey` → `mergeRepoRows` already folds them into ONE row. That $897.44 is already the whole repository.
What is wrong is the LABEL. `repoLabelsAcrossRange` (usage-queries.ts) names a repoKey group after the projectSlug with the MOST EVENTS in the window (card #166 D1), ties broken by shortest. A ticket worktree the operator lives in out-votes the main checkout and takes the repository's name.
# Rejected: hard-coded name/prefix rules (the operator's opening ask)
`workspace/upredict-backend-worktrees` sits in the same folder, shares the `upredict-backend-` prefix, and is a DIFFERENT repository (`SportsFI-UBet/ubet-devenv`). A prefix rule would swallow it. This is the exact false positive D20 rejected name-matching for, present in the real corpus.
# Chosen approach — ask git for the canonical name
`git rev-parse --git-common-dir` from a worktree returns the MAIN checkout's `.git` (verified: resolves to `…/workspace/upredict-backend/.git` and `…/concrete_engine/ccp/.git`); a main checkout answers the relative `.git`. Resolve the main checkout root at sync time, store its two-segment slug as a new `repoName` field alongside `repoKey`, and have the label prefer it. No name heuristics, no list to maintain, works for every repo on every machine.
Write path touched: `src/parser/repo.mjs` → `attribution.mjs` → `events.mjs` → `api/sync/route.ts` allowlist → `usage-store.ts`; read path: `usage-queries.ts` label ranking.
# Known open items
- Backfill re-run vs forward-only (D4 precedent on card #166: full `bin/backfill.mjs`, 2,532 files / 75,572 events).
- Bare-repo-plus-worktrees layout has no main checkout to name.
- Three stale comments + one stale test title still claim the label is the SHORTEST slug (usage-queries.ts:963/1184/1267, usage-queries.test.ts:155) — card #166 changed it to most-events and left these behind.
Follows card #166 (label rule) and #169 (container-folder attribution).P0
claude-usage·main2 months ago
#178
UBET-3872 BE: block a user from posting a duplicate comment within a marketTicket UBET-3872 (epic UBET-3691 "BM - Our Own Comments"), assignee Quan Vo, status Todo: "Duplicate comment not allowed by the same user within a market" — the write-path sibling of UBET-4179 (card #154), which merges duplicates on the read path. Backend (upredict-backend / belief_locker). Worktree workspace/upredict-backend-ubet-3872, branch feat/UBET-3872-no-duplicate-comment, based on feat/UBET-4179-tree-only (27253efd, itself off origin/main 26ca45f9) — so UBET-4179's comment_merge_key() normalization already exists on this base. Running orchestrated-feature-dev. Jira description carries a screenshot that could not be read via MCP; needs the user to describe it.P0
upredict-backend·feat/UBET-3872-no-duplicate-comment2 months ago
#180
Fix orchestrated-feature-dev plan-format drift (stale rule + stale skill + competing templates)Diagnosis: since 2026-07-12 the orchestrated-feature-dev Phase-2 plan node stopped producing the create-implementation-plan format (## Technical Design + ## Behaviors to Implement + test checkboxes) and instead emits an AC/Test-Type/Depends-on format. Measured across 49 tmp/*/implementation-plan.md files: 100% compliant before 2026-07-12, progressively non-compliant after.
Four causes:
1. .claude/rules/feature-development-guide.md was DELETED from ai-rules source on 2026-07-08 (commit 9b94992) but installed copies were never pruned — 15 copies still on disk, incl. the workspace root, so it is auto-loaded as project instructions into every session AND every sub-agent. It prescribes the exact deviating format and its "What NOT to include" list forbids the skill's Technical Design section.
2. feature-development-workflow was renamed to feature-dev-lite on 2026-07-12 (commit 4997720); 11 stale skill dirs remain installed, carrying the same competing template. Rename date == drift start date.
3. feature-dev-lite/SKILL.md itself restates the competing AC/Test-Type template (a genuine design collision, not staleness).
4. node-plan.md says "Use @create-implementation-plan" (prose, not an invocation) and never overrides that skill's Step 0 "ask the user for an identifier" + Step 1 "MUST stop and wait for the user" — un-followable for a sub-agent.
User decision: do NOT add prune-on-sync to the CLI (prune risks deleting skills they still want).P0
2 months ago
#182
Add commit-strategy gate to orchestrated-feature-dev + feature-dev-lite (one commit per behavior)Before implementation begins, both skills must ask the operator how to commit: (A) one commit per behavior, made right after that behavior goes green, or (B) defer everything and let the operator commit at the end. Under (A), any later fix — quality gate, conformance validation, adversarial triage — must be FOLDED into the commit that owns that behavior (fixup + autosquash), so the branch ends with exactly as many commits as there are behaviors in the plan.
Design notes: git must be serialized (parallel BDD batches would race, and batches deliberately share files so a shared diff cannot be split by path); verification sub-agents report only and never touch git; commits are re-resolved by subject rather than SHA because every autosquash rebase rewrites SHAs; an already-pushed owning commit is an escalation (force-with-lease vs. accept a count mismatch), never a silent rewrite.P0
2 months ago
#183
RISE-15477 — Workflow Setting default executor: show executor org-restriction guidelineOrchestrated-feature-dev run for RISE-15477 (epic RISE-15475). Frontend-facing: on the Workflow Settings > "Assessment Type" card (both view and edit mode), show guidance when the standard's assessment settings restrict which organizations may be the Executor.
Text: "Only organizations matching the filters (status or organization type) can be set as executor. View details" + bullets "Organization Status: {values}" / "Organization Type: {values}" — each bullet hidden when that filter is unconfigured; the whole block hidden when neither is configured. "View details" opens the assessment settings in a new tab.
Builds on RISE-15476 (card #168, In Code Review) which added the executor org status/type restriction fields. Branch feature/RISE-15477/default-executor-restriction-guideline in worktree /Users/quan.vo/Documents/git-repos/inspectorio/rs-frontend-RISE-15477, based on feature/RISE-15476/assessment-stakeholder-restrictions. Workspace tmp/RISE-15477/ inside that worktree.
Jira: https://inspectorio.atlassian.net/browse/RISE-15477P0
2 months ago
#184
Reorganize notification documentation (Notion + repo)Audit + reorganize all notification docs. Found 9 Notion pages (Notification Wiki, All notification API contract, Subscribed tab API, Grouped Market Notifications, Follow Notifications API, Point Change Log API Contract, Leaderboard Push Proposal, ADR-001/002/003) and 3 local files (NOTIFICATIONS_INVENTORY.md, NOTIFICATION_WIKI_GAP_ANALYSIS.md, NOTIFICATION_WIKI_NEW.md). Core problem: docs are organized per-ticket, not per-surface, and the durable "wiki" page is 3 months stale — it documents the PointChange feed subsystem that UBET-4057 (86a285ef, 2026-08-12) deleted. Supersedes card #134.P0
2 months ago
#185
UBET-4184 BE: return the requesting user's own reply on top of commentsTicket UBET-4184 (parent UBET-4146 "Reply to comment"), title "return user's reply on top of comments", NO description in Jira — requirements must be clarified. Blocks UBET-4260 "return reply in oldest first order in...". Backend work in upredict-backend, belief_locker service; comment ordering lives in src/appSql/get_market_comment_tree_{roots,replies,preview}_{newest,relevant}.sql and get_comment_replies_{newest,relevant}.sql. Related prior work: UBET-4156 (sort=newest|relevant), UBET-4179 (merge duplicate comments, merged to main as #738), UBET-4088 (nested replies + reply pagination). Driven via orchestrated-feature-dev.P0
upredict-backend·feat/UBET-4184-user-reply-on-top2 months ago
#186
RISE-15577 — Add SM org type + status columns to organizations_associations and backfillGive RSC a place to store Supplier Management's own organization type and status, per ecosystem, and backfill what SM already knows.
SCOPE (operator-confirmed, narrower than it looks): migration + one-time backfill script ONLY. No write path, no GraphQL, no UI. RISE-15509 (card #171) still owns wiring POST /data-management/add-org-into-ecosystem to populate sm_type; the consumer/filter tickets (15478/15479/15510/15557/15487, all BACKLOG) own reading it. Not demonstrable alone — a prerequisite, like 15509.
SHAPE: two new columns on organizations_associations (the `initiator` row = RSC's per-ecosystem org record), both new PG enums in SM's own vocabulary — sm_type = B R S V F I O, sm_status = draft/awaiting approval/active/inactive/suspended/blacklisted/closed. Matches SM_ORGANIZATION_TYPES / SM_ORGANIZATION_STATUSES and the SmOrganizationType / SmOrganizationStatus SDL enums RISE-15476 already shipped, so no translation layer.
BACKFILL: reads SM's true values from cdc_passport_be.ecosystem_organization via ecosystem_organization_sync (product='rise'). Covers 11,192 of 285,703 initiator rows (3.9%); the rest stay NULL. Deliberately NOT derived from RSC's own columns — organizations.type is a lossy collapse (839 SM Brands stored as `retailer`, 9,184 Suppliers as `partner`, 1,084 Vendors as `external`) and organizations_associations.status is `active` on 285,277 of 285,284 rows, so a literal prefill would write known-wrong values and zero information.
MR needs the [MIGRATION] tag.
Design context: RISE-15509_SM_RSC_ORG_MODEL.md (repo root) and rs-backend-RISE-15509/DECISIONS.md D23–D32.P0
rs-backend·feature/RISE-15577/add-sm-org-type-status-columns2 months ago
#187
VN development-gap investment edge research (nhà đất + adjacent) — Biên Hòa/Đồng NaiFind structural "developed-world-fixed / VN-still-broken" inefficiencies a semi-active local investor (~4-6B VND, HCM/Đồng Nai/Biên Hòa, buy-and-hold-never-sell, rent-now-convert-to-family-home-in-~5yr) can capture DIRECTLY — beyond what his existing VN stocks/gold/crypto book already gives. Brainstorm agent produced 11 theories; top-5 picked for deep research: T3 titled nhà phố (rent→home), T2 quy hoạch/infra-cycle land timing, T1 đất nông nghiệp→đất ở conversion, T4 nhà trọ worker housing near ĐN zones, T5 untitled→titled (giấy tay/chung sổ→sổ hồng riêng) arbitrage.P0
2 months ago
#188
UBET-4265 FE patch: show-more window for creator markets (5 at a time)Creator profiles fetch and render EVERY market a creator owns; prod creator 11849 has 1,444 specs / 21,335 markets (measured in backend #739), so the page mounts thousands of cards and pegs the browser tab at 100% CPU. Temporary FE-only patch: keep the unpaginated fetch, render a growing window — 5 initially, +5 per "Show more" click. New useShowMoreList hook in src/core/hooks/ (justified by 3 consuming surfaces: profile MyMarkets, MyMarketsPage, admin SettleMarketsPage); window resets when the underlying list changes (tab switch). Reuses the existing showMore i18n key (all 7 locales). Worktree upredict-frontend-ubet-4265, branch UBET-4265-creator-markets-show-more off origin/main (a16e48e). Plan + progress in tmp/UBET-4265/. Server-side pagination of /marketsByCreator + /users/:userId/marketsByCreator is the deferred follow-up (contract chosen: always-paginated envelope).P0
2 months ago
#190
BE audit: find every list endpoint without pagination (proper fix for the unbounded-list class)Follow-on to the UBET-4265 FE stopgap (card #188): rather than windowing one surface, find the whole class of the problem. Audit all 49 route files in belief_locker for LIST endpoints that return a bare unbounded array, and rank by growth risk. Baseline: only 7 of 49 route files currently use the house pagination helpers (getPaginationParams / withPaginationResponse / PAGINATION_QUERYSTRING_SCHEMA in src/utils/pagination.ts) — groupedMarketNotificationsRoute, getMarketComments, homeRoute, marketsBySimilarity, notificationFeedRoute, subscribedNotificationsRoute, userFollowList. Known-bad exemplar: marketsByCreator (creator 11849 = 1,444 specs / 21,335 markets; already caused a 57014 statement timeout in BE #739 and a 100% CPU tab on FE). Audit runs in a dedicated read-only worktree upredict-backend-pagination-audit detached at origin/main 70b688b5 — the main upredict-backend checkout is on perf/test-db-template and is 8 commits behind, missing routes such as market/marketVoterList.ts, so it must NOT be used as the audit source. Four parallel subagents partitioned by area: market/, bet+leaderboard, notifications+social, engagement+misc.P0
2 months ago
#191
Replace syntax-recipe exercises in Data Structures & Strings (Python + C++)Follow-up to card #97. Operator's complaint: several exercises in the Data Structures & Strings lessons are implementation recipes, not problems.
Operator's test (corrected from my first pass): an exercise fails when the PROBLEM STATEMENT prescribes the implementation steps AND that machinery is not needed to produce the stated output. "Print it backwards" is a goal → fine. "Store in a tuple, print the tuple, unpack it, print each part" is a recipe, and print(f"({x}, {y})") gives the same output → fails.
HARD FAILS (machinery provably redundant) — replace with new problems:
- Python pool: #1 Swap Two Numbers, #2 Coordinates with a Tuple, #13 Build a Date with join, #15 Total and Average Score
- C++ pool: #2 Sum of a Vector, #12 Split into Words (echoes input), #14 Total and Average Score, #18 Convert Between Text and Numbers, #20 Receipt Line
- Lesson pages: Python inline Ex1 Swap, C++ inline Ex7 Split into Words
SOFT FAILS (real goal, but statement names the tool) — reword to state only the goal:
- Python pool #9, #16, #18, #20; C++ pool #3, #10, #15; Python inline Ex8; C++ inline Ex2, Ex6, Ex8
Constraint chosen by operator: KEEP feature coverage. Replacements must still genuinely require unpacking / join / stoi / to_string / vector / substr etc. — but require them for real, not as ceremony.
Files:
- app/lesson/programming-python/data-structures-exercises/exercises-data.ts (27 exercises)
- app/lesson/programming-cpp/data-structures-exercises/exercises-data.ts (27 exercises)
- app/lesson/programming-python/data-structures-strings/page.tsx (inline practice, L306-441)
- app/lesson/programming-cpp/data-structures-strings/page.tsx (inline practice, L279-422)P0
2 months ago
#192
Werewolf Narrator — mobile single-device game host appNew standalone Next.js 16 app at personal/werewolf: a mobile-first web app that runs an in-person Werewolf ("Ma Sói") game from one phone. Host adds players, app deals roles, players privately reveal by passing the phone, app walks the host through night/day phases, resolves deaths, calls the winner. No backend, offline-capable, localStorage persistence.
Stack mirrors personal-website (Next 16, React 19 + Compiler, Tailwind v4, Biome, src/* alias) with two deltas: shadcn on Base UI (@base-ui/react) instead of Radix, and Vitest + jsdom + Testing Library borrowed from lms/.
Roles: Werewolf, Villager, Seer, Doctor, Witch, Hunter, Cupid, Fool. Bilingual VI/EN.
Plan + progress: tmp/werewolf-narrator/P0
2 months ago
#193
RISE-15478 — Request Single Assessment: filter Assessed Org / Selected Partner / auto-share by standard's org type & statusOrchestrated-feature-dev run for RISE-15478 (epic RISE-15475, blocked-by RISE-15476 which is already in pre-prod testing; FE part of 15476 merged to master).
Make the SINGLE assessment request form honor the standard's per-stakeholder organization type/status filters that RISE-15476 stored:
- AC1 Assessed Organization dropdown filtered (All + Activation List tabs), with guidance text when a search matches nothing.
- AC2 Selected Partner auto-display + "Add more" dropdown both filtered.
- AC3 Assessment Visibility / auto-share shows "Limited to Organization Types: {types}"; Open-audit variant filters its dropdown too.
- AC4 validate on save + revalidate on edit (New status only) → "Invalid organization" per stakeholder + removal alert.
- AC5 follow-up assessment copies stakeholders then validates the same way.
Gated by DF `release_org_type_sm` (precondition `supplier_management`) — must be fully inert when off.
OUT OF SCOPE: bulk request (RISE-15510, backlog) and the Standard Settings UI itself (RISE-15476, shipped).
Worktrees:
- BE /Users/quan.vo/Documents/git-repos/inspectorio/rs-backend-RISE-15478 on feature/RISE-15478/request-asm-org-type-status-filter, based on the UNMERGED feature/RISE-15577/add-sm-org-type-status-columns (carries the 15476 BE commits + the SM org type/status columns on organizations_associations).
- FE /Users/quan.vo/Documents/git-repos/inspectorio/rs-frontend-RISE-15478 on the same branch name, based on origin/master @ cab72cac2f.
Workspace: rs-backend-RISE-15478/tmp/RISE-15478/ (TASK_CONTEXT.md holds the full ACs and the 17 QA test cases).P0
2 months ago
#195
UBET-4260 BE: return replies in oldest-first order at the 3rd levelTicket UBET-4260 (Bug, epic UBET-4146 "Reply to comments"), title "return reply in oldest first order in 3rd level", NO description and no comments in Jira — requirements must be clarified. Notably "3rd level" is ambiguous: the comment tree is only 2 levels deep (root comments + replies flattened at depth 2, per UBET-4088), so "3rd level" most likely means replies (level 1=market, 2=comments, 3=replies) — must be confirmed with the user. Explicitly foreseen by card #185 / UBET-4184 decision index 2: "Design against today's reply ordering (newest-first under sort=newest, score-first under relevant), not UBET-4260's future oldest-first order... Accepted risk: some rework when 4260 flips tree replies to oldest-first." Branch fix/UBET-4260-third-level-replies-oldest-first off feat/UBET-4184-user-reply-on-top (84b667a4), worktree workspace/upredict-backend-ubet-4260. Driven via orchestrated-feature-dev; task workspace tmp/UBET-4260/.P0
2 months ago
#198
Modular paper-trading engine (pluggable strategy + params)Build a paper-trading feature in quant-trading that runs any existing strategy against live/forward data with simulated fills. Hard requirement from the operator: fully modular — any strategy pluggable, any parameter set accepted, must work end-to-end. Run via orchestrated-feature-dev. Workspace: quant-trading/tmp/paper-trading/P0
quant-trading·mainlast month
#199
UBET-4296 tagging search broken — @mention search can't find 89% of usersTicket UBET-4296 "Tagging search broken" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo). NO description and no comments in Jira. Repro from user: the @mention typeahead cannot find user "quan vo".
ROOT CAUSE (confirmed on testnet, 2026-08-21). get_users_search.sql filters on exactly two fields: `au.nickname` and social `raw_user_meta_data ->> 'user_name'`. It never touches `au.user_alias`, and never touches the social `name`/`full_name` that Google populates. `user_name` is a Twitter/X-only field.
Testnet counts (abstract_user LEFT JOIN auth.users): twitter 32/32 searchable; google 2/145; no-social (wallet/email) 8/219. Total 42/396 searchable — 354 users (89%) can never be returned by the mention search no matter what is typed. Meanwhile `user_alias` is non-null for all 396.
All three "quan vo" rows (ids 27387/63158/102412) are google: nickname NULL, social user_name NULL, user_alias quanvo/QuanVo2/QUANVO3, social name "quan vo"/"Quan Vo"/"QUAN VO". Replaying the production query verbatim for q='quan' returns [] — reproduced exactly.
SECOND, SAME-ORIGIN BUG: usersSearch.ts maps `username: row.rawUserMetadata?.user_name ?? null`, hand-rolled instead of using the shared convertRawMetadata() in socialUserInfo.ts, which does `user_name ?? name`. The mention route is the one place in the codebase that drops the `name` fallback. So even once search matches, FE getUserDisplayName({nickname, username}) gets two nulls for a Google user and renders "Unknown".
THIRD (independent, FE): getMentionQuery in src/features/comments/utils.ts uses /(?:^|\s)@([\p{L}\p{N}_.-]*)$/u — no space in the class. Typing "@quan " closes the dropdown, so no two-word name is typeable in full.
FOURTH (aggravator): `order by au.nickname asc nulls last limit 20` deprioritizes exactly the null-nickname users who dominate the table.
Fix-variant counts measured on testnet for q='quan' / q='quan vo': current 0/0; alias-only 5/0; alias + social name 5/3.P0
last month
#200
UBET-4290 BE: search API — fuzzy search, one merged market tab, relevance rankingTicket UBET-4290 "Search functionality for users & markets (question and options)" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo). NO description and no comments in Jira — requirements must be clarified. Epic UBET-4291 "Explore (Search)"; siblings UBET-4295 "Search UI/UX" (Nick Mai, FE) and UBET-4296 "Tagging search broken" (Quan, in progress). Backend work in worktree upredict-backend-ubet-4290, branch feat/UBET-4290-search-users-markets, based on fix/UBET-4296-tagging-search (UNPUSHED, card #199) — so this branch inherits an unmerged dependency. Following the orchestrated-feature-dev pipeline; workspace tmp/UBET-4290/.P0
last month
#202
Buffett-style value upgrade for the monthly DCA picker — research & suggestionsSuggestion-only research: map Buffett value-investing criteria against the current §3.0/§4 picker rules, find the gaps, and identify VN data sources (Simplize/FireAnt/Vietstock/WiChart/TCBS/ARs...) that can support the missing metrics (FCF/owner earnings, multi-year ROIC/ROE consistency, moat proxies, capital-allocation record). No rule edits without explicit approval. Workflow run wf_78b11fca-e56.P0
last month
#204
UBET-4102 create market with reel URL (BE API)Backend API to create a market from a reel URL (TikTok / YouTube Short / Instagram Reel) and return the reel URL on the market read API. Parent epic UBET-4107 Reel Market; spike UBET-4047 (Notion "Embedded Reels Spike"); prior brainstorm in workspace/tmp/reel-market-create/. Following orchestrated-feature-dev; workspace tmp/UBET-4102/.P0
upredict-backend·feat/UBET-4102-reel-market-urllast month
#205
September 2026 Phase A — first v1-vs-v2 parallel picker runRun the September monthly DCA research producing BOTH shortlists: v1 (canonical STRATEGY_NOTES/DCA_CANDIDATE_DISCOVERY funnel) and v2 (PICKER_RULES_V2.md — cash-conversion, own-history bands, ROIC/leverage/moat, top-3 by value score, no dividend scoring), plus the 5-part v1-vs-v2 diff report. Regime: VNINDEX > MA200 → stocks/funds 1×; BTC +10.9% above 200d → crypto flips 2×→1× ($500/clip). Advisory / flag-for-review only.P0
last month
#207
UBET-4308 investigate duplicate markets on testnetJira UBET-4308: explore why testnet has too many duplicate markets (Slack: Daniel J. Im flagged markets 82287/108836/150200 all named "Which do you think is superior"). Read-only investigation via Supabase MCP (testnet) + backend code. Two mechanisms found so far: (1) spec-level duplicates — new market_spec rows with identical names every ~2 days; (2) round-level duplicates — ResurrectMarketsTask re-opens the same spec as market_round+1 (spec 183965 reached round 8 in 3 days, all Push). Resurrection volume jumped from ~0/day to 2k–14k/day starting 2026-08-17, same day as UBET-3986 (#740) "compute resurrection threshold dynamically" landed.P0
last month
#208
UBET-4124 notify market creator about reel play error (BE)Stacked on feat/UBET-4102-reel-market-url (PR #767, card #204). Ticket has no description: "notify market creator about reel play error". Worktree upredict-backend-ubet-4124, branch feat/UBET-4124-reel-play-error-notification. Run via orchestrated-feature-dev; workspace tmp/UBET-4124.P0
last month
#209
Skill folder fidelity: skill.ignore (upload exclusions + guidelines) and executable bit preserved on installFollow-ups from card #206 (pull supporting-files fix), now in scope:
1. skill.ignore — collectSupportingFiles (src/app/api/lib/local-fetcher.ts) uploads everything in a skill dir (.DS_Store, node_modules, scratch) and silently skips nested symlinks. Add an optional skill.ignore at the skill root (gitignore-style patterns), always-on junk defaults, never upload skill.ignore itself, explicit symlink policy; document guidelines in setup-private-skills SKILL.md (all 3 agents' source copies under skills/).
2. Executable bit — every install path (init/add/sync/pull + hooks-install) writes 0644 via writeRuleFile, so scripts lose +x. Add optional `executable?: boolean` to the shared supporting-file entry (SkillFile/HookFile.supportingFiles in src/server/types.ts + CLI types), set from stat mode at upload/local discovery, chmod on install. Byte-identical for existing documents.
Then bump cli-package and let CI publish.P0
last month
#212
SEO image for reel markets captures TikTok cookie-consent dialog instead of the videoDiagnosis only, no code changed.
SYMPTOM: the generated SEO/OG image for a TikTok reel market shows TikTok's "Allow cookies from TikTok on this browser?" consent modal where the video should be, over the two outcome buttons.
CHAIN:
- upredict-backend/typescript/services/seo_image_generator/src/index.ts — Lambda (cron every 5 min, Terraform/environments/backend/main.tf) launches puppeteer headless Chrome with userDataDir=/tmp/puppeteer_<uuid>, goes to {originUrl}/markets/{id}/place?preview=true, waitUntil networkidle0, waits for .preview-content, screenshots that ELEMENT as jpeg, PUTs to S3, inserts upredict_backend.market_seo_image.
- upredict-frontend origin/main: PlaceBetPage.tsx:31-47 reads ?preview and adds .bet-card-preview; PlaceBetCardContent.tsx:404 is the .preview-content wrapper -> Field component=MarketOutcomes -> Market2TextBasedOutcomes.tsx:114 <MarketMainImage> -> MarketMainImage.tsx:15-21 returns <MarketReelEmbed> when market.reel is set -> MarketReelEmbed.tsx renders <iframe src=https://www.tiktok.com/player/v1/{videoId}?controls=1&autoplay=1> (utils.ts:252).
- So the third-party TikTok iframe sits INSIDE the screenshotted element.
ROOT CAUSE: a fresh userDataDir per invocation means every run is a first-time visitor to tiktok.com with no consent cookie, so TikTok's player embed renders its consent gate instead of the video. Nothing in preview mode suppresses the embed — .bet-card-preview (globals.css:314-322) only hides .market-outcome-participants, .market-outcome-footer and .market-progress-clock. networkidle0 + .preview-content are both satisfied while the consent modal is up, so the screenshot is taken and stored as a success.
SECOND-ORDER: the backlog query selects only markets with NO market_seo_image row, so a bad image is written once and never regenerated.
RELATED TICKETS (epic UBET-4107 Reel Market): UBET-4123 "download thumbnail for reel markets" (Todo) is the natural fix. UBET-4047 spike (Notion Embedded Reels Spike). UBET-4279 homefeed (In Progress), UBET-4280 create-market (Committed), UBET-4281 profile (Todo). SEO pipeline tickets: UBET-3650 seo render in backend, UBET-3818 Chrome in devenv, UBET-3613 (earlier same-shaped bug: SEO snapshot missed images).P0
last month
#216
Build + seed "Sep 5 Test" (20 MC + 10 coding, 7 easy/3 medium) for LMS prodSecond test in the language-agnostic (Python/C++) series for course c98f8f96 (Stem T-coding), needed by Sep 5. 20 new misconception-targeted MC (weight 2, bilingual explanations) + 10 short coding problems: 7 easy (weight 4) + 3 medium (weight 6), all with Python AND C++ reference solutions. No question overlap with the 40-Q review test (f87f3005). Graded, untimed, exam-safe flags. Same validation pipeline: biome, structural check, execute all references + MC answer keys, throwaway local seed, then Atlas seed.P0
4 weeks ago
#218
LMS: course share link → student self-signup → join request → teacher approvalOrchestrated-feature-dev run in /Users/quanvo/Documents/git-repos/personal/lms (branch feat/practice-mode-v1). Workspace: lms/tmp/course-join-requests/.
REQUIREMENT (user, verbatim): "help me check lms system, help me check how can a teacher share a link to a course, then student can create their own account, either by username/password, or gmail, then request to join that course, then the teacher can approve student to join, just like enrolment."
Capability chain:
1. Teacher/admin shares a link to a course (shareable course invite link).
2. Prospective student opens the link and self-registers — username+password OR Google/Gmail sign-in.
3. Student requests to join that specific course.
4. Teacher sees pending join requests and approves/rejects; approval = enrollment.
Living spec target: documents/features/course_join_requests.md (this repo keeps feature specs under documents/features/, not docs/features/).P0
4 weeks ago
#220
UBET-4323 render reel thumbnails in SEO images + Instagram via Meta tokenBug UBET-4323 (parent epic UBET-4107 Reel Market, Sprint 117, assignee Quan Vo). Follows the diagnosis on card #212 and the probe work on card #208 (UBET-4124).
PROBLEM: SEO/OG images for reel markets screenshot the live market page under ?preview=true with a fresh puppeteer profile each run, so the embedded provider iframe renders its consent/login gate instead of the video.
FIX: under ?preview=true render a static thumbnail instead of MarketReelEmbed, removing third-party iframes from the image pipeline. YouTube (URL-derivable) and TikTok (public oEmbed thumbnail_url) need no token — 47 of 77 testnet reel markets. Instagram (29 of 77) needs a Meta app token for Graph instagram_oembed (oEmbed Read review).
The same Meta token also unblocks Instagram in the reel liveness probe, where every instagram.com reel is currently retired as terminal `unprobeable` on sight. Those retired markets must be re-armed or they stay dark after the token lands.
ALSO: bad images are never retried — the backlog query skips markets that already have a market_seo_image row (75 of 77 on testnet). Decide whether to delete those rows, and whether that applies to production.
Following orchestrated-feature-dev. Workspace tmp/UBET-4323. Worktrees: upredict-backend-ubet-4323 and upredict-frontend-ubet-4323, both on branch feat/UBET-4323-reel-seo-thumbnail (BE stacked on feat/UBET-4124-reel-play-error-notification at 2aa1d186; FE on origin/main at 67c81b7).P0
4 weeks ago
#223
Fix CI flake: test postgres given only 3s to accept connectionsmain run 34136950140 shard 4 failed on `[PostgresTestInstance.launch] wait for accepting connections`. Cause: waitForLogLine had a hardcoded 3000ms race; 4 jest workers each cold-start their own postgres on a swapping runner. Fix on branch fix/ci-postgres-launch-timeout (commit 7837eeb6): caller-supplied timeout (default stays 3s so anvil is unchanged), 15s for the postgres launch, plus postgres stderr folded into the assertion message. Committed, not pushed.P0
4 weeks ago
#225
Code review: upredict-backend PR #776 — UBET-4317 associate existing markets into category listReview https://github.com/SportsFI-UBet/upredict-backend/pull/776 ([UBET-4317] Associate existing markets into category list, author quangtran-sportsinference, branch UBET-4317-associate-existing-markets-into-category-list -> main). 47 files, +6150/-0.
WHAT IT DOES: adds a new `market_category_classification` Python service that classifies markets against an interest taxonomy via a batched LLM call (bisects a failing batch to isolate one bad market; bounded by a Lambda-derived wall-clock deadline). Persists per-market classification vectors as safetensors matrices in S3 with positional `row_index` identity in Postgres, precomputes per-category/subcategory relevance scores, and adds a belief_locker TypeScript consumer (get_sampled_markets_for_categories.sql, get_user_picked_category_ids.sql, marketRecommendationService.ts) for home-page category recommendations. 7 new tables.
SETUP: worktree at workspace/upredict-backend-pr-776; review artifacts under its tmp/pr-776/review-changes/ (HOLISTIC.md, DIFF.patch, LENS_*.md), final report at tmp/pr-776/review-changes.md.
Running /review-changes at fan-out depth — all six lenses applicable, none skipped.
HOLISTIC's headline concerns for the lenses to resolve:
1. `row_index` is positional identity split non-atomically across S3 and Postgres; write_classification_rows' `on conflict do nothing` can produce a non-contiguous orphan the tail-truncation repair mis-handles.
2. `_write_relevance` deletes and re-inserts the entire markets x categories cross-product every run on an explicitly unmeasured cost assumption.
3. The vertical slice is incomplete in a way the PR description overstates: sampleMarketsForUserPicks has no caller, user_interest_category is read but written by nothing here, and the taxonomy rows the dense-dimension_index assertion depends on are seeded outside this repo.
4. Nothing ever reclassifies a market (prompt_version written, never read).
5. The new sampling query lacks the deadline/status filter get_home_markets.sql goes to lengths to get right.
Also noted as done WELL (don't re-litigate): bisection instead of dropping whole batches, real Lambda-derived deadline, refusing to run on an empty taxonomy, stabilized softmax, make_conninfo over f-string conninfo.P0
4 weeks ago
#226
UBET-4334 — Belief Points as a chain, a token and a balanceOrchestrated-feature-dev run for UBET-4334 (parent epic UBET-4282 "In-App Currency Betting"; blocks UBET-4335 "Every market also exists in belief chain"). Sprint 118, assignee Quan Vo, 4h estimate.
TICKET ASKS (4):
1. Add a `blockchain` row for Belief Points + one `collateral_token` under it.
2. Tell the two token kinds apart with a flag; make `collateral_token.address` optional.
3. Let a `market` row exist with no `contract_address` and no `deadline_block`.
4. Expose a user's spendable balance = frozen legacy snapshot + sum of points history, computed on demand.
AC: /chain returns the new chain and its token; a market row can exist against that token with no chain fields set; a balance reads back as the same total the profile already shows.
PRE-READ FINDINGS (main session, before orchestration):
- Ask 4 likely ALREADY EXISTS: GET /userRealtimePoints -> get_user_realtime_points.sql already computes greatest(0, legacy_leaderboard_view.legacyPoints + sum(point_ledger.points) post-cutoff) on demand. Open question whether "spendable" means net of points locked in open bets.
- AC "/chain returns the new chain" will NOT happen from DB rows alone: chainRoute.ts:71-80 silently drops any chain absent from the predictionMarketAddresses map, which is built in index.ts:88 collectPerChain via createEvmService -> asserts an Alchemy URL exists and chainId is in `chains` (evmService.ts:105-107). A synthetic points chain crashes the service at boot. Requires a chainRoute code change + a decision not written in the ticket.
- Nullable collateral_token.address breaks /chain for EVERY chain: get_tokens.sql selects ct.address, parsed with z.string() at chainRoute.ts:59; one NULL throws and 500s the endpoint.
- ChainResponse.tokens[].contractAddress is `string` and marketContractAddress is `EthAddress`, both non-nullable (jsonSerializable.ts:16,20) — widening is a frontend contract change + codegen regen.
- `unique (blockchain_id, address)` stops enforcing once address is nullable (Postgres NULLs are distinct) — needs a partial unique index or NULLS NOT DISTINCT.
- Nullable market.contract_address / deadline_block touches ~13 and ~6 appSql files; metric views select+group by contract_address so points markets become a NULL bucket rather than dropping rows (degrades, not breaks).
- 4h estimate looks light.
RELATED PRIOR WORK: card #211 (6a993f86c0af1b6c8a13d4b4) UBET-4282 currency model design brainstorm (staled) — read for prior decisions.P0
4 weeks ago
#228
UBET-4335 — Every market also exists in belief chain (points twin)Orchestrated-feature-dev run for UBET-4335 (epic UBET-4282 "In-App Currency Betting"; blocked by UBET-4334, blocks UBET-4336). Sprint 118, assignee Quan Vo, 3d estimate.
Ticket ask: a market created on a real chain also gets a second `market` row on the Belief-Points collateral against the SAME `market_spec` — question, outcomes, images, translations and creator shared, one extra row. Covers already-open markets (backfill) and resurrection. Open decision in the ticket: creation-transaction hook vs worker.
Worktree `workspace/upredict-backend-ubet-4335`, branch `feat/UBET-4335-points-market-twin`, based on `feat/UBET-4334-belief-points-chain` @ 5bf32288 (NOT main — 4334 is unmerged and this depends on `blockchain.kind`).
Pre-read ticket check at `workspace/tmp/UBET-4335/TICKET_CHECK.md`. Headlines from it:
- Ticket text is STALE on three bullets: 4334 chose sentinels not nullable columns (D3), so `deadline_block` stays `not null` with the sentinel 2147483647 (D14) — "no block number" is wrong; the `kind` flag is on `blockchain` not `collateral_token` (D6), reached via market -> collateral_token -> blockchain.
- MISSING from the ticket, biggest item: `get_search_markets.sql:81` dedups `distinct on (m.spec_id)` and ties break on `m.id desc`, so the later-written twin ALWAYS wins. Search has no chain filter at all — every twinned question would return its points market to every user on every chain.
- MISSING: creator page + home feed both gate on `chainId is null or ...` and both routes pass `query.chainId || null`, so with no chain filter a question lists twice.
- MISSING: `resurrectMarkets()` loops `this.perChain.keys()` (createMarketService.ts:521); `perChain` entries need an `EvmService`, so the points chain can never be in it. Resurrection needs its own path, and `createMarket()` cannot be reused for the twin (it starts with `getLatestBlockInfo`) — must be a direct insert.
- 4334 deferrals R9 + R10 DISSOLVE: `market.contract_address` is chain-wide (`chainData.predictionMarketAddress`), so the blacklist and reward aggregates already pool per contract for real chains. Still live: D20 (`BigInt(token.maxBetSizeWei)` FE crash, made reachable by this ticket) and D22 (points market vanishes from listings after deadline until BE4 settles it).
- Ticket's two stated warnings are real but described off: the auto-vote is `on conflict (user_id, market_spec_id) do update` (insert_bet.sql:45) so the second bet OVERWRITES the first vote; the weekly ranking pools bet COUNTS not volume (upredict_index_view_function.sql:1053).
- Recommendation on the open decision: worker (only option that covers resurrection at all, covers the backfill with the same code, idempotency is a query not a lock, precedent in tasks/copyMarkets.ts + ResurrectMarketsTask). Note CopyMarketsTask is NOT reusable — it calls createMarket() and duplicates the question.P0
upredict-backend·feat/UBET-4335-points-market-twin4 weeks ago
#230
Skills: default to integration tests over unit tests (survey project test patterns first)Add a test-level rule to the feature-dev skills: prefer a test that exercises the real flow through the client-facing entry point with real collaborators, over an isolated unit test with mocked collaborators. Before writing the first test the agent must SURVEY the project's existing test patterns (test command, dirs/naming, harness + setup files, fixtures/factories, an example integration test to mirror). If no usable integration harness exists, HARD GATE: stop and ask the operator (stand one up as its own step / point at one missed / accept unit-level) — never silently fall back to mocked unit tests.
Scope decided with the user: (1) all three agent variants — skills/claude-code, skills/cursor, skills/antigravity (antigravity has no feature-dev-lite, so it only gets orchestrated-feature-dev); (2) hard stop-and-ask when no harness; (3) bdd-design also gets a short pointer, with the full survey/ask protocol living in the two feature skills.
Files: feature-dev-lite/SKILL.md, orchestrated-feature-dev/SKILL.md + nodes/node-research.md + nodes/node-plan.md + nodes/node-bdd-step.md, bdd-design/SKILL.md.P0
4 weeks ago
#235
Review RISE-15482 MRs — automation rule org type/status filter (FE !7217, BE !6434)/review-changes code review of xuanphuong's paired MRs for RISE-15482 (epic RISE-15475): rs-frontend !7217 (activation-list excluded-org warning + executor warning on the automation rule) and rs-backend !6434 (daily automation run applies the Standard's current assessed/executor org type & status filters). Worktrees: rs-frontend-pr-7217 @726fb30, rs-backend-pr-6434 @b88d6c9, base origin/master. Reports land in <worktree>/tmp/mr-7217|mr-6434/review-changes.md.P0
3 weeks ago
#236
Test review: add a necessity check, name the mock-entailment signature, cut the assert-on-mocks guidanceReview-time counterpart to card #230 (which set the WRITE-time integration-first default). Trigger: the user keeps finding unit tests that guarantee nothing — they mock an API, then assert the API returned the mocked value. The assertion is entailed by the test's own arrange block, so production code is not in the causal path.
Audit finding: every test-review section asks "is this test MEANINGFUL?" (answer = improve the assertion) and none asks "should this test EXIST?" (answer = delete it). Worse, test-quality-reviewer actively manufactures the bad pattern — its Sensitivity pillar recommends `expect(fn).toHaveBeenCalledWith(...)` and its Resilience pillar says "checking internal helper calls is OK for unit tests". review-changes and feature-dev-lite both defer their deep test pass to that skill.
Scope (all 3 agent variants — hand-maintained ports, no generator):
1. node-lens-tests.md — necessity check FIRST, ahead of coverage; name the entailment signature with a concrete bad example; SHOULD FIX severity floor.
2. lens-common.md — "Suggested fix" must admit deletion; add a tests-lens accepted failure-mode form (the MISSED DEFECT that ships green), or a useless test gets filed as a NIT maintainability note.
3. orchestrated node-validation.md §2 — same necessity check + entailment signature.
4. test-quality-reviewer — CUT the mock-interaction sensitivity lines and the "internal helper calls OK" clause outright (user: remove the lines, do not add a caveat). Especially wrong for integration tests.
5. feature-dev-lite — add the inverse to "What to Avoid" so it is prevented at write time too.
Do NOT hand-edit the .claude/skills/ dogfood copies — the CLI regenerates them.P0
3 weeks ago
#237
Review RISE-15514 MR — assessment visibility by standard's "Share with organization types" (BE !6437)/review-changes code review of Luis.Tan's rs-backend !6437 for RISE-15514 (epic RISE-15475): the standard's "Share with organization types" setting now controls who actually has visibility of an assessment, its report and its CAPA (AC1 auto-share to business partners, AC2 individually selected orgs, AC3 no config = unchanged). DF release_org_type_sm + supplier_management. Business accuracy checked against sibling epic cards (#168 RISE-15476, #193 RISE-15478, #210 RISE-15592, #221 RISE-15510, #186 RISE-15577, #235 RISE-15482 review). Related bug RISE-15741 (visibility unchanged after saving standard sharing settings for 1,000+ assessments). Worktree rs-backend-pr-6437.P0
3 weeks ago
#239
Celery + Redis background tasks: async notifications & email fan-out (buildly-django-project)Add a background task system to buildly-django-project (Django 5.2 + DRF + SimpleJWT, `accounts` app, Next.js frontend). Two behaviors in scope, chosen by the user over email-only: (1) an in-app Notification record (recipient, type, payload, read state) written asynchronously by a Celery task and exposed over the existing DRF API; (2) an async email fan-out for that notification via Django's email backend, with retry on failure and recorded delivery status. Running via the orchestrated-feature-dev pipeline; workspace tmp/celery-background-tasks/. Repo has no .ai-rules.json. Note: repo is on `main` with a clean tree — needs a feature branch before any commit. Deployment is Render/Vercel/Neon, so a Celery worker needs its own process (noted, not yet designed).P0
buildly-django-project·feat/celery-notification-worker3 weeks ago
#241
Plan + build Files, Sorting & Records handouts (Python + C++) — the 100-student problemNext lesson after Data Structures & Strings (cards #97, #191). Covers curriculum module 8 (Files) plus sorting and records, but organised problem-first, not topic-first.
# Method (operator's, corrected through several passes)
One real contest problem drives everything: read 100 students, print lowest→highest score. Every technique appears ONLY when a wall demands it. Second thing taught is decomposition (GET/KEEP/DO/SHOW) — NOT to be called "divide and conquer" (that name is reserved for mergesort/binary search later).
Walls, in order of pain:
1. Can't retype 100 rows → file input (ifstream / open)
2. Scores sort fine, but the problem wants NAMES → parallel arrays produce a program that compiles, runs, looks right, and pairs everyone wrong (shown on 5 rows, never 100) → tuple/pair in a list/vector
3. Payoff: box-by-box diff shows GET/KEEP/SHOW changed, DO is byte-identical. Verified by compiling both C++ versions.
# Corrections the operator made during design (do not regress)
- Sorting must come BEFORE records. Without sorting there is no wall — parallel arrays work fine.
- The name requirement is ADDED to a solved problem (requirements grow), not "restored after simplifying".
- No session labels in the handout — one continuous flow, operator splits it live. Break points after sections 5, 6, 10.
- Do NOT teach shell redirection (`./prog < scores.txt`). I invented a fake "spoiler" conflict around it across two turns; it is not in the syllabus and adds a failure mode for nothing.
- Section 0 = install only (bash, language toolchain, compile+run). No proof checklist, no troubleshooting section.
- Dropped the "four-box worksheet" as a graded artifact — the boxes stay as explanation only.
# Decisions
- Windows only. No Mac/Linux track.
- TWO separate files, one per programming language (both still bilingual EN/VN per repo convention).
- Python setup: Git Bash + python.org installer ("Add python.exe to PATH").
- C++ setup: MSYS2 ONLY — its UCRT64 shell is itself bash AND has g++ on path, so students never edit Windows PATH (the classroom-killer step). `pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain`. Verified against current VS Code / mingw-w64 docs.
- Data file uses ONE-WORD names; full names with spaces break `>>` and would cost half the lesson on stringstream. Save as a later bump.
- Deliberately NOT taught here: comparator lambdas / `key=`, `struct`, dicts-in-a-list. Field-order choice + reverse covers everything. Comparators arrive when a mixed-direction sort (score desc, name asc) demands them.
# Done so far
- app/lesson/programming-python/files-sorting-records/manifest.md
- app/lesson/programming-cpp/files-sorting-records/manifest.md
# Remaining
- page.tsx for each (print-friendly component structure, CodeBlock language py/cpp)
- scores.txt generator (100 Vietnamese names + random scores, regenerable for homework variants)
- Add both to courses.md and app/page.tsx nav
- One clean Windows run-through of section 0 before it goes to students (I am on macOS and could not test Git Bash / MSYS2)
# Stint 2026-09-27 — more section 9 exercises
Operator asked for more exercises in section 9 and more sorting of records (struct / tuple). Adding: 3 sort-order exercises on name+score (highest first, top 10 with place, closest to 75) and a three-field part (name math literature): Python 3-part tuple, C++ struct taught briefly in section 9, with sort-by-math / sort-by-literature / sort-by-total exercises. Homework (alphabetical) stays last.P0
3 weeks ago
#243
Sep 13 Test — 20 MC + 10 file I/O coding (after Files lesson §6)LMS test data file following data-9-6-2026-sep-6-test.ts: 20 hard misconception MC with revealing explanations, 10 free-text file input/output problems, scoped strictly to Files, Sorting & Records sections 0–6 plus prior lessons.P0
3 weeks ago
#246
UBET-4337 — Settle a belief points market and move the points (BE4)Epic UBET-4282 "In-App Currency Betting", ticket BE4 in tmp/UBET-4282/ticket-breakdown.md. Depends on UBET-4336 (card #240). Worktree upredict-backend-ubet-4337, branch feat/UBET-4337-belief-points-settlement, branched from local feat/UBET-4336-belief-points-bet tip 7edf5e7f (4336 unpushed). Ticket: worker settles points markets past deadline, reuses off-chain payout calc, pays winners + creator + platform fee atomically, or refunds full stake; remainder rule (blocked); relax transaction_hash on settlement tables + market_result.commitment; idempotent re-run.P0
3 weeks ago
#249
Werewolf PR #2: bring the role-card image UI in line with repo rulesPR #2 (feat/add-image-ui, by phananhlinh144) turns setup role rows into flip cards with art. Add one reviewable commit per fix on top: lint/format, a11y button for the flip, pile instead of absolute, grid instead of flex, theme tokens, cn class grouping, restored WHY comments, Doctor prompt matching PR #1, villager note as a popover (not hover-only). Missing art for 7 roles left as-is per user.P0
3 weeks ago
#251
shortlink-resolver: batch-resolve short links to their yeumoney / dr.ontops linkNew Python (stdlib) CLI at personal/shortlink-resolver. Reads short links (anonlink.io, oklink2.online→vuotlink.xyz — AdLinkFly/CakePHP engine) from a file, spins the first hop's own POST /links/gosl/ API (per-visitor rotation, fresh cookie jar each link) and writes one line per input: the yeumoney link if it appears within a cycle (its url= param leaks the destination), else the dr.ontops link, else an empty line. Never touches third-party gates (toplinks/cuty/shrinkme etc. — declined).P0
3 weeks ago
#252
UBET-4338 — Re-check every market and bet surface for points (BE5 sweep)Assessment only, nothing implemented — no branch, no worktree. Reading pass over Jira UBET-4338, its four sibling tickets, and the board records from implementing them (cards #211, #226, #228, #240, #246).
TICKET. UBET-4338 "Re-check every market and bet surface for points", Task, Todo, Sprint 118, assignee Quan Vo, 1d4h estimate, parent epic UBET-4282 "In-App Currency Betting", blocked by UBET-4337. It is BE5 in tmp/UBET-4282/ticket-breakdown.md. Not an open audit: the PO asked "do we need a BE5 to sweep everywhere a market is shown" on 2026-09-08 and the answer was to make it a DEFINED CHECKLIST sequenced after BE4. The seed checklist already exists in tmp/UBET-4282/JOURNAL.md under "Survey — what breaks on market and bet read surfaces".
EPIC STATE. 4270 planning Done. 4334 Done (PR #779 merged 2026-09-11). 4335 Done (PR #781, on main at a924580b). 4336 Jira Review, PR #783 OPEN — not merged. 4337 Jira In Progress, branch feat/UBET-4337-belief-points-settlement unpushed, card #246 need_review. So two of 4338's four prerequisites are not in main; the sweep has nothing complete to walk.
CARRIED FORWARD INTO THIS TICKET (from the board):
1. Creator "fees collected" — card #246 D20 (R53) left explicitly to BE5, no code and no tests. Surface is get_creator_and_total_collected_fee.
2. Homepage blacklist — JOURNAL survey: not exists on lower(contractAddress) passes a points market, and market_homepage_contract_blacklist is keyed on contract address, so a points market cannot be blacklisted from the homepage. Compounded by card #226 D14/D23 (R10): the blacklist PK is (contract_address, blockchain_id) and every points market shares the 0x0 sentinel, so blacklisting ONE points market hides ALL of them. Card #226 D23 says this goes live the moment any real points-market row exists — 4335 is merged, so the infra token seed opens it. Never resolved by 4335/4336/4337. Possibly overlapping with 4335 D18 (R32 suppression list made an explicit no-op) — needs checking whether they are the same list.
3. get_referrer_summary silently returns zeros for points markets (left join on lower(m.contract_address) never matches the sentinel). JOURNAL calls it "probably correct, but it should be a deliberate answer, not an accident". No decision recorded anywhere since.
4. Resurrection first activation — card #228 D17 (R18): the resurrection twin hook is PRODUCTION-DORMANT because nothing can move a points market off Open until 4337 lands. 4337 gives points markets a close, so that path fires in production for the first time inside 4338's window.
5. Deadline disappearance — card #226 D22: a points market silently vanishes from home and search once its deadline passes (get_home_markets open/closed clause unsatisfiable), root cause "no settlement path". Deferred to 4335, still unverified. 4337 supplies the settlement path; the sweep should confirm it actually fixed it rather than assume.
6. Stranded-bet sweep — chain of deferrals ends unconfirmed: card #240 D52 dropped the EVM-only filter on update_orphaned_bets ("belongs to 4337"), card #246 D27 then decided no points guard is needed because atomic settle leaves nothing stranded, marked "pending user confirm".
7. Collateral-token id collision — card #226 D21: the check that the seeded BP token id does not collide with copyMarketsConfig.sourceCollateralId/targetCollateralId was never performed. Belongs on an infra checklist, not code.
FRONTEND — the whole other half, and no tickets exist for it. Card #211's nextAction still reads "create the 3 FE tickets if they should be tracked separately"; FE1-FE4 are drafted only in ticket-breakdown.md. Recorded FE breakage:
- Card #226 D4: an unknown chain id throws at render in ChainDropdownItem/AnonymousChainButton with no error boundary, breaking chain switching for ALL users on ALL chains. Card #226's nextAction says flipping beliefPointsConfig.enabled on testnet is exactly what makes this real.
- Card #226 D20: Token.maxBetSizeWei is typed non-nullable and the FE does BigInt(token.maxBetSizeWei); 4334 emits null for BP, and BigInt(null) throws (probe-confirmed) in MarketOutcomeAmountInput. A second, distinct crash site.
- CHAIN_ICONS has no fallback.
- The chain dropdown does not work when logged in at all: ChainDropdownItem calls setAnonymousChainId and never wagmi switchChain, while four resolution sites (HomePage, RecommendedMarkets, ActivitiesSidebar, server getInitialChainId) read `isAuthenticated ? wagmiChainId : anonymousChainId`. A logged-in user can never reach the points chain.
- Card #228 D6: chain-aware search is backend-only; features/search/fetches.ts still sends no chainId. Deferred to an FE ticket that was never created.
ALREADY DECIDED — the sweep must NOT re-raise these:
- Points bets excluded from every leaderboard bet stat, wins/losses/volume/profit (card #240 D25), and from /activitySummary volume (D12).
- Stake source type left out of every per-bucket leaderboard figure, so buckets stop summing to the headline while a stake is open (card #240 D8).
- Betting both twins of a spec overwrites the public vote with the latest bet's outcome (card #240 D10, regression-tested).
- Creator "my markets" shows a prediction twin as Pending because the winner lives on the money market (card #246 D46, user call, out of scope).
- Weekly board cross-week effect accepted (card #246 D20, R50).
- The chain is a hard partition: a user on BNB sees neither points markets nor their own points bets in history. Accepted deliberately.
- Amount formatting needs no work: the FE uses viem formatUnits(value, token.decimals) in 7 files and the BP token is decimals=6.
- Belief-points markets DO get their own generated SEO image (card #228 D40 dropped the exclusion) — a render surface worth walking, not a gap.
WATCH: card #228 D20 made the weekly market ranking money-markets-only, but card #240 D51 later removed the kind='Evm' filter in generate_market_spec_points so points bets DO raise a question's ranking score. Check those two still mean what was intended together.P0
3 weeks ago
#255
UBET-4297 follow-up: fix profile SEO capture (capture by alias + wait for .preview-content)Production bug in the shipped UBET-4297 profile capture (card #224). All 6,620 captured profile images in prod are junk (blank, loading skeleton, or 404 page). FE #730 (UBET-4273) removed numeric-id profile URLs and added a .preview-content marker that only renders once the profile has loaded, plus scripts/capture-seo-images.mjs showing the intended capture: /@<alias>?preview=true, waitForSelector(".preview-content"), element screenshot — with a comment that BE #778 should switch to it. The backend never switched. This card makes seo_image_generator match that. Post-deploy (operator, not code): delete from user_seo_image and user_seo_image_attempt to re-queue everyone.P0
upredict-backend·fix/UBET-4297-profile-capture-preview-content3 weeks ago
#256
RISE-15828 — write tech-debt descriptions for epic RISE-15475 (org type/status sources, visibility sync consumer, DF removal)Docs-only task. Draft reviewable .md descriptions for tech-debt epic RISE-15828 (follow-up of epic RISE-15475 "Organization type, Organization Relationship Alignment between SM and RSC"):
- RISE-15829 — Org Status / Org Type read from 2 sources (CDC tables vs organizations table); pages Activation List, Assessment page.
- RISE-15830 — [Assessment Visibility] Org Sync Consumer: refresh assessment_orgs_visibility + document the message contract.
- RISE-15831 — Remove DF supplier_management_attributes_rsc, especially on Request Assessment page.
Plus: suggest other tech debts found in the epic's code, review reports (mr-6437, mr-6434, mr-7217) and decision logs (tmp/RISE-15476..15756). Inputs: cards #168 #183 #186 #193 #210 #221 #235 #237 #245 #250. Output folder: tmp/RISE-15828/.P0
2 weeks ago
#257
RISE-15756 follow-up — the Standard owner's own dark features decide the org type/status restriction (reverses AC3)Follow-up to card #250. The gate subject moves from the ecosystem owner to the Standard's owner organization, judged on that org's OWN dark features (no ecosystem hop). Plan: tmp/RISE-15756-standard-owner/implementation-plan.md (13 behaviors). Operator decisions 2026-09-18: subject = standard owner itself; scope = only surfaces epic RISE-15475 touches; activation/cron = activation owner's DF for the cohort, standard's rules on top; FE = relax grantedFeaturesForEcosystem authz for dark features only; no standard in request = keep today's ecosystem-owner rule for smType/smStatus/isInactive. Lands as more commits on chore/RISE-15756/df-gate-precedence (one MR).P0
2 weeks ago
#258
Quant: test the copy-trade TP-ladder geometry (+0.5/1.0/1.5% scale-out, -0.8% stop, 4h cap)Operator copy-trades a leader on Binance perps at ~100x: TP at +50%/+100%/+150% of margin, SL at -80% of margin, fees ~10% of margin per round trip. Translated to PRICE space that is TP +0.5%/+1.0%/+1.5%, SL -0.8%, round-trip cost ~10-12 bps — and the fee figure independently confirms ~100x taker fills.
WHY THIS IS NOT ALREADY REFUTED: the live paper accounts 4/5/6 are `mean_reversion` lookback 60/240, entry_z=1.5, exit_z=0.0, take_profit_pct=0.0 — they exit on reversion to the mean, a target of roughly 15 bps, below the ~19-24 bps cost line that docs/research/ml-v1-improvements/04-frequency-and-fees.md says you must clear. The leader's targets are 50-150 bps, 3-10x larger. Accounts 4/5 losing ~13 bps/trade does NOT refute the leader's geometry; it confirms the cost doc.
MEASURED (2026-09-21, scratchpad, real 1m bars 2020-01..2026-05, entry every 60m, hold<=240 bars, SL-wins-intrabar):
- ZERO-SKILL entry: gross +/-0.1 to 0.3 bps per trade on BTC/SOL/DOGE, i.e. the ladder is a martingale. Net = -12 bps all-taker, -8 bps with limit TPs. The exit geometry creates NO edge.
- Outcome mix BTC long: stopped 35.1%; rungs hit 0/1/2/3 = 52.9/23.4/10.6/13.1%.
- Oracle (always picks the better side) = +53 bps BTC, +68 SOL, +64 DOGE. Anti-oracle mirrors it.
- BREAKEVEN DIRECTION ACCURACY: 61.4% BTC / 58.5% SOL / 59.4% DOGE all-taker; 57.7/55.6/56.3% with limit TPs. Repo's best measured OOS direction accuracy is 54.3% (Tier-3 v0).
LIQUIDATION CATCH: at a flat 100x with BTCUSDT tier-1 mmr 0.4%, liquidation sits at -0.6% price (-60% of margin), INSIDE the -0.8% (-80%) stop — so at true 100x the stop can never fire on a fresh position; liquidation closes it first. An 80%-of-margin stop only becomes reachable below ~50x, or after a rung is banked and realized profit pushes liquidation out. Any honest test must model liquidation, not just the stop.
CAPABILITY GAP:
- Backtest: engine/core.py resolves ONE stop + ONE target intrabar and closes the FULL position (_resolve_intrabar). No partial scale-out. Signal.intent already carries add/close_all for LadderEngine (scale-IN); a reduce/rung-aware exit is the missing piece. No leverage/liquidation in the single-instrument engine.
- Paper: closer. mean_reversion_adapter already has order_type=limit, market=perp, maker/taker fee split, trail_bps, max_hold_minutes; account 7 proves limit-on-perp works live at 1m cadence. Needs TP-ladder + SL params + margin/liquidation (wallets.py has the primitives).
Scripts: /private/tmp/claude-501/-Users-quanvo-Documents-git-repos-personal/2e15dc2b-acb8-4064-aeb2-293ab4d38a87/scratchpad/ladder_null.py and ladder_skill.py. Related cards: #198 (paper engine), #45 (100x leverage research), #73 (minute-level go/no-go).P0
2 weeks ago
#259
RISE-15560 — AI Autofill from Network Profile: entry point + 3-step modalOrchestrated-feature-dev run for RISE-15560 "Select AI Autofill from Network Profile" (Story, BACKLOG, epic RISE-15559, DF `release_autofill_assessment_AI_phase3`). Repos: rs-backend + rs-frontend.
SCOPE: the entry point and the 3-step modal only. AC 1 adds "From network profile" above the 2 existing options on the "Auto-fill assessment" button, shown when the executor org has a Network Profile. AC 2 opens the modal directly when executor org = assessed org; AC 3 interposes a warning dialog when they differ. AC 4 is the modal: step 1 picks data-only (default) vs data-and-documents, step 2 runs the AI analysis and blocks advancing if nothing was found, step 3 applies and reports "X questions answered" per RISE-15252.
NOT in scope: RISE-15561 (AI insight badge / section attribution), RISE-15562 (Mixpanel), RISE-15652 (Epic 2 certificate picker).
BUILDS ON SPIKE RISE-15634 (card #229, staled). Its decisions S1-S13 are locked inputs, mirrored into tmp/RISE-15560/CONTEXT.md: serialize the NP into 5 section JSON files in GCS and feed them to `rise-document-intake` as documents (no Data Science change needed); read all 5 sections from CDC `cdc_passport_be` and extend the sink, with the live NP API explicitly rejected; copy NP files into the RSC bucket rather than requesting a cross-bucket grant; exclude rt=9 and rt=12 question types. Feasibility is proven — 18/18 answerable questions correct at confidence 1.0 on the real staging service — and the ticket's embedded dev note ("check if we are able to do Step 1") is already answered YES.
TWO BLOCKERS on AC 1, both asked by Will in a Jira comment on 2026-09-10 with no reply since: (1) what counts as "has a Network Profile" — a row exists, or a row with data in it; (2) whether the phase-1 and phase-2 dark features are also required to show the option, or whether phase-3 alone is enough. The second appears nowhere in the spike docs.
KNOWN INFRA GAP: `ecosystem_organization_document`, the four capacity tables, and the remaining capability child tables are not in the CDC sink. Each addition is Infra-gated and backfill is Infra-only. Certifications, Documents and Capacity sections cannot be fully populated until they land.P0
2 weeks ago
#262
Infra release 20260922.2 to testnet — add the points-settlement migration and belief-points fee configupredict-infra PR #784 "Upgrading testnet to tag 20260922.2" (branch deploy-20260922.2-to-testnet, base main) currently changes only ci/configs/testnet/pipeline-config.json. Tag 20260922.2 = backend 4c5c1f5b [UBET-4338] (#790), which sits on top of 3fe94b96 [UBET-4337] (#785) — testnet is on 20260922.1 = 5c38cca9, so this release carries BOTH settlement and the surface sweep.
Two additions needed:
1. MIGRATION — 20260915000000_add_points_settlement.sql is staged in upredict-backend/migrations/ but absent from Terraform/testnet/postgres/migrations/ (testnet stops at 20260913000000_add_market_bet_user_id_and_points_bets.sql). It drops NOT NULL on market_result.commitment and adds five point_ledger_source_type_enum values (BetPayout, BetRefund, CreatorFee, ReferralFee, TreasuryFee). Must re-run `atlas migrate hash --dir "file://."` after copying. UBET-4338 itself adds NO migration — its only schema change is a view function, which ships with the wholesale sql_schemas deploy.
2. CONFIG — config/testnet/belief_locker/belief_locker-config.yaml already has "beliefPointsConfig": {"enabled": true} on main and on the release branch. Missing are the fee rates. User's call: "same as money market". Money fees are not config at all — they are stamped per-bet by the contract and read off the PlacedBet event, so the rates were read from the testnet DB: the live band since 2025-12-10 is creator_fee_percentage_decimal 10000, operator_fee_percentage_decimal 4000 (earlier bands 1000/4000 and 0/0). Operator fee is the money-side equivalent of the points platformFeePercentageDecimal. treasuryAddress to be omitted: its default is the money chains' shared defaultReferralReceiver, which is 0xbB1a40cE9a9570af2137C7f6489178689A4736c7 on both testnet chains.
Known consequence, already accepted by the user (enabled:true was set by them before this session): the testnet frontend has not shipped its belief-points side, so the chain switcher will show a blank-icon entry and an anonymous user selecting it can hit a render crash in the bet-amount input (BigInt(null) on maxBetSizeWei).P0
2 weeks ago
#263
macOS 27: repeated internet loss + Wi-Fi drops — NordVPN proxy vs iCloud Private RelayDiagnostic investigation on Quan's MacBook Pro (macOS 27.0, build 26A428, arm64). NOT a code change — machine/network troubleshooting, findings recorded for reuse. Session 2026-09-22.
REPORTED SYMPTOMS (three, initially believed unrelated):
1. "Bartender 7 kills my internet; force-quitting it restores connectivity."
2. Internet dies completely; only a reboot fixes it (3 reboots on 2026-09-22: 08:23, 10:18, plus earlier).
3. Wi-Fi ("Trung Hung 1") keeps disconnecting; forced onto iPhone hotspot; a second machine on the same AP is fine.
ROOT CAUSE (symptoms 1 + 2) — two traffic interceptors fighting:
- NordVPN registers a TRANSPARENT PROXY network extension: NESMTransparentProxySession[Primary Tunnel:NordVPN protection], com.nordvpn.macos.Shield (com.apple.networkextension.app-proxy). EVERY socket on the machine carries "flow divert" (15,898 refs in a 14-min window).
- iCloud Private Relay is ALSO enabled (com.apple.networkserviceproxy holds a 120KB active NSPConfiguration). It tunnels via mask.icloud.com.
- 83% of Private Relay connections (29,088 of 35,019) carry "flow divert" — Apple's tunnel is being intercepted by NordVPN's proxy.
- NordVPN's Shield extension constantly fails keychain access: "Failed to talk to secd after 4 attempts" — 3,092 times in 39 min (~20-24/min steady). Independent NordVPN defect.
- When NordVPN's side breaks (errno 50 ENETDOWN, "Connection failed to connect 1:50"), Private Relay cannot reach its gateway -> "mask.icloud.com:443 failed resolver" -> infinite retry.
- Those retries are issued BY mDNSResponder, so the DNS resolver saturates itself and ALL name resolution dies = "Wi-Fi connected, no internet". Does not self-recover; only a reboot clears it.
EVIDENCE (mDNSResponder log lines/min; normal ~1,500):
- Before the 10:18 reboot: 10:04=11,425; dead-silent 10:10-10:12 (resolver hung); 10:14=30,961; 10:15=34,892; 10:16=39,015; 10:17=38,893. Reboot 10:18:57.
- Before the 08:23 reboot: identical shape — 08:10=26,781, then 10,054/14,180/15,938 up to the restart.
- "Failed to talk to secd" spiked in lockstep (73 and 69/min at 08:10-08:11; 137/min at 08:20).
- Both shutdowns HUNG and were force-killed by the watchdog (shutdownStall reports), consistent with a wedged network extension.
BARTENDER IS NOT THE CAUSE (symptom 1 explained):
- /Applications/Bartender 6.app is actually v7.0.4, notarized, signed by Bartender App LLC (24J875RH8J) — genuine, not tampered.
- It has 13 entitlements, NONE network-related (no VPN / content-filter / app-proxy / packet-tunnel). It cannot touch traffic.
- It IS a trigger: Bartender launched/exited 6x in 10 min with 3 distinct LaunchServices bundle records + a Sparkle self-update. Each re-registration fires nehelper "apps installed" -> nesessionmanager RESTARTS the NordVPN proxy (12 restarts in the window) -> every diverted flow is torn down. Flow teardowns per 10s: 1,062 and 512 at restarts vs 70 baseline.
- Duplicate bundles registered: /Applications/Bartender 6.app, stale /Applications/Bartender 7.app, ~/.Trash/Bartender 6.app + 7.app, /Volumes/Bartender 6 + 7 (unmounted DMGs).
SEPARATE ISSUE (symptom 3) — Wi-Fi drops have their own causes:
- Signal was never weak: RSSI -38 to -46 dBm throughout.
- 6 link-downs 15:50-16:38. Two (15:50:47, 15:56:58) coincide exactly with DarkWake from 'Clamshell Sleep'/'Maintenance Sleep' (pmset confirms; 10 Maintenance + 4 Clamshell sleeps that day). Firmware reason: "link down due to beacon loss", state NET_MANAGER_STATE_SLEEP, trigger=dark_wake.
- After waking it re-associated to 2.4GHz channel 1 @20MHz instead of 5GHz channel 36 @80MHz. Channel 1 is saturated: crsglitch 2,804,798 (vs 4,401 on ch149); 47 own beacons vs 44 other-BSS.
- AWDL (AirDrop/Continuity) held the radio in a permanent real-time schedule: 3,258 "RTG: Active / UserTriggered" events, dwell split ~50/50 between ch1 and ch149. Missed beacons: 18,904 from AWDL, 6,608 home-channel.
WHY IT WOULD NOT REJOIN (the decisive one):
- 13:36:50 macOS ran CONFIRM BROKEN BACKHAUL PROBE -> TIMED OUT after 3.2s -> concluded the Wi-Fi had no working internet.
- 16:41:58 auto-join refused: "Known network profile with recently (<3600s) broken backhaul not allowed when already associated to PH" (PH = Personal Hotspot). macOS deliberately pinned the Mac to the iPhone.
- Plus 684 "DeferredTKIP" refusals since 16:00 — the router runs TKIP, which is the "Weak Security" warning, and macOS actively deprioritises TKIP networks.
- LIKELY LINK: the 13:36 backhaul probe failed while the NordVPN/Private Relay DNS storm was active. The second machine never got that verdict because it does not run that pair.
UNVERIFIED / LIMITS:
- SSIDs are redacted in the unified log and /Library/Preferences/com.apple.wifi.known-networks.plist is root-only, so networks were matched by channel+security, not by name. `sudo wdutil info` would confirm.
- The total DNS blackout was inferred from teardown/retry spikes, not directly observed (DNS still resolved at 10:56).
- Not read: the two shutdownStall reports (user is in _analyticsusers, so they are readable if wanted).P0
2 weeks ago
#264
Quant: carry's headline result is not reproducible — audit and re-establish it before any buildA 98-agent workflow (survey -> 6 proposal lenses -> 3 adversarial reviewers each -> synthesis) audited the one arm this program still believes in. I then verified the load-bearing claims against the code myself.
THE HEADLINE PROBLEM — "always-on carry beats B&H on BTC/ETH/LINK by 1.10/1.30/1.45 Sharpe" is NOT REPRODUCIBLE BY ANY RUNNER IN THE REPO TODAY.
- It traces to exactly one place: docs/research/carry-hedge-drag/01-result.md:50, from a single run on 2026-08-05 (baseline commit 33c9409, measurement code 071b6e2).
- VERIFIED: carry_verdict.py:272 passes always_on_sharpe into compute_verdict's BENCHMARK slot, and :444 writes bah_sharpe=result.always_on_sharpe. So that runner's question is "does the funding GATE beat always-on carry?" (answer: FAIL, gated 1.198 < always-on 2.314). It structurally cannot grade always-on against buy-and-hold.
- VERIFIED: neither src/quant/validation/rehedge_drag.py nor scripts/run_carry_verdict.py contains any buy-and-hold code at all.
- NOT a hidden defect: docs/research/carry-hedge-drag/00-pre-registration.md:56 states it outright — "Carry has never been benchmarked against Buy & Hold ... This is deliberate and documented as D17's Step 10/11 encoding, not an oversight." The workflow framed this as a discovery; it is a KNOWN, DOCUMENTED gap. What is genuinely new is that the number published to close that gap cannot be re-derived from current code.
MY OWN ERROR: I repeated "carry is the only arm that ever beat buy-and-hold" many times this session as settled fact. It rests on one non-reproducible document. Corrected to the operator.
THE NUMBER'S ERROR BAR IS MOSTLY BOOKKEEPING (per the workflow): the identical always-on arm reads -0.249 (bare test slice via _mean_baseline_sharpe), +1.20 (per-symbol non-overlapping windows), +2.31 (warm-sliced), +5.50 (zero cost). A ~6-Sharpe spread that is 100% convention and 0% market.
TWO DEFECTS I VERIFIED STRUCTURALLY IN THE CODE:
1. GROSS RAMP — engine/carry.py:104-111 sizes BOTH legs once at entry (notional = gross_per_leg * equity_open) and never resizes; the comment at :99 says matched units deliberately avoid re-trading every bar. So notional/equity drifts freely with price and equity. Agents measured BTC 0.503 -> median 1.351 -> max 2.731 (total gross 5.46x against a declared 1.00x cap; ETH 10.23x; SOL 31.16x), and de-levering flips SOL 1.348 -> -0.168 and moves BTC 4.232 -> 3.790. MAGNITUDES NOT INDEPENDENTLY VERIFIED BY ME — the structural cause is confirmed, the numbers are agent-measured via scratchpad scripts (measure_gross_ramp.py, measure_collateral.py).
2. F5 ENTRY FILL — always-on sets pending_on at bar 0 and fills at bar 1 of the WIDENED panel, inside the warm prefix carry_verdict then slices off, so its entry cost never lands in reported returns. Repo's own estimate: +0.4 to +1.0 Sharpe per fold. Documented at docs/research/structural-edges-audit/flaws-to-fix.md:76-82. NOTE: that file lists F5 among items "fixed via meaningful-red TDD", but the fix was to RELABEL 2.314 as "frictionless", not to charge the fill — the behaviour still stands.
3. COST NEVER PRICED FOR CARRY — run_carry_verdict.py hardcodes CostModel() with no fee flags, CarryEngine charges ONE CostModel to BOTH legs, run_multi_carry_verdict.py exposes no cost knobs. No carry verdict has ever been priced at the verified futures-taker schedule (spot 10 / futures 5 bps). Agent reconstructions (UNVERIFIED, hypothesis only) put the 9-leg basket at -0.575 -> +0.93..+1.12 and the mean-of-9 baseline at -0.249 -> +0.91 at 14 bps, with the diversification lift turning positive — which would reopen the basket refutation on cost grounds.
DSR IS THE WRONG INSTRUMENT HERE: n_trials is hardcoded to 1, deflation_applied needs >=5, and B&H itself scores DSR 0.0000 at n_trials>=10 at 1h. Use a paired block bootstrap of the DIFFERENCE (carry minus B&H on the common index), block length swept at funding-regime scale (336/720/1440 bars, not the ML default 24), and declare DSR inapplicable with the dated_carry_verdict precedent. Publish block-length sensitivity, not one number.
HONESTY NOTE worth carrying into any write-up: in a coin-matched delta-neutral book the spot gain IS the perp mark loss, so a 1x liquidation forfeits ~25 bps of equity and leaves a naked spot leg, not a wipeout. 1x breach count on BTC/ETH/LINK is 0/1/1 folds out of 109 — a caveat, not a retraction. At 3x it is much worse (see card #198's liquidation table).
Full synthesis: /private/tmp/claude-501/-Users-quanvo-Documents-git-repos-personal/2e15dc2b-acb8-4064-aeb2-293ab4d38a87/tasks/wj39dd7cd.output (98/98 agents, 8.7M subagent tokens). Related: #258 (ladder/minute-frame refutation), #198 (paper-trading ops audit).P0
2 weeks ago
#265
UBET-4345 AI comment moderator — quality gate for points + gibberish filterJira UBET-4345 "AI comment moderator" (Task, Todo, Sprint?, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-3691 "BM - Our Own Comments"). Ticket body is 3 lines: (1) decide whether to give points or not, (2) if it is not a word but random characters don't allow to display, (3) judgment criteria — meaningful? / gets conversation going? / super emotionally stimulating?
CURRENT STATE (BE, read pass done): OpenAI is the only LLM vendor in belief_locker. Comment path = synchronous OpenAI Moderation API (omni-moderation-latest) in commentLlmService.ts, called from routes/commentOnMarket.ts before any write; flagged categories (default hate, self-harm) reject with MARKET_TEXT_MODERATED 400. Fail-open on any API error. Market path = marketLlmService.ts does moderation + gpt-4.1-mini translation (JSON schema) + text-embedding-3-small embedding, sync at create and via FetchTranslationsTask. Images = AWS Rekognition DetectModerationLabels. Belief points for comments are decided by pure SQL (appSql/get_comment_ledger_decision.sql) on structure only (first reply per author/market, first credit-worthy interaction per market) — no content signal. market_comment has NO hidden/moderated/score column, so there is no way today to store a comment but suppress its display.
Running the orchestrated-feature-dev pipeline; workspace upredict-backend/tmp/UBET-4345/. Sibling card #194 (UBET-4241 comment sorting) is the same epic but a different ticket.P0
2 weeks ago
#266
Quant: measurement-stack defects — DSR var_trials input, carry fold geometry, corrupt LINK barFrom a 74-agent workflow on legitimate ML/TA uses. The headline was not an ML finding — it was that the measurement stack is mis-reporting things. I VERIFIED the two most consequential claims against the code and data myself; the rest are agent-measured and flagged as such.
1) DSR var_trials IS FED THE WRONG VARIANCE (verified by me, structural):
- carry_verdict.py:263, multi_carry_verdict.py:374, ladder_verdict.py:411, ml/prediction/walk_forward_ml.py:341 all pass statistics.pvariance(fold_sharpes)/bpy — the fold-to-fold variance of ONE strategy.
- sweep.py:116 passes statistics.pvariance(result.all_oos_sharpes)/bpy — variance ACROSS TRIALS, which is what Bailey/Lopez de Prado's expected-maximum term wants.
- walk_forward_ml.py:339 has a comment claiming it mirrors sweep.py. It does NOT — fold_sharpes (one config, many folds) is not all_oos_sharpes (many configs). That false equivalence is probably how this survived review.
- WHY IT MATTERS: fold-to-fold Sharpe variance for a single strategy is large, so feeding it as across-trial variance inflates the expected-max hurdle and crushes DSR toward zero. This is consistent with the recorded "B&H itself scores DSR 0.0000 at n_trials>=10 at 1h" symptom — i.e. the DSR-unfireable finding may be an ARTIFACT OF THIS INPUT, not a property of the 1h interval.
- Agent re-run (NOT verified by me): with across-trial variance the gate grades normally at 1h — DSR 0.914 / 0.727 / 0.096 at n_trials=32 for across-trial sd 0.3 / 0.5 / 1.0.
- BLAST RADIUS: every DSR-gated verdict in this program was read through this input. The z-score ladder arm was failed on DSR 0.930 <= 0.95. Re-read all of them after the fix.
- Memory quant-trading-dsr-gate-unfireable.md has been annotated so a future session does not treat it as settled.
2) CORRUPT BAR IN THE STORE (verified by me, exact):
- linkusdt 2020-03-12 10:48:00 UTC has low = $0.0001 against open 2.1372 / close 2.20. Exactly one such bar across LINK; SOL has none by the same screen (low<50% or high>200% of close).
- engine/core.py _intrabar_hits tests `bar.low <= stop` for a long, so EVERY LINK backtest carrying a long stop has been spuriously stopped out on that bar, and the triple-barrier labeller touches the same low.
- Agents also claim SOL's carry leg shows 67 bars above 100 bps and a max single-bar move of 1,459.9 bps — that is a BASIS/desync claim, not a raw OHLC anomaly, and my screen would not catch it. UNVERIFIED.
- Fix: an outlier guard in data/store.py rejecting a bar whose log-range exceeds a large multiple of its trailing median.
3) CARRY FOLD GEOMETRY CHARGES A ROUND TRIP A LIVE HOLDER NEVER PAYS (agent-measured, NOT verified by me):
- multi_carry_verdict.py:191 runs each fold on the bare test_idx with fresh cash and liquidate_at_end=True, so all 18 legs open and close every 500 bars, 95 times.
- Claimed size: ~24 bps/fold of forced churn against ~26.9 bps/fold of carry income — the harness cost is ~100% of the strategy's revenue. Same BTC arm reads +2.31 at test=500 and ~+5.10 at test=8000 with nothing else changed.
- Combined with F5 (always-on's entry fill lands in the discarded warm prefix and is free, while the gated arm pays every toggle inside the scored window), the two carry arms are scored under DIFFERENT cost regimes. See card #264.
4) CARRY HAS NO MARGIN MODEL (agent-measured, NOT verified by me):
- CarryEngine's only guard is equity <= 0, which a delta-neutral book can never trip. paper/wallets.py:50 already has liquidation_price = entry * (1 - mmr + 1/leverage) and dated_adapter.py:263 already enforces it.
- Claimed: 12/97 SOL folds, 8/109 LINK, 3/109 ETH, 1/108 BTC cross the liquidation price today and still report a finite Sharpe. At a fixed 1.0x gross the book IS fundable with zero in-sample liquidations (max perp-leg leverage BTC 2.61x, SOL 1.23x, AVAX 1.11x). Repo DEFAULT_LEVERAGE = 3.0 liquidates on a +32.83% rally, which BTC/SOL/AVAX all exceeded — consistent with my own independent measurement on card #198.
- Also: CarryConfig.__post_init__'s 2*gross_per_leg <= 1.0 check is a construction-time assert on a config field; the live book allegedly breaches it by up to 27x on SOL. Should be a runtime invariant in the engine loop.
5) THE ONE REAL ML/TA WIN (agent-measured, NOT verified by me): Parkinson range volatility sqrt(mean(ln(high/low)^2)/(4 ln 2)) beats the incumbent close-to-close pstdev on Spearman 9/9 AND QLIKE 9/9 across the 9 coins at 1h (BTC rho 0.6068 vs 0.5816; QLIKE 19% lower). An EWMA(0.94) control wins Spearman 9/9 but LOSES QLIKE 8/9 — so the gain is the RANGE, not the weighting. Information argument (high/low are order statistics the close discards; Parkinson 1980 ~5x efficiency), not a pattern claim. Path to P&L is indirect: it sharpens every sigma-consuming component.
ORGANISING RULE the workflow extracted, worth keeping: every construct that survived on this data predicts a SECOND MOMENT or a mechanical identity; every construct that died predicts a SIGN. Second moments are conserved and observable; signs are competed away.
Full output: /private/tmp/claude-501/-Users-quanvo-Documents-git-repos-personal/2e15dc2b-acb8-4064-aeb2-293ab4d38a87/tasks/wemf5ao6x.output (74/74 agents, 7.5M subagent tokens). Related: #264 (carry credibility), #258 (minute-frame refutation), #198 (ops).P0
2 weeks ago
#267
Quant: order-book depth + cascade absorption — free data exists, but the feed lies during cascadesOperator proposed using bid volume as a signal, tied to cascade absorption. 79-agent workflow (6 survey angles -> 3 adversaries per candidate -> plan). 78/79 agents, one TLS drop on a candidate that still got 2 of 3 votes. I verified the data-availability claims myself.
HIS IDEA IS GENUINELY NEW INFORMATION, NOT A REPEAT. Spearman(depth imbalance, taker_buy ratio) = -0.025 on 519,433 joined BTC minutes. taker_buy_base_volume (aggressor flow) is already a feature in every failed direction run (config.py:93/98/132-134); resting depth is a different quantity.
DATA AVAILABILITY — I VERIFIED THESE AGAINST THE LIVE HOST:
- futures/um/daily/bookDepth: 2023-01-01 -> 2026-09-21, LIVE. ~470KB/day, 0.59GB BTC full history, ~5.6GB for 9 coins. (My first listing hit the 2000-key cap and looked like it ended 2024-05-17; paginating properly shows it is current. Watch that trap.)
- futures/um/daily/bookTicker: DEAD ARCHIVE — exactly 320 files, 2023-05-16 to 2024-03-30, then Binance stopped. 53GB for BTC alone. Do not build on it.
- futures/um/daily/liquidationSnapshot: DOES NOT EXIST for USDⓈ-M (zero keys). Exists only for COIN-M and is discontinued. There is NO forced-liquidation ground truth for the market he trades.
- futures/um/daily/metrics: OI + 3 long/short ratios at 5-min cadence, BTC from 2020-09-01 (others 2021-12), 0.19GB for all nine. Cheapest dataset, and the one that bears on carry timing.
- futures/um/daily/aggTrades: 2019-12-31 -> now, ~18MB/day, 44.7GB/symbol full, ~3.6GB if only cascade days.
- Ingestion measured on this machine: 120 bookDepth files in 12.3s at 10-way parallel; 2,736 metrics files in 30.5s. Bandwidth is not the constraint. binance_dump.py needs a _days() generator + daily loaders + a long->wide pivot; store.py read_store hardcodes OHLCV + RAW_EXTRA.
WHY DEPTH DOES NOT DELIVER (agent-measured, not verified by me):
- It is NOT an order book: 10 rows per snapshot, every ~30s, CUMULATIVE notional within +/-1/2/3/4/5% of mid. No price levels, no queue, no top-of-book. At BTC $110k the tightest band is $1,100 wide. The +/-0.2% near-touch band only appears ~2026-01-15, so near-touch designs have 5.5 months of single-regime data.
- GEOMETRIC TRAP: the band is measured off the CURRENT mid, so a price move slides the window along a static book. Spearman(bid-depth change, 5m return) = -0.53, ask = +0.51 — near-perfect mirrors. Bid depth RISES as price falls. A naive study measures a coordinate system, not demand.
- Economically hopeless at 30s-60m: raw depth-imbalance IC +0.012/+0.027/+0.042/+0.049 at 1/5/15/60m, collapsing to +0.008-0.013 after controlling for past returns — ~80% is restated short-horizon mean reversion, already killed by the 36-config TA sweep. Decile spread of forward 60m return +2.34 bps, non-monotone, vs a 10-12 bps round trip. Causal form (rolling z, |z|>1, h=60m, n=183,087): +0.57 bps gross.
- Adds nothing to vol forecasting: past-60m RV predicts forward-60m RV at +0.79; depth's incremental contribution after residualizing is -0.012.
- Cost model correction runs AGAINST us: live walk-the-book at $50k gives BTC 0.006 bps, ETH 0.018, SOL 0.43, DOGE 1.3-2.1, LINK 3.2-4.9, AVAX 3.5-5.1 vs the 2.0 bps/leg assumed in costs.py. At $200k LINK/AVAX are 9-12 bps/leg. Sizing constraint on alt baskets.
- CAPACITY IS A NON-ISSUE: the +/-1% bid band holds $17.9M at its 1st-percentile thinnest and ~$120-190M typically. A $200k clip is 0.1-1% of the thinnest book.
THE FEED LIES EXACTLY WHEN IT MATTERS — the single most important finding here:
- On 2025-10-10 (largest liquidation cascade on record) the bid series PINNED at exactly $2,142,547.09 / 17.652 BTC for 379 consecutive snapshots = 189 minutes, straight through the 21:19 crash, while the ask side updated normally.
- A frozen LOW value reads as a maximal liquidity vacuum — THE ARTIFACT CONFIRMS THE HYPOTHESIS. Multiple independent passes found "77x liquidity withdrawal" and it was a stalled feed.
- Not a one-day problem: 10.67% of 2025 BTC snapshots repeat the previous value to the cent; 2025-04-16 -> 2025-05-18 (34 days) has exactly one distinct value per band per day.
- MANDATORY LOADER RULES: drop runs of >=3 identical values before anything else; parse `percentage` as Float64 (written "-5" before ~2026-01 and "-5.00" after, which raises a polars ComputeError on Int8).
CASCADE ABSORPTION — latency is genuinely fine, adverse selection is brutal:
- Latency NOT the problem (measured on real aggTrades 2025-10-10 and 2024-04-13): price dwelt below a -5 bps limit for 7 to 300 SECONDS with $0.33M-$1.8B of resting-bid-hit notional below it. 60-90ms is 2-4 orders of magnitude inside that.
- Aggressor imbalance does NOT detect a cascade: through the 2025-10-10 peak aggressive-sell share ran 50-60% vs a 0.501 day mean — price fell 5% in a minute on roughly BALANCED flow. What spikes is INTENSITY: prints/sec 6 -> 1,000-3,000, makers consumed per sweep 8 -> 127. Cascades are violence, not one-sidedness.
- SITTING ON THE BID IS WORSE THAN TAKING: limit 0.5% under the signal close returns +58.7 bps at H60; plain market buy +62.3; events where the limit NEVER FILLED returned +137.4. You get filled precisely when the flush continues. Adverse selection, quantified.
- WINDOW OVERLAP is the largest error in every cascade number so far: at a 0.5% wick BTC goes from +52 bps (t=6.4) to +7 bps (t=1.0) once de-overlapped to one position per 60 minutes.
- REPORTING MEDIANS is the second largest: at a 10 bps offset over 2,241 fills the median is +5.83 bps and the MEAN is -1.36; removing the 5 worst days flips it to +0.98 — and those 5 days (2021-05-19, 2020-08-02, 2020-05-10, 2021-04-18, 2021-09-07) ARE the actual cascades. You buy ordinary dips and get run over by the real ones.
- A STOP-LOSS DESTROYS IT: -5%/H60 goes from +121.3 to +42.2 bps gross and 66% -> 44% win rate with a 3% stop. The edge requires holding through adverse excursion => no meaningful leverage.
- SURVIVORSHIP IS HORIZON-DEPENDENT: alive-9 vs dead-4 mean forward return H15 +27.8/+19.6, H60 +46.9/+36.2, H240 +78.3/-16.2, H480 +99.7/-30.4. The short-horizon effect survives; the LONG-horizon effect is ENTIRELY survivorship.
- LUNA disproves the "liquidity filter saves you" defence: on 2022-05-09, the day before the death spiral, LUNAUSDT was the 3rd most liquid USDT perp by trailing-30d dollar volume, ahead of SOL/XRP/DOGE/BNB. Any live filter includes it. Worst name in the study at -242 bps mean, -71% worst event.
- LUNA and FTT PREDATE bookDepth (May/Nov 2022 vs a 2023-01-01 start), so depth data structurally CANNOT see the two observations that matter most. Run the survivorship bound on klines.
- The true delisting cohort is 31 USDT perps (most of the apparent 134 are BUSD retirements or renames like MATIC->POL); 26 are already downloadable. data.binance.vision does not delete delisted symbols.
BUILD ORDER (inverted on purpose — do not download first):
1. ZERO-DOWNLOAD precondition test, an afternoon, no bytes: ungated cascade fade (-3%/-5% 15-min drop) on the perp klines already on disk plus the 26 delisted symbols, de-overlapped to one position per horizon, entry at next bar open, H in {15,60}, 2023-01-01 onward. Report the MEAN (never the median), the worst single event, and a day-block bootstrap over distinct calendar days (8,294 trades sit on only 995 days; 25% fire in hours where >=7 of 9 coins move together). KILL: if the 95% day-block CI net of 10 bps does not exclude zero, the family is closed and no order-book data can rescue it. EXPECT IT TO FAIL — the best existing measurement is gross +19.26 bps, day-block CI [+5.5,+33.3], net at 10 bps [-4.5,+23.3], already a failure.
2. Only if (1) passes: aggTrades on ~300 cascade days (~3.6GB, ~12 min) to price the FILL. The entry minute's median high-low range is 166 bps and the whole claimed edge is 14-50 bps, so where inside that minute the order lands decides everything. A mild adverse-fill assumption already turns the ungated arm from +14.2 to -17.9 bps. KILL: realized one-way cost on DOGE/LINK above ~6 bps and it is dead at any gate strength.
3. Only then bookDepth, and only as a SELECTOR conditional on (1) and (2) being net-positive — never as a standalone predictor. Mandatory: drop >=3 identical-value runs, Float64 percentage, and residualize every depth change against the contemporaneous return before use.
Full output: /private/tmp/claude-501/-Users-quanvo-Documents-git-repos-personal/2e15dc2b-acb8-4064-aeb2-293ab4d38a87/tasks/wg73vqmoc.output (9.1M subagent tokens, 2,233 tool calls, ~15GB downloaded to scratchpad). Related: #266 (measurement-stack defects), #264 (carry credibility), #258, #198.P0
2 weeks ago
#269
Feature-set expansion: TA family ablation + open-interest/funding as ML featuresOperator challenged the 2026-09 audit's narrow scope: the copy-trade work tested 4 signal shapes x 3 lookbacks, and the production ~30-feature set was never ablated. Three steps, approved in order:
1. Ingest Binance UM `metrics` (open interest + 4 long/short ratios, 5-min cadence, ~0.19 GB/9 coins) and join funding into the feature matrix. Funding has been on disk since 2020 but was only ever a carry TRIGGER, never a predictive feature.
2. Widen the TA library (bollinger, stochastic, adx, volume_flow/OBV/MFI/VWAP/Amihud, channels, oscillators, persistence, range_vol) and ABLATE — learn which features carry anything rather than adding to an unmeasured pile.
3. Score on direction AND forward volatility. Second moments are the only thing measured to work here (Parkinson beat the incumbent estimator 9/9 coins).
Run at 1h, not 1m: at 1m the 58% direction bar comes from the fee, not the features.
Built so far: `data/store.py` load_metrics_csv + METRICS_COLUMNS; `scripts/pull_metrics_data.py` (daily, parallel, resumable); `scripts/research/ta_features.py` (8 families); `scripts/research/feature_sweep.py` (ablation harness, de-overlapped trades + block-bootstrap CI); `tests/research/test_ta_features.py` (generic causality property, mutation-verified).P0
2 weeks ago
#270
Local e2e: a user plays Belief Points markets through the FE against the local docker BEPull latest main and stand up a full local flow where users play Belief Points (BP) markets entirely through the FE (https://localhost:3001) against the local docker BE (Postgres + anvil, beliefPointsConfig on). Only users are seeded. Social login is faked by minting credentials with the same signing method the BE verifies. Markets are created through the real create API with a local OpenAI stub. BE worktree upredict-backend-bp-e2e (branch feat/bp-e2e-local off origin/main b2999432) carries the re-applied local-chain tooling from card #81/#82 (scripts/local + per-chain rpcUrl override). FE main checkout fast-forwarded to f855e9ce.P0
2 weeks ago
#274
UBET-4363 — Stop the frontend guessing about points from backend responsesThe four backend changes promised on FE PR #738 (decided as D51-D54 on card #252): /chain returns chainKind; create-market rejects the Belief Points token and token/chain mismatches; a dedicated error code for settling an already-settled market; chain-agnostic notifications where each item carries its chain and market id. Run via feature-dev-lite in a new upredict-backend worktree from latest origin/main.P0
upredict-backend·feat/UBET-4363-points-contract-cleanuplast week
#275
LMS: make AI (Gemini) failures visible and diagnosable in telemetryIn /Users/quanvo/Documents/git-repos/personal/lms. Audit found AI integration is traced (gemini.* + action.* spans) but: (1) invisible failures — no timeout so hung Gemini calls lose their span; client-side PDF/docx extraction errors are uncaught and never reported; (2) undiagnosable — no finishReason, no raw reply on schema failure, no error category, console.error lines have no trace id; (3) no quality/cost signals — returned-vs-requested count, unknown/duplicate ids, question count, reasoning/cached tokens, response model id, teacher override on apply. User wants (1)+(2) handled and (3) recorded once per request as one object. Alerts (item 11) out of scope.P0
last week
#279
UBET-4348 — Give 10 BP to new users after register + category interest selectionOrchestrated-feature-dev run for Jira UBET-4348 "Give 10 BP to new users once they register and complete the category interest selection" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-4282 "In-App Currency Betting"). NO description and no comments in Jira — requirements derived from code + epic context. Workspace: workspace/tmp/UBET-4348.P0
last week
#285
Plan + build DSA track for competitive programming (Python + C++) — divide and conquerNext after Files, Sorting & Records (card #241). Operator decision 2026-09-27: skip curriculum modules 9 (exceptions) and 10 (std library); move to data structures & algorithms for competitive programming.
Track order: (1) binary search (loop, no recursion) → (2) recursion → (3) mergesort → (4) quicksort. One lesson per algorithm, matched Python + C++ handouts, problem-first method, web step-through animations like #241. Two-phase: manifest first, wait for approval.P0
last week
#286
UBET-4353 — Point system update: no BP for betting interaction, commentator reaction/reply = 1Orchestrated-feature-dev run for Jira UBET-4353 "point system update" (Task, Todo, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-3870 "Leaderboard + BM point system"). Ticket asks: (1) make sure no points are given for betting interaction to bettors — betting interaction is a way to tax points from users, not distribute them; (2) reduce reaction and reply points for the commentator to 1. Repo upredict-backend. Workspace workspace/tmp/UBET-4353. Related open work: card #265 (UBET-4345 AI comment moderator, uncommitted, touches comment points).P0
last week
#290
Sep 27 + Oct 4 Tests — Files, Sorting & Records §0–9 (20 MC + 10 file I/O each)LMS test data file lms/scripts/data/data-9-27-2026-sep-27-test.ts, following the Sep 13 test (card #243): 20 misconception MC (weight 2, ~2 per lesson section 0–9, Python + C++ snippets give the same answer), 10 read → process → write coding problems (B1–B7 w4, B8–B10 w6), 86 points, bilingual EN/VN. Scope: the whole Files, Sorting & Records lesson incl. tuple/pair records and ex8–ex10. No tied scores anywhere (C++ sort is not stable).P0
last week
#291
RISE-15561 — View AI auto-filled results from Network Profile in the assessment (insight card)RISE-15561 "View auto-filled results by AI in the assessment" (Story, BACKLOG, epic RISE-15559, DF release_autofill_assessment_AI_phase3). Repos: rs-backend + rs-frontend.
SCOPE: the per-answer AI insight for answers auto-filled from the Network Profile. Format: "Auto-filled with x% confidence from: Network Profile - {sections, comma-separated}" + the AI explanation; AC1 single section, AC2 multiple sections, AC3 a document from the profile (display name in the explanation). Inherits RISE-15254 behaviour: visible only to the user who ran the auto-fill, not in any PDF, cleared on answer edit (kept on comment/attachment/finding), cleared on step complete, honours the fill-scope options.
BUILDS ON RISE-15560 (card #259, BE !6486 d8fbf9827 + FE !7274 a084e75f2e merged). It already persists source_network_profile_sections (slugs; empty array = section unknown) on assessment_answers_ai_explanations via a three-way CHECK. The created_by read filter is intended (D62). Handoff notes: tmp/RISE-15560/JOURNAL.md Q9/Q11/Q12/F65, DECISIONS.md D29/D62/D63.
OPEN (Tuan's QA comment 520469, 8 questions): renderer branch, one card vs per-section cards, confidence values, display name vs file name (AC3), struck "attach the file" clause, canonical section names, AC3 blocked on the Documents CDC table, empty Figma.P0
rs-backend·feature/RISE-15561/view-np-autofill-ai-insight +17 days ago
#299
UBET-4367 — Push a market when only one side has bets or both sides tieOrchestrated-feature-dev run for Jira UBET-4367 (Task, Todo, Sprint 119, assignee Quan Vo, parent epic UBET-4282 "In-App Currency Betting"). Ticket: a market should push (full refund, no fees) instead of settling when only one side has bets, or both sides have the same total stake. Today both settle as Won with just the stake back. Applies to money and Belief Points markets. Origin: testnet push audit (card #294) and card #298 (which filed the ticket, open question: does "tie" include a top tie with a losing third outcome?). Related: BP settlement UBET-4337 (card #246). Workspace tmp/UBET-4367.P0
6 days ago
#300
RISE-15841 / RISE-15851 / RISE-15849 — Set My Org as Executor bugs (bulk request executor)Orchestrated-feature-dev run over three QA bugs on the bulk-request executor flow (story RISE-15557, epic RISE-15475). Workspace tmp/RISE-15841-15849-15851.
- RISE-15841 (High): a disqualified org can claim the Executor Placeholder seat. Likely fixed on master by RISE-15756 (card #257, Standard-owner gate); confirm with one UHC e2e test.
- RISE-15851: "Access denied" toast when a retailer uses Set My Org as Executor — the flow shouldn't read the assessment; the user has the right to set executor.
- RISE-15849: "Select Executor Organization(s)" popup should close after Save when the partial-failure toast shows.
Worktrees off latest master: rs-backend-RISE-15851, rs-frontend-RISE-15851, unified-health-check-RISE-15841.P0
6 days ago
#302
RISE-15674 / RISE-15802 — Assessed Organization lists require an active RSC relationship, same as Executorfeature-dev-lite fix. RISE-15166 widened the requestee (Assessed Organization) org-list query to admit inactive organizations_associations rows when supplier_management_attributes_rsc is on; Executor / Another-org / Selected Partner always require ACTIVE. Operator decision D-AM (card #250, supersedes D-AJ): requestee lists require ACTIVE too. Keep SM's Inactive exclusion and RISE-15756's Standard precedence. Keep it simple. Workspace tmp/RISE-15674, worktree rs-backend-RISE-15674.P0
6 days ago
#304
UBET-4354 — Global leaderboard: show Belief Points market statsOrchestrated-feature-dev run for Jira UBET-4354 "gloabl leaderboard stats update?" (Task, Todo, Sprint 119, 1d, reporter Daniel Jiwoong Im, assignee Quan Vo, parent epic UBET-3870 "Leaderboard + BM point system"). Ticket has NO description. User clarified: update the global leaderboard page stats to cover belief-point (BP) markets (betting etc.). User asked to proceed without questions — decisions logged in workspace/tmp/UBET-4354/DECISIONS.md.P0
upredict-backend·feat/UBET-4354-leaderboard-bp-stats +15 days ago
#308
Switch price reads off aipa (stalled since 2026-08-27) to vnstock VCI before the 1 Oct runaipa's data stopped on 2026-08-27 (last bar partial) for FPT, VNINDEX and BTCUSDT, checked 2026-09-29; CLI last release 0.1.48 on 2026-06-11. vnstock VCI is live through 2026-09-28 (FPT 64.70k on 09-25 = exchange print). Owner approved the switch 2026-09-29. Scope: VN stock + VNINDEX prices -> vnstock VCI; crypto (BTC vs EMA200 tilt) -> a live source (Binance public klines to test); update the monthly skill, dipwatch.py, CLAUDE.md, STRATEGY_YEARLY data guards; check whether aipa fundamentals/ratios are also stale. Found during card #278.P0
5 days ago
#314
Review RISE-15544 MRs — severity/criticality list selection for workflow questionnaires (BE !6495, FE !7287)/review-changes code review of Minh Nguyen's paired MRs for RISE-15544: rs-backend !6495 (with migration) and rs-frontend !7287 — let admins pick which severity list links to a questionnaire's Finding/Issue section instead of auto-picking the oldest. Worktrees rs-backend-pr-6495 / rs-frontend-pr-7287; reports at tmp/mr-6495/review-changes.md and tmp/mr-7287/review-changes.md.P0
5 days ago
#316
Ops "run script" mechanism in upredict-backend — first script: grant N points to a user by emailSurfaced during UBET-4348 (card #279): there is no sanctioned way to run a one-off DB script against testnet/production (only Atlas data migrations in upredict-infra; operator CLI scripts were dropped in backend #707/#723; informal psql/Supabase editor). User proposes building a "run script" action in upredict-backend for infra to use. First script: add a given number of points to the user with a given email. Stage: design/clarification — no code yet.P0
5 days ago
#325
Add Pay Yourself First calculator to fin calNew /calculators/pay-yourself-first page in finance-calculation-app: fill all but one field (current savings, monthly investment, annual return, retirement age, life expectancy, monthly retirement spending; current age always required) and it solves the empty one. Spend-down to zero at life expectancy, no inflation (user: return covers it), one return rate for both phases. Also adds Vitest (unit) + Playwright (e2e) to the project.P0
4 days ago
#329
October 2026 monthly DCA run — buy list for all four sleevesRun STRATEGY_MONTHLY.md (monthly-dca-research skill) after the 2026-09-30 close: regime + tilt reserve, PASS pool, Angle-1 tripwire, v2_gate valuation, top-3 + split data, funds NAV tilt, gold gap, crypto clip. Output CANDIDATES_2026-10.md. Advisory only.P0
4 days ago
#336
Wellness points — add 10-year record and 3-year growth to the monthly cheapness pointsBuild Suggestion 1 (cheapness on normal per-share profit from the 10-year record) and Suggestion 2 (wellness 0-100: 10-yr consistency/ROE/resilience + 3-yr growth/run, multiplier 0.8-1.2x) for the October pool, compare with the current points. Preview only; no live rule change; backtest is a later step.
2026-10-03 stint: wellness score v2 (Buffett-shaped quality tier). Owner approved: rebuild W for non-banks around the 10-year record (growth Option B: recent growth capped at the 10-year trend), use W as a tier (skip RICH -> rank by tier -> cheapness breaks ties), run compare-only beside the live pick. Bank direction still open (owner argues banks already passed the debt screen). Writing the plan(s) first.P0
3 days ago
#338
Show the weekly market ranking on the Belief Points chainPearlFix reported the weekly market ranking is gone on prod. Root cause: ranking is money-chain only by design (BE #790 Evm filter in get_weekly_market_leaderboard.sql; FE #738 hasMarketRanking/isPointsChain gate in HomePage.tsx + ActivitiesSidebar.tsx), and FE #741 made Belief Points the default chain. Prod data verified healthy (392 specs, stored == live). Fix: BE returns the requested chain's market + latest round within that chain (incl. Belief Points); FE drops the gate. feature-dev-lite, new BE + FE worktrees.P0
upredict-backend·fix/UBET-4371-bp-market-ranking +12 days ago
#339
UBET-4373 — Grant 10 BP when a user visits a demo-day market pageOrchestrated-feature-dev run for Jira UBET-4373 "prepare for BP grant for demo day" (Bug, In Progress, Medium, reporter/assignee Quan Vo). Ticket: a list of market specs will be created for demo day; when a user visits one of those market pages (via the place-bet page or the referral page), grant the user 10 BP (Belief Points) to bet with. Related prior work: UBET-4348 onboarding 10 BP grant (card #279), ops grant-points script (card #316). Workspace workspace/tmp/UBET-4373.P0
2 days ago
Done
137#1
remove amplify proxy between FE and BEcheck the infra, be, fe folder in sport inference, i want to remove the proxy so that fe call directly to backend. Need to check to understand why the proxy was there Make sure when the proxy from amplifier is removed the Frontend can call backend api without issue P0
upredict-frontend·feat/UBET-4083-remove-amplify-proxy +24 months ago
#2
merge and deploy the PRshttps://github.com/SportsFI-UBet/upredict-backend/pull/668
https://github.com/SportsFI-UBet/upredict-frontend/pull/634
https://github.com/SportsFI-UBet/upredict-infra/pull/613/changes
hi team @here, please help me review these 3 PRs for the remove proxy, the release order would be merge BE -> create new tag -> merge infra release new testnet -> merge infra (need review) -> merge FE
after all, our testnet will call BE directly. after a day of testing, we can safely deploy this to prod -> can observe the cost reduce the next day
this is the message from me
need to check if the BE pr approved, then merge, then trigger the tag new build, then merge the new infra PR created by tag new build, then rebase the infra PR with latest main, then merge it, then after all done, can merge the FE PRP0
upredict-backend·feat/UBET-4083-remove-amplify-proxy +24 months ago
#8
research new alternative for alchemyneed to investigate alternative to alchemy smart wallet signer since it's deprecated. and privy is too expensive
Alchemy stopped wallet embedding service...
Here are some alternative services
https://www.dynamic.xyz/
https://web3auth.io/
https://www.turnkey.com/
https://www.openfort.io/embedded-wallet
https://sequence.xyz
https://www.fireblocks.com/products/embedded-wallets
https://magic.linkP0
3 months ago
#10
Fix weekly leaderboard Push-round scoringWeekly market leaderboard drops a spec / miscounts when the current round is Push. Fix: exclude Push-round bets from scoring (mirror generate_leaderboard status != 'Push') and remove the spec-level EXISTS gate so specs whose only round is Push still surface via comments/votes.P0
3 months ago
#12
UBET-4088 BE comment replies (4147 POST + 4152 return nested)Orchestrated feature dev for UBET-4088 reply-to-comments, scoped to subtasks 4147 (POST nested reply via extended /commentOnMarket + migration for parent_comment_id/depth, flatten at depth 2, keep vote gate) and 4152 (return comments with nested replies: extend MarketComment + get_market_comments.sql tree assembly). Worktree: upredict-backend-ubet-4088 on feat/UBET-4088-be-comment-replies off origin/main. Contract plan in workspace/tmp/ubet-4088/api-contract-plan.md. Out of scope: 4148/4149/4150/4151.P0
upredict-backend·feat/UBET-4088-be-comment-replies3 months ago
#13
UBET-4088 BE comment replies — reply pagination (inline cap + cursor endpoint)Fold-in to UBET-4088 (BE only): cap inline replies at N=5 both levels + add cursor-paginated GET /comments/{id}/replies. Core subtasks 4147/4152 already done+tested. Driven via orchestrated-feature-dev; 8 steps.P0
3 months ago
#14
Tier 2 — widen search space: 5 new strategies + engine mechanicsOrchestrated-feature-dev run for Tier 2 of the engine roadmap. Item 4: new strategies (Donchian breakout, ATR breakout, RSI-2, MA/EMA cross, MACD) on the Tier-1 indicator helpers. Item 5: engine mechanics (trailing stops, drawdown kill-switch, volume-scaled slippage). Goal: more real hypotheses to sweep honestly toward beating B&H + surviving the DSR gate. Branch tier1-trust-and-fix (Tier-1 committed at 8119c48).P0
3 months ago
#15
Expose settlement fields on market APIAdd a nested `settlement` object (status, outcomeId, windowEndsAtEpochSeconds) to MarketDescriptionResponseOk for prediction markets, so the admin Settle panel gets the settled outcome id + settle window and can drop the localStorage workaround. BE-only, worktree upredict-backend-settlement-fields on feat/expose-settlement-fields.P0
3 months ago
#16
Tier 3 v0: tabular ML prediction baseline (LightGBM)Orchestrated-feature-dev (slug tier3-ml-baseline). Build supervised LightGBM predictor: multi-horizon return/vol/RSI/MACD features → fixed-horizon-sign labels → LightGBM (purged/embargoed CV) → portable artifact → MLStrategy → existing engine + deflated-Sharpe gate. Train locally (CPU); reserve GPU box for v1 deep model. Resumable (parquet feature cache + LightGBM init_model). One-time: brew install libomp + uv add lightgbm. Roadmap item 6 (docs/research/engine-roadmap/42 + 00).P0
3 months ago
#18
ML holdout eval: decoupled train-elsewhere → score frozen artifact over a chosen periodDecouple ML training from backtesting. (1) scripts/train_ml_model.py: train on --start/--end → artifact, stamp train window + Optuna search count (n_trials) into manifest. (2) holdout.py score_frozen_model: load artifact, slice bars to [start,end], run frozen MlStrategy via run_backtest, OOS Sharpe vs B&H over that slice, DSR deflated by manifest n_trials, verdict. (3) writer.py ml branch: TriggerRequest gains artifact_dir + backtest_start/end; single-period backtest instead of run_pipeline. WARN (not block) when backtest_start < manifest.train_end (leakage flag — user chose flexibility). (4) dashboard form fields (Next.js dashboard/). TDD throughout. Follow-on to Tier-3 v0 (card #16).P0
3 months ago
#19
Research: Tier-3 ML v1 improvement directions (features, engine correctness, payoff/EV, sampling, horizon, granularity)v0 LightGBM predictor is honest but edge-less (~0.543 OOS acc; 1h holdout FAILs DSR). Fanning out 4 parallel research agents to answer the user's v1 questions: Q1 richer features / model complexity, Q2 engine position+signal correctness (does holding long + up-signal wrongly close?), Q3 payoff/EV trade selection (triple-barrier, meta-labeling, Kelly), Q4 random-chunk vs fixed walk-forward sampling, Q5 horizon-5 meaning + longer horizons, Q6 minute-candle granularity vs fee drag. Questions catalogued in docs/research/ml-v1-improvements/00-questions.md. Agents return clarifications; main agent spawns round 2 as needed.P0
3 months ago
#20
Tier-3 ML v2: convert IC≈0.15 signal into a tradeable risk-adjusted edgeFollows v1 (card #19, honest negative result — see docs/research/ml-v1-improvements/16-v1-empirical-results.md). v1 proved the model has real ranking signal (pooled IC ≈ +0.15, stable across feature sets) but NO tradeable risk-adjusted edge at 1h/H=24; walk-forward FAILs, loses to B&H +0.79. Both hypothesized levers ruled out: richer features (enriched -1.06 < close-only -0.88 warm Sharpe) and λ-selectivity (monotone but never positive; the +1.93 was a pooled-proxy artifact). v2 mission = the IC→Sharpe CONVERSION problem, which v1 isolated as the real gap. Untested v2 hypotheses (from doc 16): (1) payoff-asymmetry / position sizing (convex/Kelly-style bet sizing — IC ranks direction, not size); (2) triple-barrier target-vs-stop exits (let winners run, cut losers → reshape payoff distribution); (3) benchmark/framing (long-only vs long/short, excess-over-B&H vs absolute Sharpe, since B&H +0.79 is a strong bull-era baseline); (4) granularity (execution axis, only relevant once an edge exists). Also carries a v1 methodological debt: any v2 tuner must judge the SAME variance-penalized quantity the verdict does (v1's net-EV tuner was variance-blind and harmful). Starting orchestrated-feature-dev at the research/direction-selection stage — awaiting user scope decision on which hypothesis(es) to pursue before spawning research fan-out.P0
3 months ago
#21
Integrate AI-Kanban with OpenClaw (feature idea + OpenClaw setup reference)FEATURE IDEA
Integrate AI-Kanban with OpenClaw so the board can be driven from a chat channel (e.g. Telegram): create/query/move cards, get progress pings, and potentially have OpenClaw agents pick up and work cards. OpenClaw already exposes MCP tools + a paired Telegram control channel, so a thin bridge to the ai-kanban-dispatch MCP tools is the likely integration surface.
--- OpenClaw local setup (reference, as of 2026-07-06) ---
Host: Quan's MacBook Pro (macOS 26.5.2 arm64). OpenClaw 2026.6.11 (brew: /opt/homebrew/bin/openclaw). Config: ~/.openclaw/openclaw.json. Gateway: LaunchAgent, ws://127.0.0.1:18789.
GATEWAY: was crash-looping every ~10s ("Gateway start blocked: existing config is missing gateway.mode"). Fixed with `openclaw config set gateway.mode local` + relaunch. Now listening/reachable. doctor --lint: 0 errors (only warning: gateway.auth.token stored plaintext — cosmetic).
MODEL / AUTH: `openclaw configure --section model` → provider Anthropic via claude-cli OAuth (mode=oauth, profile anthropic:claude-cli) = REUSES the Claude Code subscription (no metered API key). Default model = anthropic/claude-opus-4-8 (fallbacks 4-7 / sonnet-4-6 / 4-6). Verified with a live agent turn. NOTE: subscription OAuth in a 3rd-party tool is a ToS gray area; fine for light manual use, risky for unattended. Cost on this route = Max-plan quota, not $. Switch models per-conversation from Telegram with /model <id>; /model default resets to Haiku/Opus default.
TELEGRAM CHANNEL: bot @quan_vo_open_claw_bot, dmPolicy=pairing. Paired + set as command owner (telegram:1767875031, "Quan Vo") via `openclaw pairing approve telegram <code>` — only this account can command it or switch models. Inbound + outbound + agent auto-reply all confirmed working (first msg was silent due to a one-time auth-profile session reset; resend worked).
BROWSER: plugin enabled. Isolated `openclaw` profile (CDP, port 18800) running. `user` profile = existing-session / chrome-mcp attach to real Chrome (where Bitwarden lives) — NOT yet wired (real Chrome not exposing a debug port; chrome-mcp bridge needed). Existing-session profiles also have some unsupported browser actions (ACT_EXISTING_SESSION_UNSUPPORTED).
PRIMARY USE CASE BEING BUILT (separate from the ai-kanban integration): on-demand AWS SSO login for Claude Code's aws CLI. Flow: OpenClaw runs `aws sso login --sso-session upredict --no-browser` → navigates the printed verification URL in the real Chrome → Bitwarden autofill login (company SSO portal TTL ~1h, NO MFA) → click Confirm → Allow → token cached → aws works. Trigger = MANUAL, on demand from Telegram ("refresh my AWS login"), not a cron. Model Haiku (cheap). Hard rule: stop and ping on any unexpected page. (upredict SSO covers prod=eu-south-1 + testnet=us-east-2 DevOps — token grants both.)
OPEN ITEMS
1. Wire `user` profile bridge so OpenClaw can drive the real Chrome (Bitwarden). 2. Write the "refresh aws" OpenClaw skill (pings back over Telegram). 3. Test AWS flow end-to-end. 4. (This card) design + build the AI-Kanban <-> OpenClaw bridge.P0
3 months ago
#22
Convert SLCP EQ mapping specs from API-only to UI-drivenRewrite 3 slcp-eq-mapping-issue-generation*.spec.ts under unified-health-check to trigger the "Generate Mapped Issues" action via the RSC UI (localhost:4000) instead of directly calling the generateStepExeSchemeIssues/generateAsmExeOrgSchemeIssues GraphQL mutations, and delete the manual-seed debug spec. Seeding, DF toggle, and teardown remain GraphQL helpers.P0
3 months ago
#23
Add BE unit tests for PR #94 storageQuota validation + fix quota-bound & NaN bugsExtract pure resolveStorageQuota helper from routes/users.js PUT /me, unit-test it DB-free asserting correct behavior, and fix the quota-bound bypass + NaN-on-name-only-update bugs found in PR #94 review.P0
3 months ago
#24
Build RISE-15271 factory assessment report toolDesign and ship a self-contained Python script (uv-runnable, single-file with PEP 723 inline deps) that turns a PO-provided xlsx list of factory external_ids into the pivoted assessment-status Excel report from RISE-15271. Includes a psql-runnable fallback SQL and Confluence-ready instructions.P0
3 months ago
#27
Add hooks artifact type to ai-rules + kanban session-tracking hookTwo-track feature. Track 1: build a Claude Code UserPromptSubmit hook that reliably tracks substantive work on AI-Kanban — reads a per-session pointer file (~/.claude/kanban-session-state/$SESSION.json = {cardNumber,cardId,summary}), injects a per-turn re-evaluation reminder (open card if substantive / if work diverged open a new card), and POSTs each user prompt as its own progress note directly to the kanban HTTP MCP endpoint (deterministic, no reliance on the model). Model still owns judgment: create_card + write pointer; hook does mechanical per-prompt logging. Track 2: make "hooks" a first-class installable artifact type in the @quanvo99/ai-rules CLI (parallel to skills/workflows) — .ai-rules.json `hooks:[]` key, hooks/{agent}/{name}/ repo layout, server discovery + Mongo collection + /api/rules payload, and a NEW deep-merge-into-.claude/settings.json writer with an ownership marker so sync can prune only ai-rules-managed hook entries. Motivation: the existing kb-memory rule is start-of-task only and leaks when work grows substantive mid-session; a hook is the deterministic fix. Following orchestrated-feature-dev workflow.P0
3 months ago
#30
PR #94: profile modal via hash nav + name/avatar click opens it (missing ticket requirement)Convert UserProfile into a hash-controlled modal (like signInModal), repoint the navigator name/avatar click to navigate to #/profile instead of logging out, keep Log Out inside the modal, and remove the Grid-panel wiring for profile.P0
3 months ago
#32
UBET-4142 Reply & tagging notifications (BE)Backend: emit notifications when someone replies to your comment and when someone tags/@mentions you, on branch feat/UBET-4142-reply-tagging-notification (based on feat/comment-tagging).P0
upredict-backend·feat/UBET-4142-reply-tagging-notification3 months ago
#33
Brainstorm: AI-Kanban → personal tracker (MCP capability map)Design brainstorm to generalize AI-Kanban into a task-type-agnostic personal tracker any agent (clawbot/CC/non-coding) can operate. Producing a capability map: discovery/read tools, nextAction field, generic update, git-decoupled context, generalized track-session skill.P0
3 months ago
#37
UBET-4156 BE: comment sort by interactionsBackend: sort market comments by interaction score (emoji reactions + all descendant replies) via a `sort=newest|relevant` query param. Worktree upredict-backend-ubet-4156, branch feat/UBET-4156-be-comment-sort-by-interactions (based on origin/main). Plan drafted; awaiting user go-ahead to implement.P0
upredict-backend·feat/UBET-4156-be-comment-sort-by-interactions3 months ago
#38
[RISE-15102] SLCP Non-Compliance column mappingSwap SLCP xlsx flag source from 'Legal Flag' → 'Non-Compliance' column (PO-confirmed no reports use Legal Flag anymore). Drop SLCP_RAW_ANSWER_FIELDS.LEGAL_FLAG and the dead `|| legalFlag` fallback in SlcpAccountInformation.js:395. Following /orchestrated-feature-dev on rs-backend-RISE-15102 worktree.P0
3 months ago
#39
Add market-type filter to market creator API routeAdd a query param to the market creator API route in upredict-backend to filter markets by type: belief market, prediction market, or all. Branch feat/market-type-filter, worktree upredict-backend-market-type-filter (based on origin/main).P0
3 months ago
#40
RISE-14881: Display SM attributes in Organization Compliance — research + CDC data-sourceResearch and data-source investigation for displaying Supplier Management (SM) attributes, incl. org custom fields, in the Organization Compliance page. Locate where custom-field values and names live and how to route them into rs-backend via CDC.P0
3 months ago
#42
Compare our Tier-3 quant ML system vs industry/AFML practiceResearch task (user-requested). Spawn 2 Sonnet sub-agents in parallel: (A) document exactly what our quant-trading Tier-3 ML system implements → docs/research/quant-system-comparison/01-our-system.md; (B) research how professional/industry + AFML systems are built → 02-industry-practice.md. Both cover the SAME 12 dimensions (data/universe, features, labeling, model, decision rule, sizing, risk/exits, execution/costs, backtest+validation, overfitting control, results, gaps) so they line up. Then a 3rd sub-agent compares them → 03-comparison.md. Goal: understand what we did vs what serious systems do differently.P0
3 months ago
#43
RISE-14881 — Display SM Attributes in Organization Compliance (app impl, post-CDC)Orchestrated-feature-dev implementation of RISE-14881 after the CDC pipeline landed in pre. CDC done: cdc_sight_be.assets_attribute (custom-field definitions id→name/type) + cdc_passport_be.attribute_value (values) now flow into rs-backend. Research (Phase 1) complete in tmp/RISE-14881/RESEARCH_OUTPUT.md. Next: Phase 2 plan for the app work (BE reflect cdc_sight_be + mapper join attribute_value.attribute_id = assets_attribute.id + populate customFields; FE display). Resolving scope + open product questions before planning.P0
3 months ago
#44
Add countdown timer tool under new /utils sectionBuild a configurable mm:ss countdown timer in bas-attendance under a new open-access /utils section with a grid-style tool selector. Large center Start/Stop button, loud Web Audio synth alarm looping at zero until Stop/Reset, separate Reset button. Stop preserves button state to prevent double-press restart.P0
3 months ago
#45
Research: Binance leverage/fees/funding vs 100x hypothesisResearch Binance USDT-M perp fee schedule, funding mechanics, leverage/margin mechanics; rigorously evaluate the "100x leverage + minimal fee = higher profit" hypothesis against Sharpe-invariance, liquidation risk, and notional-scaled fees. Document implications for the current negative-Sharpe directional ML strategy vs. a funding/basis carry strategy. Write to docs/research/leverage-and-costs/ in quant-trading repo.P0
3 months ago
#46
Tier-3 ML v3: meta-labeling precision filter (integrated live filter, full strategy mode)Follows the v2 post-mortem + comparison (card #42): wire meta-labeling into the Tier-3 LightGBM predictor as a new v3 strategy mode. Primary (v2: µ̂ EV gate + conviction + triple-barrier) decides SIDE; a secondary binary LightGBM classifier predicts P(trade wins net of cost) and gates ENTRIES (suppress if below threshold) — trading recall for precision on the IC≈0.15 signal. User decisions: (1) INTEGRATED live filter — meta-model threaded into MlStrategy, OOS backtest re-run with it live so skipped entries correctly propagate to downstream state (honest equity Sharpe); (2) FULL v3 strategy mode now (not just a diagnostic A/B) — persistent use_meta toggle + 4-arm verdict (v3/v2/v1/B&H) on identical purged folds + CLI. Existing quant.ml.meta_label harness is bound to the OLD mean-reversion strategy → not reusable directly; building fresh in quant.ml.prediction. Plan-gate: implementation-plan in tmp/ml-v3/, awaiting user 'implement it'.P0
3 months ago
#47
Walk-forward speedup: cache global feature matrix (byte-identical) + fold progress lineThe 4-arm ML verdict run is ~80 min; per-bar Python feature loops are the bottleneck (451 folds × ~2 build_feature_matrix calls × 2000 bars). ACCURACY-NEUTRAL fix only: build the feature matrix ONCE globally, then per fold slice it — re-imposing the SAME warm-up NaN prefix (first max_feature_lookback rows) so the primary's training rows stay byte-identical to the current cold per-window build; meta warm-features use the unmasked warm slice (identical to the current [warmup+is] build for is_bars rows). Prove byte-identity with an equivalence unit test; all existing walk_forward tests must still pass unchanged (same fold Sharpes). Plus: add a per-fold progress line to run_ml_verdict CLI (on_fold callback already exists). NOT doing the non-neutral ones (cross-fit n_splits=2, subset --fast mode). Follows v3 (card #46).P0
3 months ago
#48
Unify storageQuota validation under BE (voluptjs), remove FE validationPR #94 cleanup: (1) remove client-side storageQuota validation in userProfile.js, relying on BE for validation; (2) re-express storageQuota validation as a voluptjs custom validator/schema so all validation logic is grouped in the validation layer, replacing the imperative resolveStorageQuota helper. Update unit tests accordingly.P0
3 months ago
#50
Pull cross-section + funding/perp data into storeStructural-edge pivot after v0-v3 single-asset direction exhausted (IC~0.15 wall). Pull data to support two new directions: (1) cross-section — multi-symbol spot OHLCV for a liquid universe (ETH/SOL/BNB/XRP/DOGE/ADA/AVAX/LINK), reuse existing download_month; (2) funding/basis carry — Binance futures UM funding-rate history + perp klines (new data/futures/um/ path, new CSV schema). All endpoints probed HTTP 200. Report what failed.P0
3 months ago
#51
Build structural-edge strategies: cross-section + funding carryorchestrated-feature-dev (combined run, ws=tmp/structural-edges). Two structural-edge directions after v0-v3 single-asset direction exhausted (IC~0.15 wall): (1) cross-sectional relative-value across 8-symbol universe (long top/short bottom, dollar-neutral) reusing LightGBM feature stack as cross-sectional ranks; (2) funding/basis carry (delta-neutral long-spot/short-perp harvesting 8h funding). Both extend the single-instrument/single-position engine to multi-asset/portfolio + a funding-aware two-leg carry backtest. Data ready (card #50). Phase 1 research in progress.P0
3 months ago
#53
DCA cổ phiếu VN — monthly target scanDCA (dollar-cost averaging) into Vietnamese stocks. Standing task: periodically web-search and scan for possible new DCA targets (candidate VN tickers worth adding to the DCA basket). Run manually when Quan asks — no automated monthly schedule (removed per his request 2026-07-12). No hard deadline.P0
3 months ago
#54
Design monthly DCA candidate-discovery methodology (60-name shortlist, quarterly rebuild)Write a methodology doc for a repeatable monthly DCA candidate-discovery process in ai-price-action. Universe: curated ~60-name shortlist, re-fetched quarterly. Manual ritual (user runs at month-start). Research global + VN 'tich san' consensus to define screening criteria/strategy AND surface seed candidate names. Deliverable this session: methodology doc only (no full 60-name screen run).P0
3 months ago
#55
Research AI-doable side incomes (dropship, affiliate, etc.)Research popular side-income / money-making paths that can be largely run or automated with AI — e.g. dropshipping, affiliate marketing, print-on-demand, content/faceless YouTube, freelancing with AI, digital products, SaaS micro-tools, etc. For each: what it is, realistic earning potential, upfront effort/capital, how much AI can automate, and pros/cons. Goal is a shortlist Quan can evaluate. No deadline. Research only.P0
3 months ago
#57
Crypto DCA: conditional 2× accumulation rule (deploy $2k/mo while in discount zone)User wants to accelerate crypto DCA from $1k to $2k/month, framed as a price-conditional rule: deploy 2x WHILE crypto stays in the current bear/accumulation discount zone, revert to 1x if it re-rates up. Budget stretch (won't starve the 40M VN core). Need to: pull live aipa crypto prices to set mechanical trigger levels, define the conditional rule (discount condition + revert condition + thesis gate + weekly cadence), then write it into DANH_MUC_CRYPTO.md. Year-end total becomes an output of the rule, not a $12k target.P0
3 months ago
#61
Fix structural-edges audit flaws (F1-F9 + count logging)Fix the flaws surfaced by the orchestrated-reasoning audit of the two structural-edge mechanics. Clear-cut latent-bug/robustness fixes via TDD: F1 (DSR sqrt-before-guard crash), F4 (carry warmup_n truncation), F8 (carry RunRecord interval literal), F9 (walk_forward purge>=train guard), F5 (frictionless-always-on label), count-logging follow-up, F2 (cross-section daily feature windows + re-run). Defer F3 (DSR estimator — design decision) and F6/F7 (behavior changes vs logged D-decisions) for user call.P0
3 months ago
#62
Cross-symbol always-on carry sweep (structural-edge step 3)The one unrefuted lead from the structural-edges audit: raw always-on delta-neutral carry is ~2.3 frictionless Sharpe on BTC only. Run the carry verdict across all 9 funding symbols (BTC+ETH/SOL/BNB/XRP/DOGE/ADA/AVAX/LINK), reading the ALWAYS-ON (frictionless) arm not the dead gate. Q: does ~2.3 hold cross-symbol or is BTC a lucky draw? If it holds, next is a realistic-frictions stress test (basis blowups, perp liq/borrow, slippage, hold decay). If not, structural-edge program is exhausted → 'no tradeable edge'.P0
3 months ago
#64
Build multi-symbol carry basket engine (structural-edge step 3, diversification)Via orchestrated-feature-dev (ws tmp/multi-carry-basket/). Build 4 pieces to test if a diversified all-9 equal-weight delta-neutral carry basket earns enough Sharpe margin to survive the ~0.05 bps/bar hold cost that kills every single symbol. (1) build_multi_carry_panel inner-join 9x build_carry_panel; (2) MultiCarryConfig+MultiCarryEngine N-leg shared-equity always-on book, runtime /(2N) sizing + 1x solvency assert, count=4N; (3) multi_carry_verdict walk-forward Sharpe+DSR + diversification baseline (mean of 9 single-symbol Sharpes on identical folds) + hold-cost sensitivity + funding correlations; (4) runner + real-data decision (Sharpe>1.0 at realistic hold?). Decisions MC-D1/D2/D3 locked. 12 BDD steps, 5 quality checkpoints. Follows cards #61 (fixes) + #62 (sweep+frictions).P0
3 months ago
#65
RISE-14881: seed local CDC SM data for org 661cbc91 to test Organization CompliancePopulate local Docker CDC schemas (cdc_passport_be / cdc_sight_be) so target partner org 661cbc91 (owner: Inspectorio SSO c8820e9a) shows full SM attributes + custom fields on the Organization Compliance page. Copy Facility D (eco 345) data + reuse lululemon SIGHT-318814 definitions. All new rows id>=99000000 for easy cleanup.P0
3 months ago
#66
Test, improve & refine the release skillTest, improve, and refine the release skill. Scope includes: (1) listening to Slack (pick up release-related signals/notifications), and (2) posting to Slack after a release (announce/confirm the release in the channel). Iterate on reliability + polish the workflow end to end. No deadline.P0
3 months ago
#67
Restructure KB rule → policy-only; move all kb commands into the knowledge-base skillOption (a): the knowledge-base RULE becomes policy-only (retrieve-first, proactively suggest capturing generalizable learnings, drafts-not-canonical, memory sparingly) and references the knowledge-base SKILL for all command mechanics. Move every `kb` command (search/get/capture/update/delete + flags) out of the rule and into the skill. Add the missing kb update/delete to the skill. Mirror across claude-code/cursor/antigravity + update manifest.json if it carries descriptions.P0
3 months ago
#69
UBET-4176 Vote change fix — preserve comment vote sideOrchestrated feature dev for UBET-4176: preserve the vote side of the comment when a user votes. Backend (belief_locker), worktree upredict-backend-ubet-4176, branch fix/UBET-4176-vote-change-fix.P0
upredict-backend·fix/UBET-4176-vote-change-fix3 months ago
#70
UBET-4190: API returning all replies for a market in one ordered callDesign/build a backend API so the FE can load ALL replies for a market in a single call, with ordering consistency guaranteed structurally (wrong-order continuation unrepresentable). Following orchestrated-feature-dev. Worktree: upredict-backend-ubet-4190 (branch feat/UBET-4190-be-all-replies-api off origin/main). Brainstorm + state in tmp/UBET-4190.P0
upredict-backend·feat/UBET-4190-be-all-replies-api3 months ago
#73
Analysis: minute-level edge — full-MM frame, entry-precision + multi-hour hold (go/no-go)Structured-reasoning decision analysis: can minute-level bars produce a robust tradeable edge the exhausted hourly/daily arcs couldn't? Frame: full market-making execution; minute-precision entries with holding horizon unconstrained (can be hours). Compare BOTH prediction targets (order-flow/microstructure vs single-asset direction @1m). Method: Sonnet agents gather evidence dossiers from codebase+docs, then Fable 5 reasons (primary + adversarial + synthesis) over the gathered evidence — not from scratch. Deliverable: go/no-go + best-shot design + train/test/horizon/selectivity knob recommendations. Continues the structural-edges arc (cards #61/#62/#64, terminus 'no robust tradeable edge').P0
3 months ago
#74
UBET-4143: Comment gains BP when others reply / react (BP scoring)Extend market-points/BP scoring: (1) 1 BP per unique comment per market, (2) 1 BP per unique replier to a commentor, (3) 1 BP for emoji reactions to commentor/replier. Parent epic UBET-4146 "Reply to comments". Backend (upredict-backend). Following /orchestrated-feature-dev pipeline.P0
upredict-backend·feat/UBET-4143-reply-belief-points3 months ago
#75
Design performance review lens for review-changes skillBrainstorm + implementation plan for a new performance lens carved out of correctness, with a conditional perf-sensitive gate, across all three review-changes variants (claude-code, cursor, antigravity). Deliverable this session: design doc + plan, then pause.P0
3 months ago
#76
Fix 2 more assessment-filter nested-loop anti-pattern instances (addCaseHistoryJoins, filterByLatestCase)Prove-then-fix the two remaining unscoped-aggregate-JOIN instances on the assessment-list filter route, same class as the already-fixed caseHistoryByDateQueryBuilder (submit/start/abort). (1) addCaseHistoryJoins (filter.service.js:589) — unscoped DISTINCT ON case_history LEFT JOIN feeding 8 case/CAPA date filters; rewrite to correlated EXISTS (reuse caseHistoryByDateQueryBuilder). (2) filterByLatestCase (FilterUtils.js:399) — unscoped MAX(case_index) GROUP BY case_info_id INNER JOIN for the "Most recent assessments" quick filter. Approach: EXPLAIN-prove fan-out on local prod-copy, apply EXISTS rewrite, verify (EXPLAIN after + tests + real-code-path). Temp slow-query logger in knex.js must be reverted before commit; work sits in fix/RISE-15315/scheme-filter-exists worktree, move to own branch.P0
3 months ago
#78
RISE-14881: eco-first field priority + supplier-profile scoping + org-type label mapCombined change to match SM "My Organizations" table: (BE) resolve the ecosystem-scoped supplier profile (ecosystem_id = viewer ecosystem), flip field-source priority to eco-first with sm_organization fallback, select eco.type, keep Inspectorio ID from the global profile. (FE) add org-type code->label map matching passport-be OrganizationType. TDD.P0
3 months ago
#80
Plan + build 1 progressive Python-basics exercise (input/variables/conditionals)Design ONE untimed practice test whose exercises go easy→hard, for students who know only input, variables, and conditionals (no loops/functions/lists). ~120 min of work, balanced MC + free-text branching-program coding, same course c98f8f96, seed to Atlas after approval.P0
3 months ago
#81
Run belief_locker live HTTP server against local anvil chainEnable running the live belief_locker Fastify server locally against a local anvil chain (full on-chain write flow) + persistent local Postgres, in a dedicated worktree. Add config-driven per-chain RPC override + anvil chain support, chain setup (roles/fees/faucet), local self-contained config, and a bootstrap runner.P0
3 months ago
#82
Local graph-node subgraph indexer for local anvil chainFollow-up to #81: stand up a local graph-node (+ IPFS + its own Postgres) indexing the local anvil chain (31337), deploy the upredict subgraph against it, and point belief_locker's per-chain subgraphUrl at the local endpoint so subgraph-driven flows (bet confirmation, fee tracking) work end-to-end locally.P0
3 months ago
#83
Drive agents to log decisions to AI-Kanban decision array (skills + project)The ai-kanban-track-session & ai-kanban-work-card skills never drive the agent to use the card decision log (append_decision/mark_decision_outdated): the tool isn't in allowed-tools, no step covers it, and one line misroutes decisions into the progress log. Fix both skills (push decision-logging at real decision points) AND the AI-Kanban project (whatever's needed end-to-end, e.g. get_card_context returning decisions). Running via orchestrated-feature-dev.P0
3 months ago
#85
Improve grading page UX (AI panel, MC forms, explanations, model)UX improvements to the admin grading page: nest AI suggestion inside the question box, make MC grading read-only (auto-graded), add optional "why correct" explanation to MC questions (test + pools) shown to students, change per-student Save & Next to advance to the next question, and upgrade the Gemini grading model.P0
3 months ago
#87
MCP board parity: create-in-todo + any→any status movesGive the ai-kanban-dispatch MCP full board parity with the webview. (1) create_card gains an optional status param (default in_progress); status=todo creates a fresh queued backlog card. (2) set_status lets an agent make any→any transitions like a person (remove AGENT_EDGES). Running via the orchestrated-feature-dev pipeline; workspace at AI-Kanban/tmp/mcp-board-parity/.P0
3 months ago
#88
UBET-3958 — Belief-points forward ledger (implement)Implement the belief-points forward ledger (UBET-3958): a point_ledger table + per-source emit so a future point-formula change is cheap and non-retroactive — points frozen at WRITE time, reads become SUM(point_ledger), rule_version stamps each row. D12 split: the 6 user-route sources (comments, replies, reactions, votes, streak, mystery-box) emit INLINE in the request transaction with app-code dedup under a group-scoped pg_advisory_xact_lock; the 4 chain-ingested sources (referral, creator-fee, bet-volume, push-reversal) stay worker/watermark. Worktree upredict-backend-ubet-3958, branch feat/ubet-3958-point-ledger. Driven via orchestrated-feature-dev; Phase 4 implements ONE source at a time, stopping at each for user review + commit gate.P0
2 months ago
#89
UBET-4188: return unread vote items (voteId + timestamp) in market activity detailChange MarketActivityVotesSummary in the grouped market notifications detail route from `sampleVoterNames: string[]` to `items: MarketActivityUnreadVote[]` ({ voteId, authorName, atEpochSeconds }). Touches jsonSerializable interfaces, the get_market_activity_detail_summary SQL, the route mapper, generated schemas, tests, and the contract doc. Branch feat/UBET-4188-be-group-notifications-by-market (PR #701). Running trimmed orchestrated-feature-dev in tmp/UBET-4188-vote-items/.P0
2 months ago
#90
Market-wide value scan — find DCA candidates at the lows (VN)Market is broadly down. Run the DCA_CANDIDATE_DISCOVERY.md funnel over held names + the seed/shortlist universe: gather live aipa price/MA/liquidity data via sonnet subagents, rank quality+cheapness WITHIN ngành (never raw cross-sector), news-screen survivors, output a Candidate Watch list. Flag-for-review only.P0
2 months ago
#91
RISE-14826 Org Management: Export table to CSV (Data table)Add a "Data table" CSV export to the Organization Management activation table: new FE option + mutation, BE ORGANIZATION_CSV background task + worker with special column formatting (contacts, SEDEX) and DF-gated value population.P0
2 months ago
#92
UBET-4188: add avatarUrl to interaction row details (latest, comment, vote)Add avatarUrl: string | null to GroupedMarketNotificationLatest, MarketActivityUnreadComment, MarketActivityUnreadVote. Source: rawUserMetadata.avatar_url (already selected by all 3 SQL queries — no SQL change needed). New resolveActorAvatarUrl resolver next to resolveActorDisplayName. Null when no social avatar (no fallback). Extend existing tests with avatarUrl assertions (no new tests). Update contract doc + regenerate jsonSerializableSchemas.json. Branch feat/UBET-4188-be-group-notifications-by-market (PR #701).P0
2 months ago
#93
Pooled-panel direction ML: train one model on all 9 symbols, predict eachTest whether pooling all 9 symbols' data (BTC + 8 alts) into ONE LightGBM direction model — as data-augmentation vs the ~83-sample single-symbol starvation — yields a better ABSOLUTE-direction predictor than the BTC-only baseline. Distinct from the existing (failed) cross-section relative-value RV model: predicts each coin's OWN absolute return, not demeaned rank. Decisions: ragged-union alignment (keep all history, global-time purge split) + combined equal-weight book verdict (one blended Sharpe/DSR). Built via orchestrated-feature-dev pipeline.P0
2 months ago
#94
UBET-3958 Step 11 — belief-points ledger backfill script + unit testsOne-time, cutoff-bounded backfill for the belief-points forward ledger. Replay-emitters model (user's choice): set-based backfill_*.sql per source, idempotent via on-conflict, coexists with live-emitter rows. Reusable runBeliefPointsBackfill(db,{dryRun}) in src/services + thin CLI scripts/backfillBeliefPointsLedger.ts (dry-run default, AWS-secret DB). Unit tests via testDbFixture.P0
2 months ago
#96
UBET-4052: revamp interaction rewards / point systemPlan + implement new point system: +1 per reply/emoji to your comments, +1 per interaction to your markets (creator), +1 per referee interaction to referrals, remove +1 for likes.P0
upredict-backend·feat/UBET-4052-revamp-interaction-rewards2 months ago
#98
RISE-14881 — resolve SM taxonomy labels via assets_category CDC (read-side)rs-backend read-side for taxonomy label resolution. Backfill already fired on pre+stg (signals RISE-14881-pre-03/stg-03); pre sink cdc_sight_be.assets_category fully populated (106,973 rows) and verified: coded custom_ids resolve to correct labels scoped by d_owner_org_id (e.g. owner 513048: m06→Service Provider, b04→White Label, bu3→Accountability, bu09→Beauty & Personal Care). Implement: (1) constants ASSETS_CATEGORY + add to SIGHT_CDC_TABLES; (2) extract SIGHT-owner-id subquery helper; (3) label-resolving taxonomy join in sm_cdc_attributes.service.js with raw-value fallback when assets_category absent; (4) extend service spec. Branch feature/RISE-14881/taxonomy-label-resolution off fix/RISE-14881/sm-attributes-followup.P0
2 months ago
#99
UBET-3958 read-cutover — serve belief points from point_ledger (3 read APIs)Orchestrated-feature-dev run for the ledger read-cutover on branch feat/UBET-3958-ledger-read-cutover. Hybrid points-from-ledger: realtime = live query-time SUM; all-time leaderboard + weekly = matview with swapped points term. Branch-as-gate, no runtime flag. Design in tmp/ubet-3958/{LEDGER_READ_CUTOVER_DESIGN,UBET-3958-V2-TODO}.md.P0
2 months ago
#100
RISE-14887 — Supplier Profile hyperlink on Organization Information pageAdd a "View Profile" hyperlink to the RSC Organization Information page header that opens the corresponding Supplier Management supplier profile in a new tab. Epic RISE-14879 (Read SM Organization data in RSC). Open point from the ticket: mapping the RSC org to the SM org id. Running via /orchestrated-feature-dev; workspace ./tmp/RISE-14887/.P0
rs-frontend·feature/RISE-14887/supplier-profile-hyperlink +12 months ago
#102
Review PR 710 (UBET-4067 public profile + nickname routing) — blind behavior-risk auditCode review of SportsFI-UBet/upredict-backend PR 710. First pass done (2 MUST FIX both dismissed by user: migration is a separate infra PR; social SCA address exposure is intended). Now: spawn an implementation-blind behavior-risk cataloguer (orchestrated-feature-dev phase 3b) against origin/main only, then diff its catalog against the actual implementation.P0
2 months ago
#104
review-changes: holistic-driven lens gating across 3 variantsReplace the hardcoded "correctness, quality, security always run" lens gate in the review-changes skill with per-lens applicability verdicts emitted by the holistic phase. Floor = correctness only; security/quality/tests/performance all gateable with an uncertain->yes bias. Applies to skills/claude-code, skills/cursor, skills/antigravity. Plan at tmp/review-lens-gate/plan.md. Worktree: ../AI-rules-repo-review-lens-gate on branch feat/review-changes-lens-gate.P0
2 months ago
#105
UBET-4202 review fixes: referral interaction rewardsApply the 9 decided fixes from the UBET-4202 code review, in the worktree upredict-backend-ubet-4052 (branch feat/UBET-4202-referral-interaction-rewards, rebased onto origin/main 64822b3).
Decisions and full rationale: tmp/UBET-4202/review-decisions.md. Option analysis for the leaderboard universe: tmp/UBET-4202/brainstorm-leaderboard-universe.md. Original review: tmp/UBET-4202/review-changes.md.
Order: (2) extract shared establish-link/decide/emit helper; (3) order-independent pair advisory lock + correct the false cycle comment; (4) codeResolved warning log via namedQueryZ; (5) reaction route referralCode validation in-handler; (6) direct-referrer-only bet gate in SQL + reshape verifyLeaderboardResult; (7) move/fix point_ledger meta index predicate; (8) abstract_user.is_system_account column + infra migration + boot-time write + view filter at both join sites; (9) add Referral + CreatorReward to the earned_at-keyed universe branch.
Constraint: step 8 migration must land before the wholesale re-apply of upredict_index_view_function.sql.P0
upredict-backend·feat/UBET-4202-referral-interaction-rewards2 months ago
#108
Creator rewards follow-up: belief point values and creator vote creditOn feat/creator-rewards-followup (upredict-backend, stacked on UBET-4211): collapse CreatorComment/CreatorReply into one source type with the kind in meta, move the creator cap to a per-kind ledger test, add a creator +1 credit when a user votes on their market, floor the creator fee credit at 1, and raise Reply 1->5 and Reaction 1->3.P0
2 months ago
#109
Investigate + harden anvil EVM test fixture flakes (BE CI)BE CI flakes traced to the anvil/EVM jest fixture. Two signatures in the last 7 days: (1) BlockOutOfRangeError "block height is 16 but requested was 15" in evmFixture.ts during contract role read — cost the 20260731.1 release tag its TS docker images; (2) hook/test timeouts (15s hook, 10s test) in backendServiceFixture. Goal: gather evidence, root-cause, propose concrete hardening.P0
2 months ago
#113
Cross-session card dedupe: search-first trackingStop the board fanning out duplicate cards for the same unit of work across sessions (RISE-14881 x5, UBET-3958 x3, UBET-4188 x3). Root cause: create_card dedupes on session:<sessionId>, so a new session always means a new card, and the skill's adopt ladder only checks session-keyed sources — nothing ever asks the board. Fix is search-before-create (wide recall + explicit verification), NOT a caller-supplied key. AI-Kanban: call bootstrapIndexes at connect so indexes actually exist in prod (repairs list_cards text search, makes dedupeKey uniqueness real). AI-rules-repo: flip the kanban-track hook reminder to search-first, add a board-search rung + reopen path to ai-kanban-track-session, correct the stale any->any transition docs. See PLAN-cross-session-card-dedupe.md in AI-rules-repo.P0
2 months ago
#119
Build session-durability behaviors (journal, work-index, PreCompact log, card mirroring)Implementation follow-on to card #106 (audit, no file changes). Build the 8 "build now" session-durability behaviors from tmp/session-durability/PROPOSAL.md: typed journal + continuous capture, work-index.mjs read path, PreCompact evidence log, kanban-track breadcrumb for every session, CONSTRAINTS.md convention, promotion criteria to card/kb, staleness flagging, flush-debt Stop nudge. Repo: AI-rules-repo, worktree AI-rules-repo-session-durability, branch feat/session-durability. One commit per behavior. Following orchestrated-feature-dev end to end. Deferred (9-11): per-prompt CONSTRAINTS injection, SubagentStart inheritance, /clear discontinuity.P0
AI-rules-repo·feat/session-durability2 months ago
#120
UI: trigger any strategy/verdict run, persist to DB, display trade-annotated resultsOrchestrated-feature-dev. SCOPE CORRECTED by user mid-Phase-1: not just a nicer chart. Make everything we've built (single-symbol pipeline, ladder, carry, multi-carry, cross-section, pooled-direction verdicts) TRIGGERABLE FROM THE WEB UI (dashboard/), persist each run to the DB, and DISPLAY the result in the UI — including a richer trade-annotated visualization (entry long/short, exits, per-trade PnL, position size) with toggles for what to display.
Known crux from Phase 1 research: EngineResult exposes only equity_curve + a scalar count — NO trades list, NO position series, NO price. Trades exist transiently (Portfolio.trades, ladder tranches) and are discarded at the engine seam and per walk-forward fold; per-trade PnL is computed nowhere. So overlays require additive plumbing across the seam. Second crux: 4 of 6 tearsheet callers are stitched 1/N multi-symbol books where a single position/price/trade does not exist.
External viz research (done): adopt stacked shared-x panels (price+markers / equity / underwater), exit-triangle encoding win-loss by color + side by direction, entry→exit shaded spans, exposure as its own subplot; render via matplotlib multi-panel inline SVG + artists tagged into SVG <g id> groups with ~15 lines of inlined vanilla JS for toggles (no CDN, stays self-contained).P0
2 months ago
#121
Work on Concrete Engine — Sun Aug 2Focus task for Sunday, Aug 2, 2026: work on Concrete Engine. (Specific scope to be filled in by Quan.) Quan asked for an hourly reminder to keep at it until it's finished — set up on the OpenClaw cron system, delivered to Telegram, and stopped once he says he's done.P0
2 months ago
#124
Trade chart: distinct exit glyph, fix overlapping exit PnL, marker tooltips explaining whyFour fixes to the run page's Trade detail chart, from user feedback on the live UI:
1. Exits currently reuse the SAME glyph as entries — needs a visually distinct exit marker (the researched convention is distinct entry vs exit glyphs; we only varied colour/direction).
2. Double-click-to-reset-zoom is bad UX — remove it, keep/improve the explicit Reset control.
3. Ladder exits OVERLAP: per D7 (user call) a basket stores one trade PER RUNG all sharing the basket's single exit ts AND exit price, so N per-trade PnL labels render stacked on the exact same pixel. Fix by drawing ONE exit marker per basket with an aggregate label, and moving per-rung detail into the tooltip. Data stays per-rung; only the rendering dedupes.
4. Hover/click a marker should explain the stats AND WHY the entry/exit happened. Blocker: RoundTripTrade/TradeRecord carry no rung index and no z-score, so the reason for an ENTRY cannot currently be stated. Needs backend enrichment: rung_index (engine knows it), entry_z and exit_z (the strategy computes z; ride it on the shared Signal as an optional defaulted field, per the standing extend-the-shared-contract rule). exit_reason already exists.
Existing runs (28, 29) predate the new fields, so the tooltip must degrade gracefully when they are null.P0
2 months ago
#125
claude-usage: sync API, hooks, backfill + dashboard (PLAN Steps 9-14)Implement remaining steps of claude-usage PLAN.md via orchestrated-feature-dev.
Phase 2 (sync): Step 9 event mapper (Turn -> UsageEventDocument, per-event account from ledger), Step 10 POST /api/sync with x-claude-usage-secret guard, Step 11 SessionStart + UserPromptSubmit hooks (detached upload, <10ms), Step 12 backfill over ~46K events.
Phase 3 (dashboard): Step 13 /login + /api/auth + edge proxy, Step 14 dashboard views (cost per day/machine/project/model, subagent share, cache efficiency, session drill-down) on shadcn + Base UI, base-nova, neutral, dark-first.
Repo: github.com/votrungquan1999/claude-usage. Constraint: aggregates ONLY - transcripts never leave the machine.P0
2 months ago
#126
Ladder verdict soundness: stop_z ceiling guard, baseline sizing, true B&H arm + re-run bake-offOpus audit of run #31 found the run did not test its configured strategy.
FLAWS: (1) stop_z=5.0 is mathematically unreachable — RollingZScore uses statistics.pstdev over the full lookback window, so max |z| = (n-1)/sqrt(n) = 4.359 at lookback=20; 0 of 18415 trades exited on 'stop', max entry_z observed 4.3537. Combined with max_hold_bars=0 (disabled) the run had NO loss exit and NO time exit. (2) rung 2 (|z|>=4.0) fired 8 times in 15550 baskets — 84% single-entry, so the ladder thesis was barely exercised. (3) ladder_verdict.py:313 calls run_backtest with no size kwarg so the baseline arm runs at 100% of cash vs the ladder's ~33% — arms compared at ~3x different notional. (4) bah_sharpe stores the single-entry MR arm, not real buy-and-hold (run #30 stores true B&H +1.0857 in the same column) so #31 cannot answer 'should I just have held?'. (5) The gate's real comparator max(baseline,0.0) is not persisted, so the record reads as 'beat the baseline but failed'.
VERDICT ON #31: the FAIL is trustworthy in direction — frictionless per-trade edge is -15.8bps over 18415 trades and 47000 OOS bars, i.e. it loses at ZERO cost; fees $120,165 vs gross-of-fee PnL -$118,566. But the ladder thesis is UNTESTED, not refuted.
REFUTED (my own suspicions, checked and wrong): purge=0 is not leakage (neither arm trains a model; each fold builds a fresh engine over test_idx only). train=2000/test=1000 is BETTER than the old test=120 (47 vs 398 folds, 47000 vs 47760 OOS bars, 940 vs 7960 warm-up bars wasted). The negative-baseline gate is already correctly floored at max(baseline,0.0). No repeat of the run-#28 blowup artifact (equity never exceeds its 10000 start; largest step +3.03%).
SCOPE (user-approved): guards + code fixes + re-run as a 2-config bake-off (rescaled rungs at lookback=20 vs original [2,3,4] at lookback=50), realistic costs only — no zero-cost diagnostic.P0
2 months ago
#127
Trade chart: snap x-axis ticks to real bars + zoom-aware full-resolution price seriesUser spotted axis labels like "11-18 21:09" / "12-06 05:49" on a 1h run and asked whether trades were on minute candles. They are NOT — verified all 1259 bnbusdt trade entry_ts and all 1484 price points on run #33 land exactly on :00, and the run interval is 1h. Two display-layer bugs underneath:
(1) TICK LABELS: the zoom feature switched the XAxis to a continuous numeric (epoch ms) scale with a [lo,hi] domain, so Recharts places ticks at arbitrary points inside the range instead of on bar boundaries. "21:09" is not a bar, it is where the tick math landed. Affects both the axis ticks and the range readout next to the Reset button.
(2) MARKER/LINE MISALIGNMENT: GET /runs/{id}/prices downsamples ~31x (1484 points at 31h spacing for run #33) while ALL trades are drawn un-downsampled. Markers therefore sit off the price line — visible in the user's screenshot as the -4.9% marker floating well below the curve. Downsampling is deliberate (full series ~47k points) so the fix is to serve FULL resolution for the visible zoom window rather than disabling it globally.
Neither affects any verdict — chart series only; backtests use full-resolution data.P0
2 months ago
#128
Trade visualization for all UI-triggerable methods + ML arg prefillOnly LadderEngine builds RoundTripTrade and only ladder_verdict persists trades, so the Trade detail chart renders for ladder runs only. Extend to every UI-triggerable method: single strategies + ml (need fill->round-trip pairing off run_backtest), plus cross_section / carry / multi_carry / pooled_direction which are CLI-only today and must also be added to the trigger form. Also generalize the ladder-shaped marker detail panel, and prefill the ML artifact/date fields from artifacts discovered by a new backend scan endpoint. Plan: tmp/ui-visualize-all-methods/implementation-plan.mdP0
2 months ago
#129
Add 6 testnet migrations to production for release 20260731.4 (upredict-infra #692)Copy the 6 migrations that landed in Terraform/testnet/postgres/migrations at tags <= 20260731.4 into Terraform/production/postgres/migrations, then regenerate production atlas.sum, for the release-to-prod PR #692.P0
2 months ago
#130
Code review: upredict-backend PR #723 — user_alias profile routing identifierReview PR https://github.com/SportsFI-UBet/upredict-backend/pull/723 ([UBET-4067] User profile routing identifier). Checked out in worktree workspace/upredict-backend-pr-723 (branch ubet-4067-user-profile, base origin/main, 41 files +1199/-138). Running the /review-changes fan-out pipeline: holistic -> lenses -> verify -> merge. Report lands at tmp/pr-723/review-changes.md inside the worktree.P0
2 months ago
#131
UBET-4216 better notification feed API (unread-first + read markets, paginated)Rework GET /notifications/markets so it returns ALL markets the caller interacted with (not just unread), ordered unread-first then read-by-most-recent-interaction, with efficient pagination. Currently get_grouped_market_notifications.sql filters is_read=false in 3 places so read markets vanish after mark-all-read. Design phase: pick a pagination/aggregation approach (single composite-ordered query w/ offset vs keyset cursor vs precomputed rollup table). Response contract already carries isUnread/unreadCount — no interface change needed.P0
upredict-backend·feat/UBET-4216-notification-feed-unread-first2 months ago
#132
claude-usage dashboard insights: chart palette, session list, range picker, KPIs, repo/account dimensionsFollow-on to card #125 (claude-usage sync + dashboard). Scope:\n\n1. Real hued chart palette — current --chart-1..5 are all oklch(L 0 0), i.e. chroma 0 = grayscale; the dark-mode block is byte-identical to light so --chart-5 (L 0.269) is invisible on dark. Also "Other" uses --muted-foreground, colliding with the palette. Plus stable per-series color (today color is assigned by rank index, so a series changes color between ranges).\n2. Session list with drill-down — /session/[id] exists but is only reachable by pasting a UUID into SessionLookupForm.\n3. Date range picker — RANGE_DAYS hard-coded at 30 while ~$7k of all-time history is backfilled and unviewable.\n4. Headline KPI cards — spend today / this month / projected month-end.\n5. Repo dimension — repoKey is stored and already merged in queries, never surfaced as a split tab.\n6. Cache savings in dollars — reframe raw reads-vs-writes as money saved.\n7. Account dimension — accountUuid stored, never shown.\n8. Model mix trend — Opus/Sonnet/Haiku share over time.\n\nRun via orchestrated-feature-dev; workspace tmp/claude-usage-dashboard-insights; living spec docs/features/claude-usage-dashboard-insights/spec.md. Repo: github.com/votrungquan1999/claude-usage. Standing constraint: aggregates ONLY — transcript content never leaves the machine.P0
2 months ago
#133
Add architecture lens to review-changes + fix merge scoring rubricAdd a 6th "architecture" lens to the review-changes skill so feature-level design judgment produces scored, verified findings; purge impact from the merge confidence bands and make the filter severity-aware. Propagate across claude-code, cursor, and antigravity variants.P0
2 months ago
#135
UI methods Steps 4-8: engine triggers, carry attribution, ML artifact prefillContinuation of ui-visualize-all-methods. Steps 0-3 shipped to main (43b1fad). This card covers the deferred Steps 4-8: cross_section console trigger (S4), carry + multi_carry triggers (S5), carry PnL attribution funding/basis/costs via a new run_series store (S6), pooled_direction trigger + visualization (S7), ML artifact prefill picker (S8). Plus cross-cutting cancellation (R34) and job-runner slot routing (D4/R33). Branch feat/ui-methods-steps-4-8. Frozen BEHAVIOR_RISKS.md Groups C/D/E hold ~20 requirement-silent risks needing user decisions before implementation.P0
2 months ago
#138
Author "monthly-dca-research" private skill (scope personal) — full 4-sleeve month-start flowPackage the whole monthly DCA month-start research + deployment ritual into a private ai-rules skill scoped 'personal'. Must cover all 4 sleeves (stocks, funds, gold, crypto) and stitch the STRATEGY_NOTES steps: §3.0 include/exclude gate, §3.1 tilt, §4 health check, §5 amount (1.5× / 2×/1×), §6 two-phase entry-timing dip-watch (Phase A shortlist + Phase B daily watch), plus DCA_CANDIDATE_DISCOVERY funnel, VANG_DCA gold schedule, DANH_MUC_QUY funds, DANH_MUC_CRYPTO basket. Author SKILL.md under .claude/skills/monthly-dca-research/, get user approval, then `skill upload --agent claude-code --scope personal` (AI_RULES_SECRET already in env).P0
2 months ago
#139
Port architecture lens + certainty scoring to cursor and antigravity review-changesDescoped remainder of card #133 (done, claude-code only). Port the 6th architecture lens and the certainty-only scoring rubric from skills/claude-code/review-changes/ to the cursor variant (inline holistic/merge, no node-merge.md, cites .cursor/rules/*.mdc) and the antigravity variant (single ~198-line inline SKILL.md, no nodes/ dir).P0
2 months ago
#141
All-feed: group Comment/Vote into per-market entriesCollapse Comment/Vote rows in the All-notifications feed (GET /notifications) into one per-market group entry (reuse Market-tab grouped shape); Reply/Mention/PointChange/BetOutcome stay individual; feed stays time-ordered (group sort key = max(inserted_at)); group counts unread-only; group is display-only (reuse existing Market-tab detail + mark-group-read); /unreadCount + mark-all unchanged. Response-contract change (new feed item variant + codegen:jsonSerializable + FE follow-up). Extends branch feat/UBET-4216-notification-feed-unread-first.P0
upredict-backend·feat/UBET-4216-notification-feed-unread-first2 months ago
#142
claude-usage: migrate node:test -> vitest, and add Playwright happy-path e2eFollow-on to card #132. Two tracks, ordered: (A) unify the test runner, then (B) add the browser layer that does not exist at all today.
# Track A — migrate the 18 node:test suites to vitest
Today the repo runs TWO runners: `node --test tests/*.test.mjs && vitest run`. The `&&` means a CLI failure HIDES the server results entirely.
The 18 tests/*.test.mjs files predate card #132 (added in 40b1138 parser-core, 5145067 sync). They cover plain .mjs — src/parser/, bin/sync.mjs, hooks/ — with no TypeScript, no JSX, no @/ aliases, which is why the bare node runner was sufficient. vitest.config.ts currently includes only src/**/*.test.ts.
## Why migrating is safe (the fidelity objection does not apply)
vitest transforms modules, and these tests exist partly to verify what real `node` does with a real .mjs file. But the hook/CLI tests `spawn(process.execPath, [hookPath])` — a REAL child process at a REAL file path. The code under test is never transformed by either runner; the runner only affects the harness. Migration costs nothing in fidelity.
## Shape
Use a vitest WORKSPACE with two projects, not one merged config — the CLI tests must not inherit mongodb-memory-server's 60s timeouts or MONGOMS_SYSTEM_BINARY.
## Wins
- One command, one watch mode, one coverage report; no `&&` masking failures.
- Readable diffs on failure (node:assert/strict prints a poor one).
- `retry` becomes available for genuinely timing-dependent tests.
## Gotchas to check before committing
- Keep node:assert or convert to expect? RECOMMENDATION: keep node:assert in the migration commit so it is a provable pure move; convert opportunistically after. Mixing a runner swap with an assertion rewrite makes any failure ambiguous.
- vitest runs files in parallel workers by default. These use mkdtempSync and port 0 so they look safe, but the ones mutating process.env need a real look.
- node:test subtests `t.test()` map to `describe`, not 1:1.
- Keep `npm run test:cli` / `test:server` working, or update every reference to them.
# Track B — Playwright happy-path e2e
Everything under src/app/*.ui.tsx has ZERO automated coverage — type-checked by `npx tsc --noEmit` and nothing more. Scope here is the HAPPY PATH, not exhaustive.
WHY NOT jsdom: deliberately rejected during card #132. jsdom returns zeros from getBoundingClientRect, so a chart axis tick "survives" in the test while a real browser deletes it — a false green on exactly the claims that need checking. Recorded in docs/features/claude-usage-dashboard-insights/spec.md under "Things a test cannot tell you here".
## Happy-path candidates
- Dashboard loads authenticated and renders all six cards without an error boundary.
- Range picker: choose a preset, the URL updates, the cards re-read it.
- Cost split: switch tab (machine/project/model/repo), chart + totals table both change.
- Session list: re-sort, page forward, click into /session/[id].
- The URL is the single source of view state: preset/tab/from/to/sort/page survive a reload and a shared link.
## Three open rendering questions (from the #132 spec) — verify, do not necessarily fix here
1. Today's bar is not marked partial on the cost-per-day chart (only the KPI tile says so).
2. At 90-day and all-time windows the X axis is crowded; no bucketing or tick strategy was built.
3. A fully-unpriced day and a gap-filled empty day both draw a zero-height bar. Distinguishable in the data (eventCount) and the range-level statement fires, but not by looking at one bar.
## Setup constraints
- Auth: every dashboard route 307s to /login (proxy.ts). storageState vs a test-only bypass — FIRST DECISION, has security implications (an env-gated auth bypass shipped to prod is a real risk).
- Dev-server isolation: an e2e-owned `next dev` shares .next with a running dev server and hangs. Use NEXT_DIST_DIR + tree-kill teardown.
- Data: the local mongodb://localhost:27017/claude-usage is READ-ONLY — only copy of the backfill, must never be written to. Either read it read-only or seed a separate fixture DB.
- Repo rule: never run `npm run build` / `npm run dev` directly.P0
2 months ago
#143
claude-usage: session titles, one-command machine setup, chart bucketing, folder-grouped repo viewFollow-on to #142. Four independent features, ordered by what unblocks the operator soonest.
# F1 — One-command setup on a second machine (do first: it is blocking real use)
Today, adding a machine means: clone, `node scripts/install.mjs`, then HAND-WRITE `.env` with values fetched out of Pulumi. The install script literally ends by telling you to go do that yourself.
A client machine needs only TWO values — `CLAUDE_USAGE_API_URL` and `CLAUDE_USAGE_SECRET`. No MongoDB: only the deployed server talks to Atlas. The repo is PUBLIC (github.com/votrungquan1999/claude-usage) so cloning needs no auth.
AC: one command installs and configures a new machine end to end, with the secret supplied once (flag or prompt). `.env` is written by the tool, not by hand. Re-running is safe.
Note: `resolveDotEnvPath` looks in `~/.claude/claude-usage/.env` first, then the repo root — so writing to the installed path is enough.
# F2 — Session titles in the session list
The list is currently NOT distinguishable: many rows share the same project and machine, and the session id appears only in the link target.
Claude Code already records a name. Transcripts carry `{"type":"ai-title","aiTitle":"Build Claude session usage dashboard","sessionId":"..."}` as its OWN record type — not attached to assistant turns — and it can be rewritten during a session (3 such records in one observed transcript), so LAST ONE WINS.
DECIDED, WITH EYES OPEN: this widens the aggregates-only rule. `aiTitle` is model-generated FROM the conversation, so it is content, not an aggregate. The operator explicitly accepted this after being shown the tradeoff. Update the sync spec's allowlist to say so — the guarantee is now "aggregates plus the session title", and the event-mapper allowlist test must be updated deliberately, never silently.
DO NOT ever upload `lastPrompt`, which sits in the same transcripts and is raw prompt text.
AC: the session list shows a name column; sessions without a title degrade gracefully; existing history needs a backfill re-run to populate.
# F3 — Chart bucketing: at most 20 bars
At 90-day and all-time windows the X axis is unreadable (see #132 spec, now marked "being fixed").
DECIDED: cap at 20 bars on EVERY window over 20 days — one rule, not two. This visibly changes the 30-day DEFAULT view to ~15 two-day buckets; the operator chose that over leaving 30d untouched.
Applies to BOTH per-day charts: cost-per-day AND model-mix, so the two stay readable together and their X axes line up.
SUBTLETY: model mix is share-of-spend. Buckets must sum cost and RECOMPUTE the share. Averaging percentages is wrong and will look plausible.
Suggested home: `dashboard-format.ts`, alongside the existing `rollUpDailySavings` / `rollUpEfficiencyByDay` helpers. Note it compiles into the CLIENT bundle, so no pricing arithmetic there.
# F4 — Repo view groups repo-less spend by FOLDER
REVERSES a #132 decision. Today every repo-less row collapses into one `(unattributed)` bucket, on the reasoning that "no repository" is the answer itself and spreading it across project names would hide that it is 54.8% of spend.
The operator has now seen that data and wants the opposite: group by folder instead. Real numbers behind the current bucket:
- git-repos/personal — 27,177 events, $3,225.04
- git-repos/concrete_engine — 2,319 events, $457.39
- .openclaw/workspace — 649 events, $195.70
Context worth keeping: these are unattributed CORRECTLY. `~/Documents/git-repos/personal` is not a repo — it CONTAINS 40 of them — so a session launched there has no single repository. Attribution is by the session's cwd, not by which repos got edited.
AC: the Repo tab shows repo-less spend split by folder rather than as one bucket. Mark the superseded #132 decision outdated and update that spec section — it currently states the opposite invariant as deliberate.P0
2 months ago
#144
claude-usage dashboard: drill down from a project/repo row to its sessionsOperator ask (2026-08-05, with screenshot of the Cost-per-day card on the Project tab): clicking a project or repo — in the totals table below the chart — should navigate to a detail view showing the SESSIONS for that project/repo. Today nothing on that card is clickable; the only way into a session is the flat "Sessions in this range" list or pasting an id into the lookup form.
## Constraints already established (do not re-derive)
1. **A Repo row spans several projectSlugs.** `mergeRepoRows` groups by `repoKey` (SHA-256 of the normalised git remote) and labels the group with the SHORTEST projectSlug in it. `mergeProjectRowsByRepoKey` does the same on the Project tab, minus the repo-less collapse. So "sessions for this row" is a group of slugs, not one slug — the four known worktree pairs (AI-rules-repo, AI-Kanban, bas-attendance, personal-infra) all merge this way.
2. **`repoKey` must never reach the browser** (#132 D31 — it is dictionary-confirmable, an identifier rather than an opaque token). The link therefore carries the visible LABEL; the server resolves label -> repoKey -> the slug set. Not a design choice.
3. **`(unattributed)` is a real, clickable answer** on the Repo tab — now a genuine ~7% residue of work outside any repository, post per-turn attribution (#143 F5). Drilling into it means "sessions with no repoKey", which is a different query shape from a named repo.
4. Session ownership is per EVENT, not per session — per-turn attribution (#143 F5) means one session's events can carry different projectSlug/repoKey values. So "sessions for a repo" must mean "sessions with at least one event attributed to it", and any cost shown must be the cost attributed to THAT repo, not the session's whole cost. This is the trap in the whole feature.
## Out of scope unless asked
Making the chart bars or legend clickable (recharts internals); the Machine/Model tabs, pending the operator's answer.P0
2 months ago
#148
Code review: ConcreteEngine/icp PR #37 — environments proxy middlewareReview https://github.com/ConcreteEngine/icp/pull/37 ("implemented environments proxy middleware", reis-mcmillian, feat/environments -> main, 3 files +168/-0). Checked out in worktree /Users/quanvo/Documents/git-repos/concrete_engine/icp-pr-37 (branch pr-37-review at origin/feat/environments). Running the review-changes fan-out pipeline with the nathan-pr-review house checklist folded into every lens. Holistic verdict: proceed-with-fan-out, all 6 lenses applicable. Lenses returned 27 findings (correctness 4, security 5, architecture 7, quality 5, tests 3, performance 3); 12 flagged for verification. Workspace: icp-pr-37/tmp/pr-37/review-changes/.P0
2 months ago
#150
claude-usage: model-mix chart draws holes where a model was simply unused that dayOperator report (2026-08-06, screenshot of "Model mix over time"): a black wedge sits between 2026-07-27 and 2026-07-28 where claude-opus-4-8 hands over to claude-opus-5, plus smaller holes along the top band.
Root cause: `modelMixByDay` only writes a key for models that HAVE a row that day, so a model absent on a day reaches the chart as `undefined` -> `asShare` -> `null` -> `connectNulls={false}` breaks the series. In a STACKED area chart that leaves an unfilled band between the series below and the series above, showing the page background.
The `null` semantics from D39 are correct for "this day had no priced spend at all" (share of nothing is undefined). They are wrong for "this model contributed none of a day that DID have spend" — that is a measured 0%.
Fix: emit every series key on every day that has priced spend, 0 where the model is absent.P0
2 months ago
#152
review-changes: label each finding's origin (introduced vs pre-existing)Add a finding-level `Origin` field to the review-changes skill so a reviewer can tell whether the change CAUSED the problem or it was already there. The agent surfaces origin; it must not judge/discount on it (severity and confidence stay independent).
Audit of the current skill (all 3 variants): no provenance field exists, and pre-existing issues are hard-dropped at 4 chokepoints — lens-common.md:7 (Scope) and :15 (What NOT to flag), node-verify.md:26+33 (pre-existing → REFUTE), node-merge.md:29 (confidence 0–25) + :57 (drop list). Also node-lens-correctness.md:19 and node-lens-performance.md:14.
Three cases the current binary rule gets wrong:
1. Touched-but-not-caused — diff moved/reformatted a line that was already wrong; surfaces unlabeled and mis-blames the author.
2. Pre-existing-but-newly-reachable — faulty code outside the diff, but the change is what now calls/exposes it. Currently REFUTED as out of scope = real false negative.
3. Pre-existing-and-worsened — existing N+1 the diff now runs per-request. Same deletion.
USER DECISIONS (2026-08-06):
- Scope = "Label + unblock newly-reached": three Origin values (introduced / pre-existing — touched / pre-existing — newly reached), AND verify stops auto-refuting the newly-reached+worsened case. Unrelated pre-existing issues stay OUT of the report.
- Effort = "Free signal, escalate when unsure": infer origin from the patch (+ line vs context); when ambiguous (moved code, rename, refactor) the lens marks it unconfirmed via Needs verification and the verify phase resolves it with git blame/log. No blanket git blame per finding.
Blast radius: skills/claude-code/review-changes (SKILL + 10 nodes), skills/cursor/review-changes (SKILL + 9 nodes, merge inline in SKILL.md), skills/antigravity/review-changes (single 213-line SKILL.md). Do NOT hand-edit .claude/skills/ dogfood copies — CLI-regenerated.P0
2 months ago
#153
UBET-4246 weekly ranking: count only points from markets created this weekWeekly user ranking should only include belief points earned from markets CREATED this week (currently it counts all points earned this week regardless of market age). Backend (belief_locker), worktree upredict-backend-ubet-4246, branch feat/UBET-4246-weekly-ranking-this-week-markets. Ticket description is only a Slack thread link (Slack MCP not authorized) — requirement detail to be confirmed with the user. Following orchestrated-feature-dev; workspace tmp/ubet-4246.P0
upredict-backend·feat/UBET-4246-weekly-ranking-this-week-markets2 months ago
#161
claude-usage: sync staleness signal, per-session carry timeline, dashboard heading structureThree independent features, ordered by value. Consolidates cards #158/#159/#160 (archived in favour of this one). Chosen by the operator from a wider list on 2026-08-08.
# F1 — Surface when a machine last synced (do first)
Every failure mode in `bin/sync.mjs` degrades to a silent no-op **by design** — no network, non-2xx, missing `.env`, unreadable transcript all return `{sent: 0}` and throw nothing. There is no local watermark, no `lastSynced` field, and no dashboard surface showing when a machine last succeeded. A machine can stop uploading entirely and nothing anywhere says so.
Not hypothetical: 2026-08-04 to 2026-08-06 this machine sent nothing — first `CLAUDE_USAGE_API_URL` pointing at a dead `localhost:3001`, then a stale `CLAUDE_USAGE_SECRET` returning 401 underneath it. Both present identically to "nothing to send". Caught only because the operator looked at the chart and noticed the bars had stopped advancing.
**AC:** a per-machine last-successful-sync figure on the dashboard, and a local warning in the status line when this machine has not uploaded in N hours. The status-line half is the one that reaches the operator without them going to look.
**Traps:**
- `{sent: 0}` means four indistinguishable things (nothing to send / wrong host / wrong secret / lock held). Record success where a 2xx with a real `{accepted, rejected}` body was actually seen — NOT where `syncTail` returned.
- A 200 alone is not success: posting to the app's base URL instead of `/api/sync` used to hit the dashboard page, return 200, and drop every event (R31).
- Do NOT make the status line block on a network call. It renders every turn.
- `/api/sync` is the only place that knows a sync succeeded, so server-side `lastSyncAt` keyed by machineId is the likely home — but the status-line warning may want a local source instead. That choice is the first decision.
# F2 — Per-session turn timeline: carry cost vs new work
The dashboard answers "how much" and, since #144, "which sessions". It does not answer **why a session was expensive**.
Claude Code re-reads the whole conversation every turn, so most of a long session's cost is *carry* — paying again for context that already existed. On a 438K-token session that was 78% of each turn. The local status line already computes carry; the dashboard shows none of it, so the one number that would change behaviour (compact earlier, split the task, delegate) is invisible where spend is actually reviewed.
**AC:** the existing session page (`src/app/session/[id]/page.tsx`) shows cost across the session's turns, split carry vs new. The useful shape is where the curve turns.
**Traps:**
- Check whether per-turn carry is derivable from already-stored fields (`inputTokens`, `cacheReadTokens`, `cacheWrite5m/1h`) or needs a new one. A new field must clear BOTH allowlists (mapper + `/api/sync`) and stay an aggregate — no transcript content, ever.
- `src/app/dashboard-format.ts` compiles into the CLIENT bundle and must never import `src/parser/pricing.mjs`.
- Sessions get long; `planDayBuckets` caps at 20 buckets for a reason.
# F3 — Card titles are not headings
Below the single `<h1>`, none of the six dashboard cards is a heading — shadcn's `CardTitle` renders a plain `<div>`. A screen-reader user has no heading structure to jump between. Surfaced by the e2e work (#142), recorded in the test-runner spec under "Known app-level gaps this surfaced".
**AC:** real heading elements for card titles across dashboard, drill-down and session pages, asserted in e2e so it cannot regress.
**Traps:**
- base-ui's `Button` with `nativeButton={false}` stamps `role="button"` on the pager's anchors, so they are NOT `link`s in the accessibility tree despite being `<a href>`. Any a11y assertion must account for it.
- No DOM harness in vitest (jsdom deliberately rejected on #132 — `getBoundingClientRect` returns zeros, producing false greens). Playwright is the only place this can be asserted.
**Related bug in the same spec section:** selecting a date window then *immediately* clicking a split tab loses the window — a real race between two URL-writing controls. Low severity. Fold in or split out, operator's call.
# Context
Reasoning, findings and the traps above are in `claude-usage/tmp/split-drilldown/JOURNAL.md` while that workspace survives, and in `docs/features/*/spec.md` permanently.P0
claude-usage·main2 months ago
#203
Plan + build 40-Q easy confidence test, language-agnostic (Py/C++), fundamentals + strings (LMS)Design ONE graded, untimed, EASY test for course c98f8f96 (Stem T-coding): 20 concept MC + 20 short coding problems. Scope = fundamentals review (input/variables, conditionals, loops, functions, lists) PLUS the new Data Structures & Strings lesson (strings, dict/tuple basics, simple algorithms). Every question must be language-agnostic: solvable in Python OR C++ (no Python-only syntax in MC; coding problems specified by input/output with reference solutions in BOTH languages). Goal: raise student confidence after the hard July 90-min test. Deliverable: scripts/data/*.ts TestDefinition + blueprint in lms/tmp/easy-40-test/; seed to Atlas only after approval.P0
last month
#206
Fix ai-rules `pull` dropping skill supporting files (+ follow-ups: exec bit, skill.ignore, UI file tree)Investigation found private-skill upload already sends the whole folder (collectSupportingFiles → supportingFiles[]), and sync/add/init write them on install — but `pull` (src/cli/commands/pull.ts ~L118) writes only SKILL.md, silently dropping every supporting file. The e2e pull test never asserted a supporting file so it stayed green.
Scope now: fix `pull` via /feature-dev-lite (test-first), record follow-ups.
Follow-ups (NOT in this card's scope, to be written down as a doc): preserve executable bit on install; `skill.ignore` file + guidelines for excluding files from upload; reviewer UI file tree for private skills. Base64-whole-folder approach was assessed and rejected (opaque blob, breaks in-browser edit, +33% size).P0
last month
#217
LMS: config for answer reveal display (side-by-side diff vs. correct answer + explanation)Two parts, run through orchestrated-feature-dev in /Users/quanvo/Documents/git-repos/personal/lms (branch feat/practice-mode-v1).
(1) Verify whether the LMS already supports uploading a file to generate test questions — including free-text questions. Repo has documents/adr/import-questions-ai.md and tmp/ artifacts from prior runs (question-media-upload-ui, pools-and-per-question-ai), so the answer may be "already built" or "partially built".
(2) Feature: add a config controlling how the answer is revealed to the student. Options discussed: show the student's answer side-by-side with a diff view, OR just show the correct answer + explanation. Scope of the config (per-test vs per-question vs global) is not yet decided.
Workspace: tmp/answer-reveal-display-config/P0
4 weeks ago
#240
UBET-4336 — Bet on the belief points chain (BE3)Epic UBET-4282 "In-App Currency Betting", ticket BE3 in tmp/UBET-4282/ticket-breakdown.md. Sprint 118, assignee Quan Vo, 2d4h estimate. Blocked by UBET-4335 (need_review, card #228), blocks UBET-4337.
Worktree: workspace/upredict-backend-ubet-4336, branch feat/UBET-4336-belief-points-bet, based on feat/UBET-4335-points-market-twin (tip 7765b46c, unpublished).
Ticket ask: place a bet staked in belief points. Fork the /betRequest path after the market-open check — points side asks a bet engine, money side builds the signed commitment as today. Check balance + take stake in one locked step. Write the bet already live (market_bet_open) since no chain confirmation is coming. No BetVolume credit for a points-staked bet. New not-enough-points error. Auto-vote, referee link, creator/referrer credits stay outside the fork.
Prerequisites: market_bet.user_id (backfilled from the creator-address join, incl. bet_aggregates in generate_leaderboard); relax 7 not-null chain-only columns (creator, commitment, commitment_salt, request_commitment, user_nonce, submission_deadline_block, refund_start_block); pushBets/autoRevealBets/event monitors must ignore points bets.
Prior design decisions live on card #211 (D5-D14) and tmp/UBET-4282/{DECISIONS,design-proposal,ticket-breakdown}.md.P0
3 weeks ago
#278
Growth method — is a high P/E paid for by growth? Generic method, tested on FPTBuild a generic, source-backed method for judging whether a company's growth justifies its multiple (non-banks + a bank track), freeze it BEFORE looking at FPT, then test it on FPT today and in a blind point-in-time replay at end-2021/2022/2023 against what happened next. Study only — no rule change until the user decides. User rulings 2026-09-26: test = today + past replay; scope = all companies including banks; FPT must not be the source of truth for the method.P0
last week
#282
Add step-through animations to Files, Sorting & Records (Python + C++)Pilot of animated explainers on the lesson website so students understand better. Follow-up to card #241 (which built the handouts). Operator choices: both tracks (Python + C++); Back/Next step buttons + Play + Reset with a caption per step; concepts = sort() + key=/comparison fn (§3, §5), split() + tuple/pair moving as one unit (§6, §7 after the try-it box — never show the wrong parallel-list answer), §8 what-changed diff; hidden in printed PDFs (print:hidden).P0
last week
#284
LMS: fix the UI defects from the visual QA report (qa-visual-defects/README.md)Orchestrated-feature-dev run in /Users/quanvo/Documents/git-repos/personal/lms (branch main at start, HEAD 76d888b). Follow-up to card #268 (the visual QA run that produced the report).
REQUIREMENT (user, verbatim): "help me check this dir in the lms project. they are UI defects. follow /orchestrated-feature-dev to handle those" — dir = lms/qa-visual-defects/ (README.md: 52 findings / 48 distinct defects, 9 root causes RC1-RC9 covering 27; report written against commit 04a679e).P0
last week