Take Configuration Status and Agent Activity (provider configuration, model/tool
calls and tokens) off the home; expose them as MarketingWidgets.ADMIN_WIDGETS
gated on marketing.admin.read. Needs Attention gains a business-worded row per
active channel that cannot send. Home and record widgets now require
marketing.read via MarketingPermissionChecker (HIDDEN) and Base.render no longer
returns a "You need marketing.read" shell.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
QRun-IO/.github#2 adds a tag-and-release job that signs vX with the
QRUN_TAG_SIGNING_KEY secret after Maven Central confirms the artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On release branches the bundle's version and the producer's differed, so the
bundle test that asserts they match failed, and released bundles recorded
SNAPSHOT as their provenance. help/*.yaml is now filtered:
version: ${project.version}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The record screens show date-times in the user's zone, so widget dates
printed in UTC disagreed with them (12:26 PM vs 5:26 PM UTC for the same
moment). Widgets now use the session's zone (else the instance's), with
the zone name: "Oct 14, 2026 12:26 PM CDT".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Needs Attention and Proposed Publication printed raw ISO instants; they
now read like "Oct 14, 2026 4:53 PM UTC". Proposed Publication said
"Not approved" for content whose approval an execution had consumed; it
now says who approved it and that an execution used it.
Found in the demo-server screenshots.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MarketingDemoServer (test sources, not shipped): H2 in memory, mock login
with every marketing permission, the verified starter data, and history
produced through the real actions (readiness, an agent draft on the
scripted provider, review, approval, schedule, a test-transport send).
Run it with the Next UI dev server; see its javadoc.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
marketing_metric_daily (19th table, system-written, child of the campaign)
holds per-day raw counts and unique actors per stage and event type,
recomputed after every outcome-event insert, update and delete, plus a
Rebuild Results campaign action. MeasurementReport sums the rollup and
counts campaign-wide unique actors with a backend COUNT_DISTINCT instead
of loading every event. MarketingOutcomeImporter lets hosts plug in
analytics sources, run by the Import Outcomes campaign action through
the normal (source, external id) dedupe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
help/qbit-marketing.yaml in the qqq#1198 bundle format (layer QBIT, 346
entries), with live {{values:}}, {{label:}} and {{maxLength:}} references.
HelpBundleCoverageTest is the stand-in coverage gate until core's
HelpBundleAssertions ships; registration follows with qqq#1198.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maxConcurrentAgentRuns and maxModelCallsPerMinute were per-JVM, in memory.
Preflight now fails stale RUNNING runs (no heartbeat for maxRunSeconds
plus 60s) and counts RUNNING runs across all products; the per-minute
limit counts model-call steps in the last minute and waits instead of
failing. Runs record heartbeatAt (new column) on each model call. The
policy's maxConcurrentAgentRuns override is now honoured.
The count-then-start window remains racy; the ConditionalUpdateAction
claim from qqq#1178 (QQQ 4.1.0-RC.7) closes it in a follow-up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qbit-crm 0.2.0 renames its tables to crm_* with no compatibility shims
(owner decision via the coordinator), so the gateway uses the snake_case
names directly and drops the camelCase fallback and LEGACY_* constants.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qbit-crm is renaming its tables to crm_* snake_case. QbitCrmGateway now
resolves each table from the instance at call time, preferring the
snake_case name and falling back to the legacy camelCase one, so either
qbit-crm generation works. Tests run the gateway against both schemes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move to qbit-assistant-provider-api 0.1.0-RC.12, whose types now live in
com.kingsrook.qbits.assistant.spi (ModelPricing included), and to
qbit-build-parent 2.1.2, which allows that package by default. Drop the
per-repository guardrail allow-lists. qbit-assistant-provider-openai is
only used by tests, so it becomes test scope; hosts that register it add
it themselves.
Fix the stale README status (RCs are on Central; hosted in Voyage#113).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QbitEmailTransport and MarketingRuntime use com.kingsrook.qbits.email.api
from qbit-email 0.1.0-RC.3; getStatus() keeps its mapping through
EmailApiReadiness.failedChecks (NOT_CONFIGURED only for the base URL and
unsubscribe key; a missing provider or brand address is still REJECTED
at send). qbit-build-parent 2.1.1 allows qbit-email's api by default, so
the temporary email allowances are gone; only the existing assistant
provider SPI allowances remain.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves qqq-orb@0.6.8 to qqq-orb@0.6.9, which passes --update-snapshots so cached SNAPSHOT dependencies are re-checked on every build (QRun-IO/qqq-orb#22).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in the qbit-email transport (#11). Conflicts are resolved in
favour of the RC.6/provider-api side, keeping qbit-email.
qbit-email is a new cross-qbit implementation dependency that the
enforced G1 guardrail rejects. It is allow-listed explicitly and
temporarily until qbit-email publishes an API (#13).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Marketing compiled against qbit-assistant internals, and installing it
pulled in the whole assistant runtime. It now depends on
qbit-assistant-provider-api (the provider SPI and ModelPricing) and on the
published qbit-assistant-provider-openai, both 0.1.0-RC.11. The local
OpenAiCompatibleModelProvider is gone, and tests use a local scripted
double, so the full assistant is not needed even in test scope.
Hosts register the published provider through ProviderSettings. Its
provider name is "openai-compatible", so Marketing Policy provider
overrides must use that name.
Also move to QQQ 4.1.0-RC.6 and qbit-build-parent 2.1.0 with the
guardrails enforced. The provider-api packages and provider-openai are
explicitly allow-listed.
Closes#9 (architecture review QRun-IO/qqq#1150, finding F5).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves from 0.1.0-SNAPSHOT to the first release candidate. Test schemas
gain the RC's email_provider_sender_address table and the message
from_address_id column where they copy the qbit's DDL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase (d) of QRun-IO/qbit-email docs/DESIGN.md section 11. qbit-email is an
optional dependency (0.1.0-SNAPSHOT until its first RC) used through one
adapter class behind a classpath and instance guard; without it the
existing behaviour is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>