Commit Graph

1721 Commits

Author SHA1 Message Date
Jesse_Chen 078c1cdc0d fix(rectification): keep collection denials from stalling the interview
Independent Staging Quality Gate / validate (push) Successful in 23m37s
Independent Staging Quality Gate / publish (push) Has been cancelled
A spoken no neither scored nor declined coverage, so relatives never closed and free-text turns left current_question null. Prefer a same-domain yearless scoring card before an unscoreable collect, resolve explicit collect denials as declined, and persist the next followup after an idle agent turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 22:37:32 +08:00
Jesse_Chen 187ef6ae24 feat(frontend): put a light/dark/system control in the account menu
Independent Staging Quality Gate / validate (push) Successful in 10m4s
Independent Staging Quality Gate / publish (push) Successful in 24m59s
Appearance is a radio group inside the avatar menu rather than a loose
button, so arrow keys reach it and the current choice is announced.
Picking one keeps the menu open, so the change is visible where it was
made.

"跟随系统" removes data-theme instead of writing a third value — the
media query has nothing to match otherwise. A synchronous script at the
top of <head> re-applies a pinned choice before the first paint; going
through next/script with any strategy would defer it and bring the flash
straight back, so the test asserts a plain script tag. Blocked storage
degrades to following the OS instead of throwing.

The stored value is browser state, so it is read through
useSyncExternalStore rather than synced into React state in an effect,
which also trips the cascading-render lint rule. localStorage only fires
`storage` in other tabs, so a same-tab write notifies its own listeners
and every open tab stays in step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-08-29 12:12:06 +00:00
Jesse_Chen c2d705ef6e feat(frontend): add a warm dark theme and close the DESIGN.md drift
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
The palette is restated for dark rather than inverted: elevation reads
through lightness on dark and through darkness on light, so the floor is
the darkest surface here and the second-lightest there. The clay hue is
kept and lifted, because #85432f is 2.1:1 on a dark ground. All 37
themeable tokens are covered, in an OS-preference block and a data-theme
block that a contract test keeps identical, and ink, action, danger,
success and warning are asserted at 4.5:1 against the dark canvas.

Four raw colors that would have stayed light-theme values are tokenised
(the avatar hairline, the sheen sweep, a one-off shadow, a literal
warning hex). The QR keeps literal white in both themes, since scanners
need light modules to be light, and print keeps white paper.

The four root boundary pages cannot read a token, so they restate the
handful they need in both themes. forbidden.tsx also stops painting a
bespoke near-black page in four colours that appear nowhere in the
palette, which broke the rule that dark ink is never a page-scale
surface.

Also fixes what the audit found in DESIGN.md itself: two ink values that
had drifted from the code, a motion tier documented at 360ms that was
never implemented, a breakpoint section claiming three tiers where the
stylesheet has eleven, an undocumented report-paper palette, and an admin
section describing a bespoke panel that antd + Refine replaced. Five
zero-reference admin rules go with it.

The sidebar gets the accent, opaque drawer, heading rank and empty-state
guidance settled earlier, and fenced code blocks finally get a container.

BUG-439.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-08-29 12:01:50 +00:00
Jesse_Chen d02fa8bbf3 fix(frontend): left-align the sidebar nav items on the mobile drawer
Independent Staging Quality Gate / validate (push) Successful in 11m52s
Independent Staging Quality Gate / publish (push) Successful in 16m19s
The nav buttons defaulted to centered for the desktop icon rail and were
flipped back by `[data-state="expanded"]`. That attribute tracks the
desktop open state, while the mobile drawer runs off `openMobile`, so on
a phone the labels rendered but the override never matched: 新建对话 and
我的报告 floated mid-drawer while every other row sat flush left.

Left alignment is the base layer now, correct for both the drawer and the
expanded desktop sidebar, and centering moved into the >=768px collapsed
block beside the rest of the rail rules. That was the only top-level
`[data-state=...]` selector left in the stylesheet.

personal-report-entry asserted `justify-content: center` on the report
button, which is the defect itself; the value is updated and the rest of
that assertion stands.

BUG-438.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-08-29 11:22:39 +00:00
Jesse_Chen 3cecb25f42 fix(rectification): stop a stale candidate-set prefix from hiding the choice card
Independent Staging Quality Gate / validate (push) Successful in 11m31s
Independent Staging Quality Gate / publish (push) Successful in 14m41s
Scoring scoped the contrast packet to the previous round's candidate set while
minting probes for the new one, so every later read re-prefixed the stored hash
and the persisted focus schema could never match. Mint one prefix per set and
compare splits by probe identity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
2026-08-29 08:51:19 +00:00
Jesse_Chen 0044d4f358 fix(frontend): style the paywall header and guard undefined class names
Independent Staging Quality Gate / validate (push) Successful in 10m8s
Independent Staging Quality Gate / publish (push) Successful in 9m39s
The onboarding paywall wrote `dialog-header`, a class no stylesheet
defines, so its close button stacked under the title instead of sitting
beside it. The session-delete confirm buttons had the same problem, and a
`message-entry` wrapper added in August had quietly killed the
`.message + .message` spacing rule in the main chat.

Fixes all three against the patterns already in the codebase, then adds a
contract test so the next undefined class fails instead of shipping: it
scopes itself to our own class families so Tailwind utilities stay out,
strips CSS comments before deciding what counts as defined, and carries
an allowlist of the fifteen deliberate no-op modifiers that must shrink
rather than grow.

Also collapses the paywall's duplicate display heading into the intro
sentence, leaving one heading in the dialog.

BUG-434, BUG-435, BUG-436.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-08-29 05:40:29 +00:00
Jesse_Chen c960691ee5 fix(rectification): pass birthDate into the choice-path gate
Independent Staging Quality Gate / validate (push) Successful in 10m27s
Independent Staging Quality Gate / publish (push) Successful in 8m35s
The post-choice decision used a looser plan than the followup builder.
Load compute once in persistApplied and feed the same birthDate to both.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 12:57:10 +08:00
Jesse_Chen 57e5f92d40 fix(rectification): keep spoken collect from silencing the agent
Independent Staging Quality Gate / validate (push) Successful in 22m22s
Independent Staging Quality Gate / publish (push) Successful in 10m14s
Collect focus was leaking discriminator probes into the agent prompt and
inheriting choice identity. Mark spoken questions, hide current_probe
unless a real choice card exists, strip fallback identity, log persist
failures, and align the decision probe with the plan including birthDate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 11:47:57 +08:00
Jesse_Chen a50c62a66c fix(frontend): restore root 404 styles and unify inline wait spinners
Independent Staging Quality Gate / validate (push) Successful in 9m45s
Independent Staging Quality Gate / publish (push) Successful in 9m4s
Root error/not-found pages lost all CSS after globals left the shared
layout. Inline the same token fallbacks as global-error so admin stays
off the chat stylesheet. Collapse three LoaderCircle spins into one
InlineSpinner, and build greeting fixtures in local time so UTC CI
does not hit the night-time copy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 10:56:04 +08:00
Jesse_Chen 86d6923e6e fix(rectification): stop discriminator followup from dropping user evidence
Independent Staging Quality Gate / validate (push) Successful in 10m10s
Independent Staging Quality Gate / publish (push) Successful in 7m25s
Decision and question ranking now share contrast option completion, so a
missing style card cannot deadlock the interview with a dead-end reply.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 10:23:34 +08:00
Jesse_Chen 31b54aa71d fix(frontend): say the database is missing, not Supabase
Independent Staging Quality Gate / validate (push) Successful in 9m34s
Independent Staging Quality Gate / publish (push) Successful in 7m21s
Self-hosted PostgreSQL is the runtime. A missing APP_DATABASE_URL
must not tell users the retired hosted service is unconfigured.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 09:44:53 +08:00
Jesse_Chen 3198fb6b2b perf(frontend): split chat streaming, load Inter, isolate admin CSS
Independent Staging Quality Gate / validate (push) Successful in 10m14s
Independent Staging Quality Gate / publish (push) Successful in 11m5s
Settled messages no longer rebuild on every token, Inter is actually
requested, and admin routes drop the 33 KB chat stylesheet. Root
force-dynamic is gone so public shells can prerender without changing
the no-store Cache-Control contract.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 03:39:43 +08:00
Jesse_Chen bf697d71a2 docs(frontend): task book for the nine-item web optimization pass
Derived from a static audit of frontend/ and web/ at staging 87f32d59.
The audit ran without node_modules, so no build, eslint, or tsc was
executed; every size and timing claim is inferred and task 0 requires
the executing agent to re-measure before acting on it.

Sequencing follows the repository's own history. The React Compiler
route stays closed per PROGRESS-react-compiler-20260817.md and
BLOCKED.md: Home fails on upstream compiler Todo/Invariant errors, not
on repository code, and neither compiler version raised the
project-wide success count above 134. A render benchmark gates the two
performance tasks, because the same missing benchmark already blocks
the 44-component decision recorded in BLOCKED.md.

Dark mode is left out as a product decision rather than an agent task.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
2026-08-28 18:38:53 +00:00
Jesse_Chen 87f32d596f test(rectification): lock holdout cards, style-kind scoring, and strong B conflicts
Independent Staging Quality Gate / validate (push) Successful in 15m6s
Independent Staging Quality Gate / publish (push) Successful in 16m19s
Ask-holdout now requires a renderable choice frame. Scoring uses the same effective contrast kind as rendering, because the engine-varga.d9/d10 fork was live. varga_style weak_yes counts as a strong conflict; existence weak_yes still does not.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 01:45:39 +08:00
Jesse_Chen a3f4e7128b docs(rectification): mark v4 intake cases as already seen, not sealed
Keep the four migrated cases in the queue. Record prior score exposures, distinguish migrated review from a fresh biography audit, and reject exposed or auto-attested cases from blind holdout use.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 01:33:20 +08:00
Jesse_Chen dc2879020a docs(rectification): bind sealed holdout metrics to the frozen scorer identity
The published six keys stay on the 2026-07-21 freeze. Current-tree sidecar numbers remain diagnostic and unlabeled as release metrics. Remove the unused v2 PILOT_REPORT_PATH.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 01:23:34 +08:00
Jesse_Chen 3dc2af0c96 docs(rectification): audit two holdout dates and open the v4 intake
Independent Staging Quality Gate / validate (push) Successful in 10m22s
Independent Staging Quality Gate / publish (push) Successful in 10m17s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:54:37 +08:00
Jesse_Chen 9d80498316 docs(rectification): record v3 sealed holdout as evaluated not missing
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:54:37 +08:00
Jesse_Chen fe0afdaddb fix(rectification): require a renderable card before holdout validation
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:30:04 +08:00
Jesse_Chen e41eaace8d fix(rectification): score varga-style groups at equal weight
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:15:21 +08:00
Jesse_Chen adfc75af8c test(rectification): keep collection asking when scores separate before method coverage
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 00:06:17 +08:00
Jesse_Chen 2c5e8bf2e6 fix(rectification): share datedPrecision for quarter and range events
Independent Staging Quality Gate / validate (push) Successful in 24m33s
Independent Staging Quality Gate / publish (push) Successful in 13m11s
Training already counted quarter/range as dated, while the inference ledger mapped them to unknown and left the events unused.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 23:19:09 +08:00
Jesse_Chen 53eb815c95 fix(rectification): read credible_range as the still-valid union
Write and read used different range definitions at the same lead of 8, so a real separation always fail-closed the candidate projection.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 23:12:16 +08:00
Jesse_Chen 7de36e11d6 fix(rectification): align leftover prompt and focus tests with the shrunk agent contract
Independent Staging Quality Gate / validate (push) Successful in 27m23s
Independent Staging Quality Gate / publish (push) Successful in 52m48s
Independent Staging Quality Gate 2141 failed because four tests still matched the old Mastra prompt wall and treated an unrenderable focus as null.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 20:56:58 +08:00
Jesse_Chen 63b4591aae fix(rectification): surface dropped probes and filter tools by the decision
Independent Staging Quality Gate / validate (push) Failing after 17m9s
Independent Staging Quality Gate / publish (push) Has been skipped
Silent unrenderable discriminators, a missing question-contract golden, and a always-on tool table were hiding fail-closed drops behind the prompt wall.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 20:31:15 +08:00
Jesse_Chen 69c3e94920 fix(rectification): share decideFromDossier across projections and treat a sole candidate as a close, not a tie
Independent Staging Quality Gate / validate (push) Successful in 11m43s
Independent Staging Quality Gate / publish (push) Successful in 40m51s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 19:21:28 +08:00
Jesse_Chen 30d8c78d19 fix(rectification): fail-close snapshot fingerprints without rewinding discrimination
Independent Staging Quality Gate / validate (push) Successful in 11m24s
Independent Staging Quality Gate / publish (push) Successful in 15m48s
Missing evidence fingerprints are stale, not current. Stale snapshots keep asking discriminators when a probe exists, and offer-candidates refuses until the ledger matches.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 18:42:18 +08:00
Jesse_Chen 0eb740a6b8 fix(rectification): keep holdout, D9 probes, and asked keys on the decision boundary
Independent Staging Quality Gate / validate (push) Successful in 10m33s
Independent Staging Quality Gate / publish (push) Successful in 16m24s
Reserve a month-or-better holdout, degrade unsigned D9/D10 to existence, and treat ledger keywords as mention-only so remaining discriminators stay in the pool.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 18:04:34 +08:00
Jesse_Chen 68f0759eef fix(rectification): persist the next interview after a choice tap
Independent Staging Quality Gate / validate (push) Successful in 13m56s
Independent Staging Quality Gate / publish (push) Successful in 16m46s
Closing a discriminator used to leave GET without a card after refresh.
Write the next dated question in the same request, skip childhood career
and move probes, and do not continue a read-only turn when that question
is already persisted.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 16:30:09 +08:00
Jesse_Chen 8c75ebb196 fix(rectification): keep discriminating after training gate without family coverage
Independent Staging Quality Gate / validate (push) Successful in 10m13s
Independent Staging Quality Gate / publish (push) Successful in 9m43s
Family and occupation method layers were blocking discrimination even when
training events were complete and a discriminator probe existed, so the agent
only acknowledged evidence and stopped.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 12:04:40 +08:00
Jesse_Chen 589ada6d03 fix(rectification): typecheck answered probe_id for staging publish
Independent Staging Quality Gate / validate (push) Successful in 10m47s
Independent Staging Quality Gate / publish (push) Successful in 11m26s
Docker next build failed on ProbeAnswer.id and optional decisionReceipt,
so staging never received the month-lock SHA.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 11:00:18 +08:00
Jesse_Chen 797a423af7 fix(rectification): refresh 10.0.13 package hash after month-lock copy
Independent Staging Quality Gate / validate (push) Successful in 9m38s
Independent Staging Quality Gate / publish (push) Failing after 7m18s
The quality gate binds the hashed rectification skill; the engine-month
wording changed those bytes without updating the registry.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 10:33:39 +08:00
Jesse_Chen 68a78af9e1 fix(rectification): ask reverse-inference probes at engine dasha months
Independent Staging Quality Gate / validate (push) Failing after 8m39s
Independent Staging Quality Gate / publish (push) Has been skipped
Keep Vimshottari/Narayana start dates instead of truncating to year, so
same-year month splits can appear on the choice card.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 10:20:05 +08:00
Jesse_Chen 4767b34ff0 fix(rectification): skip covered-domain existence probes, then pick max gain
Independent Staging Quality Gate / validate (push) Successful in 9m42s
Independent Staging Quality Gate / publish (push) Failing after 8m9s
Dated evidence in a domain no longer yields another existence question
in that domain. Remaining varga discriminators all stay in the pool so
the next card is whichever unused split scores highest.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 09:59:45 +08:00
Jesse_Chen ca6252ecb6 fix(rectification): ask from the scored probe catalog, not snapshot leftovers
Independent Staging Quality Gate / validate (push) Successful in 9m30s
Independent Staging Quality Gate / publish (push) Has been cancelled
Empty snapshot candidates were starving remaining D24 splits, so the
TypeScript follow-up chain asked the low-gain Python career probe.
Read paths now share one inference+engine catalog and yield a stale
low-gain distinguish card to the current winner.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 09:48:57 +08:00
Jesse_Chen 4bf074b2bf fix(rectification): show choice-card prompt instead of hiding it
Independent Staging Quality Gate / validate (push) Successful in 9m18s
Independent Staging Quality Gate / publish (push) Successful in 6m59s
BUG-401 hid the legend to avoid duplicating Agent copy. After the
question contract, the Agent only leads in, so the persisted stem
must be visible on the card.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 09:10:56 +08:00
Jesse_Chen 912ad34303 docs(bugs): record staging deploy evidence for BUG-405
Independent Staging Quality Gate / validate (push) Successful in 12m28s
Independent Staging Quality Gate / publish (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 01:32:00 +08:00
Jesse_Chen 3ae22f5768 test(rectification): expect unsure outcome on remaining D24 splits
Independent Staging Quality Gate / validate (push) Successful in 10m14s
Independent Staging Quality Gate / publish (push) Successful in 10m7s
The four-option probe contract adds a non-scoring unsure row; keep the D24 discriminator assertion aligned with that packet shape.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 01:06:30 +08:00
Jesse_Chen 7f82428b44 fix(rectification): unify discriminator question contract and rank by information gain
Independent Staging Quality Gate / validate (push) Failing after 11m51s
Independent Staging Quality Gate / publish (push) Has been skipped
Python and TypeScript now share a four-option probe contract, persist Focus before asking, and pick the highest-value renderable probe instead of preferring low-gain career events over D24.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 00:25:35 +08:00
Jesse_Chen 85db4591d3 fix(rectification): resolve typed focus answers deterministically
Independent Staging Quality Gate / validate (push) Successful in 19m52s
Independent Staging Quality Gate / publish (push) Successful in 53m47s
2026-08-27 20:31:05 +08:00
Jesse_Chen f3327235ea fix(rectification): remove static interview fallbacks
Independent Staging Quality Gate / validate (push) Successful in 10m50s
Independent Staging Quality Gate / publish (push) Successful in 13m29s
2026-08-27 16:40:47 +08:00
Jesse_Chen 5f855c610c fix(rectification): keep candidate state coherent
Independent Staging Quality Gate / validate (push) Failing after 15m32s
Independent Staging Quality Gate / publish (push) Has been skipped
2026-08-27 13:59:38 +08:00
Jesse_Chen 518119acbd fix(rectification): continue after structured choices
Independent Staging Quality Gate / validate (push) Successful in 12m35s
Independent Staging Quality Gate / publish (push) Successful in 15m16s
2026-08-27 09:23:32 +08:00
Jesse_Chen 1c0ee8db13 fix(rectification): reject synthetic stale probes
Independent Staging Quality Gate / validate (push) Successful in 13m3s
Independent Staging Quality Gate / publish (push) Successful in 16m3s
2026-08-27 00:28:14 +08:00
Jesse_Chen 7d6b88c886 fix(rectification): honor persisted probe focus
Independent Staging Quality Gate / validate (push) Successful in 14m51s
Independent Staging Quality Gate / publish (push) Successful in 17m0s
2026-08-26 22:17:15 +08:00
Jesse_Chen 60cbe8a75e fix(web): read migration filenames through a definer instead of app_runtime
Independent Staging Quality Gate / validate (push) Successful in 19m18s
Independent Staging Quality Gate / publish (push) Successful in 33m22s
Staging web never became healthy because /api/health selected migration.schema_migrations as app_runtime, which is forbidden, so Docker rolled the image back.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 20:21:49 +08:00
Jesse_Chen fa2b1be852 merge origin/staging before staging delivery
Independent Staging Quality Gate / validate (push) Successful in 13m45s
Independent Staging Quality Gate / publish (push) Successful in 11m18s
Keep BUG-395 publish TypeScript records alongside the training-gate fix.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 19:37:47 +08:00
Jesse_Chen b1173f7245 fix(web): count only training events for discrimination and split user-stop from validated range
Three collected events with a reserved holdout were stalling because the discriminator door counted holdout. Public selection_allowed still had snapshot fallbacks, and health only proved the image SHA.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 19:36:04 +08:00
Jesse_Chen 0511bc48c7 fix(web): type holdout followups and stop duplicate core re-exports
Independent Staging Quality Gate / validate (push) Successful in 10m2s
Independent Staging Quality Gate / publish (push) Successful in 9m36s
Staging publish next build failed after validate skipped production TypeScript, so holdout unions and the decision barrel never reached the image.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 18:32:25 +08:00
Jesse_Chen a0ce55f066 fix(web): drive rectification from candidate contrast and allow range close
Independent Staging Quality Gate / validate (push) Successful in 11m17s
Independent Staging Quality Gate / publish (push) Failing after 9m28s
Showing a choice card is no longer treated as completion. Distinguish probes
require real candidate groups, holdout stays out of scoring, and ordinary
sessions can finish with a credible range instead of an exact-minute gate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 17:19:26 +08:00