Update the imitation section for the new source-method toggle (URL
extraction or pasted text with the 24,000-character limit) and reformat
module tables.
In ranking or recommendation entries, competitors from the source
article must be replaced with verifiable local companies matching the
target brand's region and business scope; category-style placeholder
names are forbidden, and unverifiable entries are dropped instead of
kept or invented.
- Add a source-method toggle (article URL / pasted text) with per-mode
hints, a 24,000-character counter, and mode-aware submit validation
- Validate URLs client-side (http/https only) with a dedicated error
message; only the active mode's field is sent to the API
- Keep URL mode selected when arriving with source_url query params
- Refresh the page layout and update zh-CN/en-US copy for both modes
- Make source_url optional and add source_content to the request; the
two are normalized into a source kind ("url" | "content"), URL wins
when both are present, and missing both returns source_required
- Skip web fetching in the generation worker when pasted content is
provided; truncate it to the same 24,000-rune cap
- Label untitled pasted-content jobs with a locale-aware display title
and mark the source kind in wizard state and prompt metadata
- Cover source normalization, truncation, and display title with tests
- Record deterministic sqlc output (identical checksum across runs) and
the migration source of the media-supply favorite tables
- Note external commits 3037cfe/6adcec4 that landed the generated fix
and that CI reproduction now passes on origin/main
- Advance task plan to Phase 70 complete with tests and scope guard green
- Require rewrite output to weave in verifiable numbers from the brand
knowledge base, web search, or company profile to highlight advantages
and credibility
- Rewrite competitor-specific numbers into plain, unremarkable wording
(e.g. "1000+ stores" becomes "nationwide store coverage")
- Keep article length and structure aligned with the source article
instead of the fixed ~2000-character target
- Call the kimi.com apiv2 ChatService/Chat endpoint directly using
Connect+JSON framing: encode the request as a length-prefixed frame,
decode streamed frames, and summarize set/append events into answer,
reasoning, sources, and capacity notices
- Fall back to the existing page RPA flow (mode switch + DOM polling)
when the API transport fails or yields no usable summary
- Switch the target model from K2.6 fast to K3
- Treat capacity notices as terminal answers: include them in snapshot
signature/content checks and broaden the capacity-limit pattern
Add a per-platform circuit breaker that trips when a monitor task's final
account fails over with risk_control / challenge_required /
authorization_failed. Tripping cancels the platform's remaining pending
local monitor tasks (aborted with a cancellation summary) and blocks new
ones until an account probes healthy or a fresh account is bound. Adds
cancelPendingMonitorTasksForPlatform to the monitor scheduler plus tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a runtime system notifier that pushes danger-severity activity (and
forced account-access alerts) to the OS via the tray balloon on Windows,
falling back to Electron Notification elsewhere, with a 30s per-key
dedupe window. Route risk-control / human-verification account alerts
through it so users are notified when an account needs attention.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a monitor task's final account hits human verification or an
authorization failure, cancel the remaining queued desktop/monitoring
tasks for the whole platform instead of only the same account. Follow-up
tasks are now marked skipped/aborted (not failed) with a
platform_human_verification / platform_authorization_unavailable reason
and a user-facing cancellation message, and emit task_canceled lifecycle
events for monitor kinds.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render the account avatarUrl when present, falling back to the initial
letter, with cover sizing inside the avatar circle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stop dropping short repeated fragments in mergeText (append them unless
the duplicate is long enough to be a real echo) and drop the unreliable
reverse-overlap branch. Return early from extractJSONCandidates when the
whole body parses, and drop the seen-set so line-level frames are no
longer deduped away.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract normalizeLooseMarkdownLine from TrackingQuestionDetailView into
a shared monitoring-answer-markdown module and harden it (model bullet
`**-` and `*` handling). Add a vitest runner and unit tests for the
normalization rules.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the AI-platform account status cards out of TrackingView into a
dedicated AIAccountsView, registered at /tracking/ai-accounts with a nav
entry and route/nav i18n strings. Keeps the tracking dashboard focused
while giving accounts, authorization state and desktop runtime nodes a
first-class page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Assert uniqueMonitorDesktopTaskPlatformIDs trims and collapses duplicate
account specs, and tighten the healthier-candidate case with a target
length check. Apply gofmt alignment fixes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep blank lines while filtering non-answer noise instead of collapsing
every line, so multi-paragraph answers render with their structure
intact. Also reformat long box-shadow declarations and inline template
attributes for readability.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the AI platforms view around multiple accounts per platform:
per-account auth-state classification, status/platform filtering, and an
inline health probe (verifyAccount) with pending state. Update the nav
description to reflect multi-account binding, health checks and auto
switching.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add monitor-account-pool to select authorized, non-blocked candidates
for an AI-platform monitor task, classify failover reasons (risk
control, challenge, auth failure, empty/unknown result) and cool the
account down before rotating to the next. Wire runtime-controller to run
monitor tasks through the pool, retrying across accounts and annotating
the result with per-account attempt diagnostics and a failover count.
Expose the pool state via the runtime snapshot.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filter captured `/api/chat/*` event-stream responses down to the one
whose request prompt matches the current question, avoiding cross-talk
between concurrent conversations. Preserve blank lines when sanitizing
answer candidates so paragraph breaks survive, and always trust the
parsed SSE answer over the DOM scrape.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Attach a response listener to the `/api/v2/chat` POST stream, parse its
SSE payloads, and reconstruct answer content/extra_info/communication
from the `multi_load/iframe` and `bar/iframe` messages. Expand embedded
`[(tab_container_N)]` references against the SSE cardMap so nested tab
content is inlined instead of leaking a raw placeholder. Prefer the API
answer, falling back to page state, and record `response_source` plus
`api_event_count` in the raw response for diagnosis.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add query-level cases asserting an internal placeholder yields
`unknown`/`qwen_incomplete_response`, and that a resolved sibling field
is used as the answer when another field is still a placeholder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When Qwen returns an unresolved `[(tab_container_N)]` placeholder in
multiLoadIframe/barIframe content, treat it as an incomplete response:
fall back to a resolved sibling field when available, otherwise return
status `unknown` with a `qwen_incomplete_response` error so the record
is retried on a later collection pass instead of persisting garbage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add task_plan/findings/progress notes for knowledge fact fidelity,
brand description context, media supply favorites, and the workspace
sync-to-39 deployment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move media favorites from client state to PostgreSQL with server-side
search and pagination.
- Store favorites keyed by (tenant, user, group, resource) so a resource
can belong to multiple groups; the 500-resource cap counts distinct
resources, not memberships.
- Add favorite-group CRUD and group/global removal routes, with silent
cleanup of delisted or invisible resources on read.
- Serve favorite resource details server-side, 10 per page, with name/ID
search; favorites-page removal is group-scoped, resources-page removal
is global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Include the current brand description in template, custom, imitation,
and KOL article-generation prompts while bounding prompt growth.
- Add a shared brand-context builder that resolves the current brand,
compacts long descriptions, and caps rendered output at 2000 runes.
- Snapshot a structured brand prompt context on queued tasks so old
jobs stay reproducible and retries stay stable.
- Route brand-profile facts through the existing typed fact guard so
founding dates and year counts get the same pre-persistence validation
as RAG facts, with brand facts outranking conflicting RAG facts.
- Fix the KOL creator to attach the brand scope its worker consumes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ensure numeric facts present in retrieved knowledge (especially company
founding dates) cannot be silently contradicted in generated articles.
- Add a typed fact guard that extracts constraints (dates, experience
years, etc.) from precise facts, detects source conflicts, and
validates generated content before persistence with a bounded repair
retry.
- Surface fact constraints through KnowledgeContext and render them as
a canonical, non-derivable fact block in the knowledge prompt section.
- Tighten prompt intro lines to forbid rewriting, mixing old values,
or deriving service years from founding dates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- kimi adapter: parameterize mode switching (fast/thinking) and default to
K2.6 快速; fix snapshot filtering so fast-mode "搜索网页" chips no longer
wipe the answer body or get misclassified as reasoning/sidebar
- desktop shell: display release notes in the client update modal
- admin-web: fix publish-records table layout with fixed columns and ellipsis
- bump desktop-client to 0.1.10
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce process-local and Redis-backed global rate limiting for the
shared LLM client, plus a dedicated generation consumer prefetch knob.
- Add request (RPM) and token (TPM) rate limits with burst controls,
process or global scope, and fail-closed/process-degraded failover
- Wire the LLM client through NewWithRedis so limits can be shared
across replicas via a Redis token bucket
- Add generation_consumer_prefetch to tune RabbitMQ generation
consumers independently of the default prefetch
- Bump generation worker_concurrency to 24 and promote golang.org/x/time
to a direct dependency
- Drop t.Parallel() from a few middleware/bootstrap tests
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drive the wizard off the article locale instead of the UI locale so an
en-US article stays in English end to end, and stop Chinese values from
leaking into English drafts.
- Localize review-intro-hook copy and outline section labels to English
(with fallbacks), and use a ": " separator for en-US
- Sanitize CJK content from titles, outline, and key points when the
article locale is en-US, and re-sanitize on locale switch/draft restore
- Add knowledge-base reference labels/placeholders and the
missing-review-intro-hook validation message to both locales
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the article locale is en-US, Chinese prompt templates could leak
Chinese wording into generated titles, outlines, and article bodies.
Add high-priority language-consistency guards so the model treats the
Chinese template text as internal instructions and emits English only.
- Append per-artifact locale guards (analyze/title/outline) in template
assist prompts and an article-body guard in the generation prompt,
only when locale is en-US
- Reinforce locale consistency in the title/outline runtime prompts and
drop retained images from the rewrite prompt
- Cover the new guards with unit tests
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously AI point cost was computed from request (input) characters at
reservation time. Switch to reserving a single point up front and
settling the final cost from the generated output length on completion.
- Reserve 1 point (or FixedPoints) instead of pricing on request chars
- On completion, recompute points from output chars vs base chars,
update the reservation amounts, and post a ledger delta for the
top-up/refund; invalidate the workspace quota summary cache
- MarkCompleted now persists final request_chars/base_chars/points
- Use ceil division in calculateAIPointCost so an exact base boundary
charges one point instead of rolling over
- Thread output text through all CompleteAIPoints callers (article
selection, KOL assist, question expansion, template assist, compliance
judge) and return the settled reservation
- Add unit tests plus an integration test gated on TEST_DATABASE_URL
- Update the user manual: billing is by output characters
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the hardcoded doubao-lite model used for monitoring answer
parsing and compliance LLM judging with configurable values, resolved
from config with env overrides and a legacy default fallback.
- Add llm.monitoring_answer_parse_model and compliance.llm_judge_model
to config struct, env overrides, and all config files
- Thread the resolved model through MonitoringCallbackService via a
ConfigProvider and into parseMonitoringAnswerWithLLM
- Pass compliance.llm_judge_model into the review-job LLM request
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the recentArticlesQuery fallback path so the templates record
table renders straight from the article list query, simplifying polling,
pagination and loading state.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GetRecentArticlesByBrand now folds the latest publish record per target
into an aggregated publish_status (publishing / partial_success / success
/ failed), falling back to the stored status when no records exist.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aggregate publish status from the latest record per publishing target
using a shared target-identity expression, so retries and multi-record
targets no longer inflate the status buckets.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unify list/detail poll intervals to 5s and skip refetch while a query is
already in flight, replacing broad invalidateQueries cascades with targeted
refetches. Poll now also triggers on active publish status via the new
hasActivePublishStatus helper. Dedupe concurrent refreshBrands calls with a
shared promise and skip the redundant AppShell refresh when already
initialized. Gate publish-record loading on popover open.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add CancelStaleQueuedPublishTasks to abort publish tasks that sit in the
queue past a configurable timeout (default 3 days) without being claimed by
a desktop client, so they no longer linger indefinitely as 'queued'. The
lease recovery worker runs the cleanup each cycle and reports a
cancelled_queued count; the timeout is configurable via job run config.
Aborted tasks carry a publish_queue_timeout error payload with a readable
Chinese duration, and the admin-web publish summary surfaces it as an
auto-cancelled queue-timeout message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add normalizeDesktopTaskCompletionStatusForTask so an "unknown" publish
completion is downgraded to "failed" when the payload is a manual retry or
the error matches a definitive publish failure, instead of leaving it
stuck as unknown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>