From 9d0d3068fbfbfc35f25269a8a48a26a6ee2045cf Mon Sep 17 00:00:00 2001 From: Keysat Date: Thu, 18 Jun 2026 20:25:34 -0500 Subject: [PATCH] Bump package version to v0.1.0:94 (NL-query matched-only fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ships the comms_by_user / email_counts_by_user matched-only fix to the box. No schema change, no UI change — version migrations are no-ops. --- start9/0.4/startos/utils.ts | 5 +++-- start9/0.4/startos/versions/index.ts | 5 +++-- start9/0.4/startos/versions/v0.1.0.94.ts | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 start9/0.4/startos/versions/v0.1.0.94.ts diff --git a/start9/0.4/startos/utils.ts b/start9/0.4/startos/utils.ts index 4868e6e..a4c4e47 100644 --- a/start9/0.4/startos/utils.ts +++ b/start9/0.4/startos/utils.ts @@ -58,8 +58,9 @@ export const PACKAGE_TITLE = 'Ten31 Database' // * 0.1.0:90 (give admins a UI path to provision the 'bot' role added in v89: the Settings → Admin edit-user role dropdown now offers "bot" alongside member/admin [the teammate-invite form stays member/admin only — provisioning an agent account is an admin re-classification, not an invite]; backend already accepted it; frontend-only, no schema change) // * 0.1.0:91 (clarify email-proposal note wording: the proposed grid note now NAMES who emailed whom — "{teammate} emailed {investor}" outbound / "{sender} emailed the team" inbound — instead of a bare "Sent"/"Received"; also fixes a misclassification where a sender on our corporate domain whose mailbox isn't enrolled read as "Received" [outbound now also matches our domain, public providers like gmail excluded so an LP's gmail never reads as ours]; going-forward only, no schema change. Matrix-side review tweaks — dash separators + redacting decided cards — ship on the Spark, not the s9pk) // * 0.1.0:92 (reminders & follow-ups, W1: new `reminders` table [in-app migration 0006; logical FK to fundraising_investors.id + denormalized name], full CRUD at /api/reminders [soft-delete; open/done/snoozed/cancelled; assignee; source human/bot/automation], read-only derived `reminder_status` grid column [overdue/due_soon/open — injected like pipeline_stage, filterable], orphan reconciler, Reminders page + Dashboard "Reminders Due" card + daily-digest "reminders due" section, and a per-investor last_activity_at recency rollup. Pure local CRM, no LLM path) -// * Current: 0.1.0:93 (natural-language query, W2: read-only "ask the database in plain English" — a curated, parameterized query catalog [backend/nl_query/] behind a strict slot validator [the trust boundary — no generic SQL / dynamic identifiers]; a local-Qwen translator maps a question→{intent,slots} via Spark Control so the question never leaves the box [no Claude, no redaction]; new endpoints POST /api/query/nl + GET /api/query/catalog [require_bot_or_admin, audited entity_type='nl_query'], results never returned to any model; no schema change. The Matrix Q&A client [dedicated room + ?/@bot trigger] ships on the Spark, not the s9pk) -export const PACKAGE_VERSION = '0.1.0:93' +// * 0.1.0:93 (natural-language query, W2: read-only "ask the database in plain English" — a curated, parameterized query catalog [backend/nl_query/] behind a strict slot validator [the trust boundary — no generic SQL / dynamic identifiers]; a local-Qwen translator maps a question→{intent,slots} via Spark Control so the question never leaves the box [no Claude, no redaction]; new endpoints POST /api/query/nl + GET /api/query/catalog [require_bot_or_admin, audited entity_type='nl_query'], results never returned to any model; no schema change. The Matrix Q&A client [dedicated room + ?/@bot trigger] ships on the Spark, not the s9pk) +// * Current: 0.1.0:94 (NL-query correctness fix: the comms_by_user + email_counts_by_user intents were counting/listing a user's ENTIRE captured sent corpus [internal/vendor/personal], not only email to a matched investor — they lacked the EXISTS email_investor_links gate that recent_emails + the Communications panel use. Added the matched-only gate to both [+ a regression test seeding an unmatched sent email]; no schema change, no UI change) +export const PACKAGE_VERSION = '0.1.0:94' export const DATA_MOUNT_PATH = '/data' export const WEB_PORT = 8080 diff --git a/start9/0.4/startos/versions/index.ts b/start9/0.4/startos/versions/index.ts index d03a253..d0190bb 100644 --- a/start9/0.4/startos/versions/index.ts +++ b/start9/0.4/startos/versions/index.ts @@ -54,8 +54,9 @@ import { v_0_1_0_90 } from './v0.1.0.90' import { v_0_1_0_91 } from './v0.1.0.91' import { v_0_1_0_92 } from './v0.1.0.92' import { v_0_1_0_93 } from './v0.1.0.93' +import { v_0_1_0_94 } from './v0.1.0.94' export const versionGraph = VersionGraph.of({ - current: v_0_1_0_93, - other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58, v_0_1_0_59, v_0_1_0_60, v_0_1_0_61, v_0_1_0_62, v_0_1_0_63, v_0_1_0_64, v_0_1_0_65, v_0_1_0_66, v_0_1_0_67, v_0_1_0_68, v_0_1_0_69, v_0_1_0_70, v_0_1_0_71, v_0_1_0_72, v_0_1_0_73, v_0_1_0_74, v_0_1_0_75, v_0_1_0_76, v_0_1_0_77, v_0_1_0_78, v_0_1_0_79, v_0_1_0_80, v_0_1_0_81, v_0_1_0_82, v_0_1_0_83, v_0_1_0_84, v_0_1_0_85, v_0_1_0_86, v_0_1_0_87, v_0_1_0_88, v_0_1_0_89, v_0_1_0_90, v_0_1_0_91, v_0_1_0_92], + current: v_0_1_0_94, + other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58, v_0_1_0_59, v_0_1_0_60, v_0_1_0_61, v_0_1_0_62, v_0_1_0_63, v_0_1_0_64, v_0_1_0_65, v_0_1_0_66, v_0_1_0_67, v_0_1_0_68, v_0_1_0_69, v_0_1_0_70, v_0_1_0_71, v_0_1_0_72, v_0_1_0_73, v_0_1_0_74, v_0_1_0_75, v_0_1_0_76, v_0_1_0_77, v_0_1_0_78, v_0_1_0_79, v_0_1_0_80, v_0_1_0_81, v_0_1_0_82, v_0_1_0_83, v_0_1_0_84, v_0_1_0_85, v_0_1_0_86, v_0_1_0_87, v_0_1_0_88, v_0_1_0_89, v_0_1_0_90, v_0_1_0_91, v_0_1_0_92, v_0_1_0_93], }) diff --git a/start9/0.4/startos/versions/v0.1.0.94.ts b/start9/0.4/startos/versions/v0.1.0.94.ts new file mode 100644 index 0000000..da96e52 --- /dev/null +++ b/start9/0.4/startos/versions/v0.1.0.94.ts @@ -0,0 +1,20 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +// NL-query correctness fix (W2). The comms_by_user and email_counts_by_user intents counted / +// listed a user's ENTIRE captured sent corpus (internal / vendor / personal mail), not only +// email to a matched investor — they were missing the `EXISTS email_investor_links` gate that +// recent_emails and the Communications panel's query_email_activity already use. Added the +// matched-only gate to both (mirroring query_email_activity), so "emails sent by " and +// "how many emails did send" answer about investor relationships only. No schema change, +// no UI change — up/down are no-ops. +export const v_0_1_0_94 = VersionInfo.of({ + version: '0.1.0:94', + releaseNotes: { + en_US: [ + 'Natural-language query fix: "emails sent by " and per-user email counts now count', + 'only email to matched investors (not internal/vendor/personal mail), matching the', + 'Communications panel.', + ].join(' '), + }, + migrations: { up: async () => {}, down: async () => {} }, +})