@ai-matrx/records 0.95.1 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/{client-DQWdJeFM.d.ts → client-D7bvxEZW.d.ts} +9 -0
- package/dist/{client-CEX4WdvX.d.cts → client-DKgbZUNt.d.cts} +9 -0
- package/dist/core/index.cjs +4 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -2
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +4 -0
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +4 -0
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-Bkh3C1Ao.d.ts → declareTable-D_CiMnXM.d.ts} +1 -1
- package/dist/{declareTable-DeQ9_TMb.d.cts → declareTable-VoNRi_j_.d.cts} +1 -1
- package/dist/questions/index.d.cts +1 -1
- package/dist/questions/index.d.ts +1 -1
- package/dist/react/index.cjs +4 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +9 -0
- package/dist/react/index.d.ts +9 -0
- package/dist/react/index.js +4 -0
- package/dist/react/index.js.map +1 -1
- package/dist/setup/index.cjs +4 -0
- package/dist/setup/index.cjs.map +1 -1
- package/dist/setup/index.d.cts +1 -1
- package/dist/setup/index.d.ts +1 -1
- package/dist/setup/index.js +4 -0
- package/dist/setup/index.js.map +1 -1
- package/dist/templates/index.cjs +124 -65
- package/dist/templates/index.cjs.map +1 -1
- package/dist/templates/index.d.cts +6 -1
- package/dist/templates/index.d.ts +6 -1
- package/dist/templates/index.js +124 -65
- package/dist/templates/index.js.map +1 -1
- package/dist/typed-table/index.cjs +4 -0
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +2 -2
- package/dist/typed-table/index.d.ts +2 -2
- package/dist/typed-table/index.js +4 -0
- package/dist/typed-table/index.js.map +1 -1
- package/dist/views/index.d.cts +1 -1
- package/dist/views/index.d.ts +1 -1
- package/package.json +4 -4
|
@@ -949,4 +949,9 @@ interface SafeReusesResult {
|
|
|
949
949
|
}
|
|
950
950
|
declare function safeReuses(spec: TemplateSpec, reuses: Reuse[], existingTables: ExistingTable[]): SafeReusesResult;
|
|
951
951
|
|
|
952
|
-
|
|
952
|
+
declare const DESCRIBE_RESULT_KIND = "describe_template_result";
|
|
953
|
+
declare function describeResultJsonSchema(): Record<string, unknown>;
|
|
954
|
+
/** The template as the check reads it: every JSON-text part opened (an object already open is left as it is). */
|
|
955
|
+
declare function parseDescribeTemplate(template: Record<string, unknown>): Record<string, unknown>;
|
|
956
|
+
|
|
957
|
+
export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESCRIBE_RESULT_KIND, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTION_NAMES, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeResultJsonSchema, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseDescribeTemplate, parseGateFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
|
|
@@ -949,4 +949,9 @@ interface SafeReusesResult {
|
|
|
949
949
|
}
|
|
950
950
|
declare function safeReuses(spec: TemplateSpec, reuses: Reuse[], existingTables: ExistingTable[]): SafeReusesResult;
|
|
951
951
|
|
|
952
|
-
|
|
952
|
+
declare const DESCRIBE_RESULT_KIND = "describe_template_result";
|
|
953
|
+
declare function describeResultJsonSchema(): Record<string, unknown>;
|
|
954
|
+
/** The template as the check reads it: every JSON-text part opened (an object already open is left as it is). */
|
|
955
|
+
declare function parseDescribeTemplate(template: Record<string, unknown>): Record<string, unknown>;
|
|
956
|
+
|
|
957
|
+
export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESCRIBE_RESULT_KIND, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTION_NAMES, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeResultJsonSchema, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseDescribeTemplate, parseGateFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
|
package/dist/templates/index.js
CHANGED
|
@@ -1696,9 +1696,9 @@ var ACCOUNT_DOOR_PATTERNS = [
|
|
|
1696
1696
|
instead: "Call create_fixture_user / fixture_user (aidream/aidream/testing/persona.py) or createFixtureUser / withFixtureUser (scripts/lib/persona.mjs). A rolled-back raw insert is allowed with a trailing matrx-fixture:rollback-only <reason> on the same line."
|
|
1697
1697
|
}
|
|
1698
1698
|
];
|
|
1699
|
-
function findPlaceholders(
|
|
1699
|
+
function findPlaceholders(text2) {
|
|
1700
1700
|
const hits = [];
|
|
1701
|
-
const lines =
|
|
1701
|
+
const lines = text2.split("\n");
|
|
1702
1702
|
for (const line of lines) {
|
|
1703
1703
|
if (ALLOW_PRAGMA.test(line)) continue;
|
|
1704
1704
|
for (const pattern of PLACEHOLDER_PATTERNS) {
|
|
@@ -2564,8 +2564,8 @@ function bookingColumnsProblem(tables, booking) {
|
|
|
2564
2564
|
if (clash) return `The booking page adds a "${label}" column to "${t.name}", which already has one ("${clash.key}"). Rename that column, or key it "${key}".`;
|
|
2565
2565
|
}
|
|
2566
2566
|
const status = t.fields.find((f) => f.key === "status");
|
|
2567
|
-
const
|
|
2568
|
-
if (status && (!
|
|
2567
|
+
const words2 = new Set((status?.choices ?? []).map((c) => c.toLowerCase()));
|
|
2568
|
+
if (status && (!words2.has("booked") || !words2.has("cancelled"))) {
|
|
2569
2569
|
return `The booking page writes "booked" and "cancelled" into "${t.name}"'s status, and its choices do not hold both.`;
|
|
2570
2570
|
}
|
|
2571
2571
|
return null;
|
|
@@ -2683,8 +2683,8 @@ var q = (n, d) => {
|
|
|
2683
2683
|
};
|
|
2684
2684
|
var qAdd = (a, b) => q(a.n * b.d + b.n * a.d, a.d * b.d);
|
|
2685
2685
|
var qCmp = (a, b) => a.n * b.d === b.n * a.d ? 0 : a.n * b.d < b.n * a.d ? -1 : 1;
|
|
2686
|
-
function parseNumeric(
|
|
2687
|
-
const m = /^\s*([+-]?)(\d*)(?:\.(\d*))?(?:[eE]([+-]?\d+))?\s*$/.exec(
|
|
2686
|
+
function parseNumeric(text2) {
|
|
2687
|
+
const m = /^\s*([+-]?)(\d*)(?:\.(\d*))?(?:[eE]([+-]?\d+))?\s*$/.exec(text2);
|
|
2688
2688
|
if (!m || !m[2] && !m[3]) return null;
|
|
2689
2689
|
const frac = m[3] ?? "";
|
|
2690
2690
|
let n = BigInt(`${m[1] === "-" ? "-" : ""}${m[2] || "0"}${frac}` || "0");
|
|
@@ -2734,9 +2734,9 @@ function unwrap(v) {
|
|
|
2734
2734
|
return v && typeof v === "object" && !Array.isArray(v) && "value" in v ? unwrap(v.value) : v;
|
|
2735
2735
|
}
|
|
2736
2736
|
function boundMoment(raw) {
|
|
2737
|
-
const
|
|
2738
|
-
if (!
|
|
2739
|
-
const at = Date.parse(/^\d{4}-\d{2}-\d{2}$/.test(
|
|
2737
|
+
const text2 = raw.trim();
|
|
2738
|
+
if (!text2) return null;
|
|
2739
|
+
const at = Date.parse(/^\d{4}-\d{2}-\d{2}$/.test(text2) ? `${text2}T00:00:00Z` : text2);
|
|
2740
2740
|
return Number.isNaN(at) ? null : at;
|
|
2741
2741
|
}
|
|
2742
2742
|
function storeFilterMatches(row, filter, _timeZone) {
|
|
@@ -2774,8 +2774,8 @@ function toFx(n) {
|
|
|
2774
2774
|
return { k: "call", f: n.name, args: n.args.map(toFx) };
|
|
2775
2775
|
}
|
|
2776
2776
|
}
|
|
2777
|
-
function parseGateFormula(
|
|
2778
|
-
const parsed = parseFormulaText(
|
|
2777
|
+
function parseGateFormula(text2) {
|
|
2778
|
+
const parsed = parseFormulaText(text2);
|
|
2779
2779
|
return parsed.ok ? toFx(parsed.ast) : parsed.error;
|
|
2780
2780
|
}
|
|
2781
2781
|
function formulaRefs(n) {
|
|
@@ -3125,8 +3125,8 @@ function capabilitiesUsed(spec) {
|
|
|
3125
3125
|
}
|
|
3126
3126
|
var DESIGNATED_REAL_NUMBERS = ["9498072145", "9496662578", "9497027626"];
|
|
3127
3127
|
var DIGIT_ZEROS = [1632, 1776, 1984, 2406, 2534, 2662, 2790, 2918, 3046, 3174, 3302, 3430, 3664, 3792, 3872, 4160, 6112, 6160, 65296];
|
|
3128
|
-
function normalizeForPhones(
|
|
3129
|
-
return
|
|
3128
|
+
function normalizeForPhones(text2) {
|
|
3129
|
+
return text2.normalize("NFKC").replace(/\p{Nd}/gu, (c) => {
|
|
3130
3130
|
const cp = c.codePointAt(0) ?? 48;
|
|
3131
3131
|
const zero = DIGIT_ZEROS.find((z) => cp >= z && cp <= z + 9);
|
|
3132
3132
|
return zero === void 0 ? c : String(cp - zero);
|
|
@@ -3140,8 +3140,8 @@ function nanpBad(area, exchange, line) {
|
|
|
3140
3140
|
const n = Number(line);
|
|
3141
3141
|
return exchange !== "555" || n < 100 || n > 199 || DESIGNATED_REAL_NUMBERS.includes(`${area}${exchange}${line}`);
|
|
3142
3142
|
}
|
|
3143
|
-
function phonesOutsideFictionalRange(
|
|
3144
|
-
const t = normalizeForPhones(
|
|
3143
|
+
function phonesOutsideFictionalRange(text2, phoneField = false) {
|
|
3144
|
+
const t = normalizeForPhones(text2);
|
|
3145
3145
|
const out = [];
|
|
3146
3146
|
for (const m of t.matchAll(INTL)) {
|
|
3147
3147
|
const digits = m[0].replace(/\D/g, "");
|
|
@@ -3195,11 +3195,11 @@ var PUBLIC_MAIL_DOMAINS = [
|
|
|
3195
3195
|
"163.com",
|
|
3196
3196
|
"web.de"
|
|
3197
3197
|
];
|
|
3198
|
-
function domainsIn(
|
|
3198
|
+
function domainsIn(text2) {
|
|
3199
3199
|
const found = /* @__PURE__ */ new Set();
|
|
3200
|
-
for (const m of
|
|
3201
|
-
for (const m of
|
|
3202
|
-
for (const m of
|
|
3200
|
+
for (const m of text2.matchAll(/[a-z0-9._%+-]+@([a-z0-9-]+(?:\.[a-z0-9-]+)+)/gi)) found.add((m[1] ?? "").toLowerCase());
|
|
3201
|
+
for (const m of text2.matchAll(/\bhttps?:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)+)/gi)) found.add((m[1] ?? "").toLowerCase().replace(/^www\./, ""));
|
|
3202
|
+
for (const m of text2.matchAll(/\bwww\.([a-z0-9-]+(?:\.[a-z0-9-]+)+)/gi)) found.add((m[1] ?? "").toLowerCase().replace(/\.$/, ""));
|
|
3203
3203
|
return [...found];
|
|
3204
3204
|
}
|
|
3205
3205
|
function numberedStreet(line) {
|
|
@@ -3285,7 +3285,7 @@ function peopleOf(spec) {
|
|
|
3285
3285
|
function proseOf(spec) {
|
|
3286
3286
|
return templateText(spec).filter(([at]) => !at.startsWith("tables ("));
|
|
3287
3287
|
}
|
|
3288
|
-
var words8 = (
|
|
3288
|
+
var words8 = (text2) => text2.toLowerCase().replace(/\{\{[^}]*\}\}/g, " ").split(/[^a-z0-9']+/).filter(Boolean);
|
|
3289
3289
|
var FOREIGN_INDEX = /* @__PURE__ */ new WeakMap();
|
|
3290
3290
|
function foreignIndexOf(other) {
|
|
3291
3291
|
let ix = FOREIGN_INDEX.get(other);
|
|
@@ -3305,8 +3305,8 @@ function foreignIndexOf(other) {
|
|
|
3305
3305
|
}
|
|
3306
3306
|
function foreignTextProblems(spec, library) {
|
|
3307
3307
|
const problems = [];
|
|
3308
|
-
const
|
|
3309
|
-
const hay =
|
|
3308
|
+
const text2 = templateText(spec);
|
|
3309
|
+
const hay = text2.map(([at, v]) => [at, v.toLowerCase()]);
|
|
3310
3310
|
const all = hay.map(([, v]) => v).join("\n");
|
|
3311
3311
|
const esc = (w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3312
3312
|
const find = (word) => {
|
|
@@ -3316,9 +3316,9 @@ function foreignTextProblems(spec, library) {
|
|
|
3316
3316
|
return hay.find(([, v]) => re.test(v));
|
|
3317
3317
|
};
|
|
3318
3318
|
const mine = proseOf(spec).map(([at, w]) => {
|
|
3319
|
-
const
|
|
3319
|
+
const words2 = words8(w);
|
|
3320
3320
|
const runs = [];
|
|
3321
|
-
for (let i = 0; i + 8 <=
|
|
3321
|
+
for (let i = 0; i + 8 <= words2.length; i += 1) runs.push(words2.slice(i, i + 8).join(" "));
|
|
3322
3322
|
return [at, runs];
|
|
3323
3323
|
});
|
|
3324
3324
|
for (const other of library.specs) {
|
|
@@ -3353,8 +3353,8 @@ var SYNONYM_WORDS = {
|
|
|
3353
3353
|
function labelMeans(f, sameAs) {
|
|
3354
3354
|
const label = norm(f.label);
|
|
3355
3355
|
if (sameAs.includes(label)) return true;
|
|
3356
|
-
const
|
|
3357
|
-
return Object.values(SYNONYM_WORDS).some((group) => group.some((w) =>
|
|
3356
|
+
const words2 = new Set(label.split(" "));
|
|
3357
|
+
return Object.values(SYNONYM_WORDS).some((group) => group.some((w) => words2.has(w)) && sameAs.some((s) => group.some((w) => s.split(" ").includes(w))));
|
|
3358
3358
|
}
|
|
3359
3359
|
var sameJson = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
3360
3360
|
var sortedJson = (v) => JSON.stringify(Object.keys(v).sort().map((k) => [k, v[k]]));
|
|
@@ -3946,8 +3946,8 @@ function validateTemplate(raw, options = {}) {
|
|
|
3946
3946
|
for (const by of dim.default?.by ?? []) if (!dimKeys.has(by.split(":")[0] ?? "")) say(`${at}.default.by`, `The first screen groups by "${by}", which is not a dimension.`);
|
|
3947
3947
|
for (const show of dim.default?.show ?? []) if (!inferredMeasures.has(show) && !newMeasures.has(show)) say(`${at}.default.show`, `The first screen shows "${show}", which is not a measure of this table.`);
|
|
3948
3948
|
});
|
|
3949
|
-
const checkMerge = (at, table,
|
|
3950
|
-
for (const m of
|
|
3949
|
+
const checkMerge = (at, table, text3) => {
|
|
3950
|
+
for (const m of text3.matchAll(MERGE_TOKEN)) {
|
|
3951
3951
|
const key = m[1] ?? "";
|
|
3952
3952
|
const f = fieldOf(table, key);
|
|
3953
3953
|
if (!f) say(at, `{{${key}}} does not resolve: the store merges only the fields of "${table}" (no today, no business details).`);
|
|
@@ -4855,7 +4855,7 @@ function validateTemplate(raw, options = {}) {
|
|
|
4855
4855
|
const f = fieldOf(table, key);
|
|
4856
4856
|
if (f?.absoluteDates) say(`tables (${table}).fields (${key})`, `"${f.label}" holds history (absoluteDates), so it cannot drive ${where}: schedule dates are relative to install day.`);
|
|
4857
4857
|
}
|
|
4858
|
-
const
|
|
4858
|
+
const text2 = JSON.stringify(raw);
|
|
4859
4859
|
const isPhoneField = (f) => f.parityType === "phone" || /(^|_)(phone|mobile|cell|fax|tel)(_|$)/.test(f.key) || /\b(phone|mobile|cell|fax)\b/.test(norm(f.label));
|
|
4860
4860
|
const phoneHits = /* @__PURE__ */ new Set();
|
|
4861
4861
|
for (const p of phonesOutsideFictionalRange(raw.business?.phone ?? "", true)) phoneHits.add(p);
|
|
@@ -4873,7 +4873,7 @@ function validateTemplate(raw, options = {}) {
|
|
|
4873
4873
|
for (const d of raw.provenance?.fictionalDomains ?? []) {
|
|
4874
4874
|
if (PUBLIC_MAIL_DOMAINS.includes(d.toLowerCase())) say("provenance.fictionalDomains", `"${d}" is a public mail provider real people use, so it is never fictional. Give each person a mailbox on an invented domain.`);
|
|
4875
4875
|
}
|
|
4876
|
-
for (const domain of /* @__PURE__ */ new Set([...domainsIn(
|
|
4876
|
+
for (const domain of /* @__PURE__ */ new Set([...domainsIn(text2), ...websites])) {
|
|
4877
4877
|
if (!declaredDomains.has(domain)) say("provenance.fictionalDomains", `"${domain}" is used but not declared fictional. List every invented domain in provenance.fictionalDomains (each is checked not to resolve).`);
|
|
4878
4878
|
}
|
|
4879
4879
|
const streets = new Set((raw.provenance?.fictionalStreets ?? []).map((s) => s.toLowerCase()));
|
|
@@ -4916,10 +4916,10 @@ function validateTemplate(raw, options = {}) {
|
|
|
4916
4916
|
if (seeded) say(`tables (${t.token}).fields (${f.key})`, `"${f.label}" is computed by the store (${f.parityType}), and ${seeded} seed row(s) write a value into it; leave it to the store.`);
|
|
4917
4917
|
}
|
|
4918
4918
|
}
|
|
4919
|
-
const label = (at,
|
|
4920
|
-
if (!
|
|
4921
|
-
const hit = findBannedLabel(
|
|
4922
|
-
if (hit) say(at, `"${
|
|
4919
|
+
const label = (at, text3, kind) => {
|
|
4920
|
+
if (!text3) return;
|
|
4921
|
+
const hit = findBannedLabel(text3, kind);
|
|
4922
|
+
if (hit) say(at, `"${text3}" is ${hit.why}. Use the practitioner's own word.`);
|
|
4923
4923
|
};
|
|
4924
4924
|
for (const t of own) {
|
|
4925
4925
|
label(`tables (${t.token}).name`, t.name, "table");
|
|
@@ -4952,9 +4952,9 @@ function validateTemplate(raw, options = {}) {
|
|
|
4952
4952
|
for (const [k, v] of Object.entries(r.values ?? {})) {
|
|
4953
4953
|
const f = byKey.get(k);
|
|
4954
4954
|
if (!f || isRelation(f) || f.parityType === "email" || f.parityType === "url" || f.parityType === "phone") continue;
|
|
4955
|
-
const
|
|
4956
|
-
if (typeof
|
|
4957
|
-
say(`tables (${t.token}).rows (${r.key}).${k}`, `"${
|
|
4955
|
+
const text3 = unwrap(v);
|
|
4956
|
+
if (typeof text3 === "string" && !RELATIVE_DATE.test(text3) && STALE.test(text3)) {
|
|
4957
|
+
say(`tables (${t.token}).rows (${r.key}).${k}`, `"${text3}" says "${STALE.exec(text3)?.[0]}", which is only true on the day it was written. Put the date in a date field written relative to install day ("@today+1b 10:00"), and keep the text free of "today" and "next week".`);
|
|
4958
4958
|
}
|
|
4959
4959
|
}
|
|
4960
4960
|
}
|
|
@@ -4962,14 +4962,14 @@ function validateTemplate(raw, options = {}) {
|
|
|
4962
4962
|
for (const t of own) {
|
|
4963
4963
|
for (const f of t.fields) {
|
|
4964
4964
|
const at = `tables (${t.token}).fields (${f.key})`;
|
|
4965
|
-
const
|
|
4965
|
+
const text3 = `${f.key} ${norm(f.label)}`;
|
|
4966
4966
|
const e = effective(t.token, f);
|
|
4967
4967
|
const floor = sensitivityFloorOf(t, f);
|
|
4968
4968
|
if (floor === "restricted" && !(e.sensitivity === "restricted" && e.contextPolicy === "exclude")) {
|
|
4969
4969
|
say(at, `"${f.label}" is the kind of value that is restricted and kept from the AI (restricted + exclude).`);
|
|
4970
4970
|
} else if (floor === "confidential" && SENSITIVITY_RANK.indexOf(e.sensitivity) < 2) {
|
|
4971
4971
|
say(at, `"${f.label}" reaches a person or a home, so it is at least confidential.`);
|
|
4972
|
-
} else if (/note/.test(
|
|
4972
|
+
} else if (/note/.test(text3) && e.sensitivity === "public") {
|
|
4973
4973
|
say(at, `"${f.label}" is somebody's notes; notes are never public.`);
|
|
4974
4974
|
}
|
|
4975
4975
|
}
|
|
@@ -5154,8 +5154,8 @@ function validateTemplate(raw, options = {}) {
|
|
|
5154
5154
|
const status2 = fieldOf(e.table, "status");
|
|
5155
5155
|
if (!status2) say(at, `A booking table needs a choice field keyed \`status\` whose choices include "booked" and "cancelled"; "${e.table}" has none. Add it, so a held time can be confirmed and given back.`);
|
|
5156
5156
|
else if (isChoice(status2)) {
|
|
5157
|
-
const
|
|
5158
|
-
const missing = ["booked", "cancelled"].filter((w) => !
|
|
5157
|
+
const words2 = (status2.choices ?? []).map((c) => c.trim().toLowerCase());
|
|
5158
|
+
const missing = ["booked", "cancelled"].filter((w) => !words2.includes(w));
|
|
5159
5159
|
if (missing.length) say(`${at}`, `This table's Status is a list of choices, and it has no choice called ${missing.join(" or ")} \u2014 the booking page writes those words (custom.booking_declare refuses).`);
|
|
5160
5160
|
}
|
|
5161
5161
|
const columns = bookingColumnsProblem(tables, e);
|
|
@@ -5275,9 +5275,9 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
|
|
|
5275
5275
|
if (agent?.question?.expect) {
|
|
5276
5276
|
const qq = agent.question;
|
|
5277
5277
|
const ask = norm(qq.ask);
|
|
5278
|
-
const
|
|
5278
|
+
const words2 = (t) => norm(t).split(" ").filter((w) => w.length >= 4);
|
|
5279
5279
|
const askWords = new Set(ask.split(" "));
|
|
5280
|
-
const mentions = (t) => !!norm(t) && ask.includes(norm(t)) ||
|
|
5280
|
+
const mentions = (t) => !!norm(t) && ask.includes(norm(t)) || words2(t).some((w) => ask.includes(w.replace(/s$/, ""))) || words2(t).length === 0 && norm(t).split(" ").filter(Boolean).some((w) => w.length >= 3 && (askWords.has(w) || askWords.has(`${w}s`)));
|
|
5281
5281
|
for (const [k, v] of Object.entries(qq.expect.filter ?? {})) {
|
|
5282
5282
|
if (typeof v === "string" && !mentions(v) && !ask.includes(norm(v))) say("agent.question.ask", `It filters on ${k} = "${v}", and the question never says so.`);
|
|
5283
5283
|
}
|
|
@@ -5359,9 +5359,9 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
|
|
|
5359
5359
|
if (!t) return false;
|
|
5360
5360
|
if (says.includes(norm(t))) return true;
|
|
5361
5361
|
const long = [...new Set(norm(t).split(" ").filter((w) => w.length >= 4))];
|
|
5362
|
-
const
|
|
5362
|
+
const words2 = long.length ? long : [...new Set(norm(t).split(" ").filter((w) => w.length >= 2))];
|
|
5363
5363
|
const said = new Set(says.split(" "));
|
|
5364
|
-
return
|
|
5364
|
+
return words2.length > 0 && words2.filter((w) => said.has(w) || said.has(`${w}s`)).length >= Math.min(2, words2.length);
|
|
5365
5365
|
};
|
|
5366
5366
|
if (!a) return;
|
|
5367
5367
|
if (a.kind === "move" || a.kind === "edit" || a.kind === "archive" || a.kind === "restore") {
|
|
@@ -5462,9 +5462,9 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
|
|
|
5462
5462
|
const LABEL_MAX = 40;
|
|
5463
5463
|
const IMPLEMENTATION = /\b(?:the\s+)?(?:ai|a\.i\.|agent|assistant|llm|model)\b[^.]*\b(?:reads?|sees?|never|cannot|can't|won't|doesn't|does not|is kept)\b|\b(?:never|not)\b[^.]*\b(?:ai|agent)\b|\bthe store\b|\bthis field\b|\bthis column\b|\bthe booking page writes\b|\bwrites? (?:a |the )?(?:booked )?time here\b|\bcustom\.[a-z_]+|\{\{|\b[a-z]+_[a-z0-9_]+\b|\b(?:sum|avg|count|min|max)\s*\(|\s=\s/i;
|
|
5464
5464
|
const STAFF_VOICE = /\bwe\b|\bour system\b/i;
|
|
5465
|
-
const screen = (at,
|
|
5466
|
-
if (!
|
|
5467
|
-
const t =
|
|
5465
|
+
const screen = (at, text3, slot, opts = {}) => {
|
|
5466
|
+
if (!text3?.trim()) return;
|
|
5467
|
+
const t = text3.trim();
|
|
5468
5468
|
if (slot === "label" && (t.length > LABEL_MAX || t.split(/\s+/).length > 6)) say(at, `"${t}" is a label (${t.length} characters); keep it to a few words \u2014 the name of the thing, no explanation.`);
|
|
5469
5469
|
if (slot === "secondary" && (t.length > 60 || sentences(t) > 1)) say(at, `"${t}" is ${t.length} characters; help text is one line of at most 60, one sentence.`);
|
|
5470
5470
|
if (slot === "tooltip" && (t.length > 140 || sentences(t) > 1)) say(at, `"${t.slice(0, 60)}\u2026" is ${t.length} characters; a description is one sentence of at most 140.`);
|
|
@@ -5839,14 +5839,14 @@ var holdsPeople = (t) => t.subject ? t.subject === "person" : t.fields.some((f)
|
|
|
5839
5839
|
var GOOD_OUTCOME = /^(completed?|done|paid|approved|won|closed won|booked|confirmed|delivered|resolved|published|signed|passed|hired|accepted)$/i;
|
|
5840
5840
|
var BAD_OUTCOME = /^(cancell?ed|skipped|lost|closed lost|denied|rejected|no[- ]show|failed|overdue|declined|void(ed)?|refunded|churned|expired|blocked)$/i;
|
|
5841
5841
|
function sensitivityFloorOf(table, f) {
|
|
5842
|
-
const
|
|
5842
|
+
const text2 = `${f.key} ${norm(f.label)}`;
|
|
5843
5843
|
const billingTable = /(invoice|bill|statement|receipt|payment|charge|fee|order|account)/i.test(`${table.token} ${table.labelSingular ?? ""}`);
|
|
5844
5844
|
const criminalCharges = /(^|_)charges?($|_)/.test(f.key) && behaviorOf(f) === "text" && !billingTable;
|
|
5845
5845
|
const phoneLike = behaviorOf(f) === "text" && /\b(cell|mobile|phone)\b/.test(norm(f.label));
|
|
5846
5846
|
const personal = PERSONAL_ONLY.test(f.key) || /\b(medical conditions?|medications?|diagnos[ie]s)\b/.test(norm(f.label));
|
|
5847
5847
|
const floored = (RESTRICTED_KEY.test(f.key) || RESTRICTED_LABEL.test(norm(f.label)) || criminalCharges) && (!personal || holdsPeople(table));
|
|
5848
5848
|
if (floored) return "restricted";
|
|
5849
|
-
if (f.parityType === "phone" || phoneLike || f.parityType === "email" || /address|street/.test(
|
|
5849
|
+
if (f.parityType === "phone" || phoneLike || f.parityType === "email" || /address|street/.test(text2)) return "confidential";
|
|
5850
5850
|
return null;
|
|
5851
5851
|
}
|
|
5852
5852
|
|
|
@@ -6332,6 +6332,7 @@ function describeSpec(template) {
|
|
|
6332
6332
|
s.specVersion = 1;
|
|
6333
6333
|
if (typeof s.version !== "number") s.version = 1;
|
|
6334
6334
|
if (typeof s.audience !== "string") s.audience = "organization";
|
|
6335
|
+
if (s.audience === "personal") s.audience = "individual";
|
|
6335
6336
|
if (typeof s.cleanupTag !== "string" && typeof s.id === "string") s.cleanupTag = `describe:${s.id}`;
|
|
6336
6337
|
for (const k of ["relationships", "sharedBlocks", "views", "forms", "dimensions", "extras"]) if (!Array.isArray(s[k])) s[k] = [];
|
|
6337
6338
|
if (Array.isArray(s.tables)) s.tables = s.tables.map(describeTable);
|
|
@@ -6374,9 +6375,9 @@ function stemWord(w) {
|
|
|
6374
6375
|
if (s.length > 4 && (s.endsWith("y") || s.endsWith("e"))) s = s.slice(0, -1);
|
|
6375
6376
|
return s;
|
|
6376
6377
|
}
|
|
6377
|
-
function meaningWords(
|
|
6378
|
-
const
|
|
6379
|
-
return [...new Set(
|
|
6378
|
+
function meaningWords(text2) {
|
|
6379
|
+
const words2 = text2.replace(/([a-z])([A-Z])/g, "$1 $2").split(/[^A-Za-z0-9]+/).filter(Boolean).map((w) => w.toLowerCase()).filter((w) => !FILLER.has(w)).map(stemWord).filter(Boolean);
|
|
6380
|
+
return [...new Set(words2)].sort();
|
|
6380
6381
|
}
|
|
6381
6382
|
var same = (a, b) => a.length > 0 && a.length === b.length && a.every((w, i) => w === b[i]);
|
|
6382
6383
|
function sameMeaning(a, b) {
|
|
@@ -6916,31 +6917,31 @@ function fixFormulaRefs(spec, fixes) {
|
|
|
6916
6917
|
if (f.parityType !== "formula" || typeof f.formula !== "string") continue;
|
|
6917
6918
|
const others = t.fields.filter((x) => x.key !== f.key);
|
|
6918
6919
|
const labelFor = (name) => others.find((x) => x.label === name)?.label ?? others.find((x) => x.key === name)?.label ?? others.find((x) => same3(x.key, name))?.label ?? others.find((x) => same3(x.label, name))?.label;
|
|
6919
|
-
const
|
|
6920
|
+
const text2 = f.formula.replace(/^\s*=\s*/, "");
|
|
6920
6921
|
let out = "";
|
|
6921
6922
|
let i = 0;
|
|
6922
|
-
while (i <
|
|
6923
|
-
const c =
|
|
6923
|
+
while (i < text2.length) {
|
|
6924
|
+
const c = text2[i];
|
|
6924
6925
|
if (c === "{") {
|
|
6925
|
-
const j =
|
|
6926
|
+
const j = text2.indexOf("}", i);
|
|
6926
6927
|
if (j < 0) {
|
|
6927
|
-
out +=
|
|
6928
|
+
out += text2.slice(i);
|
|
6928
6929
|
break;
|
|
6929
6930
|
}
|
|
6930
|
-
const name =
|
|
6931
|
+
const name = text2.slice(i + 1, j).trim();
|
|
6931
6932
|
out += `{${labelFor(name) ?? name}}`;
|
|
6932
6933
|
i = j + 1;
|
|
6933
6934
|
} else if (c === "'" || c === '"') {
|
|
6934
|
-
const j =
|
|
6935
|
+
const j = text2.indexOf(c, i + 1);
|
|
6935
6936
|
if (j < 0) {
|
|
6936
|
-
out +=
|
|
6937
|
+
out += text2.slice(i);
|
|
6937
6938
|
break;
|
|
6938
6939
|
}
|
|
6939
|
-
out +=
|
|
6940
|
+
out += text2.slice(i, j + 1);
|
|
6940
6941
|
i = j + 1;
|
|
6941
6942
|
} else if (/[A-Za-z_]/.test(c)) {
|
|
6942
|
-
const m = /^[A-Za-z_][A-Za-z_0-9]*/.exec(
|
|
6943
|
-
const after =
|
|
6943
|
+
const m = /^[A-Za-z_][A-Za-z_0-9]*/.exec(text2.slice(i))[0];
|
|
6944
|
+
const after = text2.slice(i + m.length).trimStart()[0];
|
|
6944
6945
|
const label = after === "(" ? void 0 : labelFor(m);
|
|
6945
6946
|
out += label ? `{${label}}` : m;
|
|
6946
6947
|
i += m.length;
|
|
@@ -7672,7 +7673,7 @@ function describeVocabulary() {
|
|
|
7672
7673
|
field_shape: FIELD_SHAPE_FACTS,
|
|
7673
7674
|
formula_shape: FORMULA_SHAPE_FACTS,
|
|
7674
7675
|
relationship_shape: RELATIONSHIP_SHAPE_FACTS,
|
|
7675
|
-
phone_rule: "seed phone numbers are fictional: 555-0100 to 555-0199
|
|
7676
|
+
phone_rule: "seed phone numbers are fictional: 555-0100 to 555-0199 (e.g. (813) 555-0142); never a real-looking number, and never a number from a country the person did not name.",
|
|
7676
7677
|
team_rule: "the team (name, role, work email, mobile, start date) is the shared team_member block; do not declare a table with those fields \u2014 keep a table of your own to just name and role, or point a relation field at team_member.",
|
|
7677
7678
|
title_field: "a table's titleField is the key of a plain text-like field of that same table (a name, a title) \u2014 never a link to another table, a formula or a timed date"
|
|
7678
7679
|
};
|
|
@@ -7735,6 +7736,61 @@ function safeReuses(spec, reuses, existingTables) {
|
|
|
7735
7736
|
const out = { ...spec, tables: spec.tables.map((t) => rename.has(t.token) ? { ...t, ...rename.get(t.token) } : t) };
|
|
7736
7737
|
return { spec: out, reuses: kept, notes, converted };
|
|
7737
7738
|
}
|
|
7739
|
+
|
|
7740
|
+
// src/templates/describe/result-schema.ts
|
|
7741
|
+
var DESCRIBE_RESULT_KIND = "describe_template_result";
|
|
7742
|
+
var text = { type: "string" };
|
|
7743
|
+
var words = (list) => ({ type: "string", enum: [...list] });
|
|
7744
|
+
var jsonText = { type: "string", description: "one JSON object, as text" };
|
|
7745
|
+
var jsonTextList = { type: "array", items: jsonText };
|
|
7746
|
+
var DESCRIBE_TEXT_PARTS = ["tables", "relationships", "views", "forms", "extras"];
|
|
7747
|
+
function describeResultJsonSchema() {
|
|
7748
|
+
return {
|
|
7749
|
+
type: "object",
|
|
7750
|
+
required: ["__kind", "template", "notes", "reuses"],
|
|
7751
|
+
properties: {
|
|
7752
|
+
__kind: { type: "string", enum: [DESCRIBE_RESULT_KIND] },
|
|
7753
|
+
template: {
|
|
7754
|
+
type: "object",
|
|
7755
|
+
required: ["id", "useCase", "industry", "vertical", "job", "teaches", "business", "tables", "forms"],
|
|
7756
|
+
properties: {
|
|
7757
|
+
id: text,
|
|
7758
|
+
useCase: text,
|
|
7759
|
+
industry: words(INDUSTRY_GROUPS),
|
|
7760
|
+
vertical: text,
|
|
7761
|
+
job: words(TEMPLATE_JOBS),
|
|
7762
|
+
audience: words(TEMPLATE_AUDIENCES),
|
|
7763
|
+
teaches: words(TEACHES_FEATURES),
|
|
7764
|
+
business: jsonText,
|
|
7765
|
+
tables: jsonTextList,
|
|
7766
|
+
relationships: jsonTextList,
|
|
7767
|
+
views: jsonTextList,
|
|
7768
|
+
forms: jsonTextList,
|
|
7769
|
+
extras: jsonTextList
|
|
7770
|
+
}
|
|
7771
|
+
},
|
|
7772
|
+
notes: { type: "array", items: text },
|
|
7773
|
+
reuses: { type: "array", items: { type: "object", required: ["token", "existing_table_id"], properties: { token: text, existing_table_id: text } } }
|
|
7774
|
+
}
|
|
7775
|
+
};
|
|
7776
|
+
}
|
|
7777
|
+
function open(value, at) {
|
|
7778
|
+
if (typeof value !== "string") return value;
|
|
7779
|
+
try {
|
|
7780
|
+
return JSON.parse(value);
|
|
7781
|
+
} catch {
|
|
7782
|
+
throw new Error(`${at} was not valid JSON text.`);
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
function parseDescribeTemplate(template) {
|
|
7786
|
+
const out = { ...template };
|
|
7787
|
+
if ("business" in out) out.business = open(out.business, "business");
|
|
7788
|
+
for (const k of DESCRIBE_TEXT_PARTS) {
|
|
7789
|
+
const v = out[k];
|
|
7790
|
+
if (Array.isArray(v)) out[k] = v.map((x, i) => open(x, `${k}[${i}]`));
|
|
7791
|
+
}
|
|
7792
|
+
return out;
|
|
7793
|
+
}
|
|
7738
7794
|
export {
|
|
7739
7795
|
BAD_OUTCOME,
|
|
7740
7796
|
BOOKING_AVAILABILITY_FACTS,
|
|
@@ -7744,6 +7800,7 @@ export {
|
|
|
7744
7800
|
CHOICE_COLORS,
|
|
7745
7801
|
CHOICE_COLORS_DISTINCT_UP_TO,
|
|
7746
7802
|
DEFAULT_TEMPLATE_AGENT,
|
|
7803
|
+
DESCRIBE_RESULT_KIND,
|
|
7747
7804
|
DESIGNATED_REAL_NUMBERS,
|
|
7748
7805
|
ENTITY_REFERENCE_KINDS,
|
|
7749
7806
|
FORMULA_FUNCTION_NAMES,
|
|
@@ -7801,6 +7858,7 @@ export {
|
|
|
7801
7858
|
deferredRelations,
|
|
7802
7859
|
derivedFieldSpec,
|
|
7803
7860
|
describeCheck,
|
|
7861
|
+
describeResultJsonSchema,
|
|
7804
7862
|
describeSpec,
|
|
7805
7863
|
describeVocabulary,
|
|
7806
7864
|
digestSpec,
|
|
@@ -7829,6 +7887,7 @@ export {
|
|
|
7829
7887
|
numberedStreet,
|
|
7830
7888
|
packageDescribeResult,
|
|
7831
7889
|
parseAt,
|
|
7890
|
+
parseDescribeTemplate,
|
|
7832
7891
|
parseGateFormula,
|
|
7833
7892
|
parseNumeric,
|
|
7834
7893
|
pathOfAt,
|