@ai-matrx/records 0.96.1 → 0.96.2

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.
@@ -1,5 +1,5 @@
1
- import { A as AgentSnapshotRow, T as TemplateSpec, a as TemplateTable, S as SharedBlockId, C as CapabilityWord, b as TemplateField, c as TemplateAgent, d as TemplateAutomation, e as TemplateBooking, f as TemplateChecklist, g as TemplateDashboard, h as TemplateDigest, i as TemplateDocument, j as TemplateDrillDown, k as TemplateDimensions, l as TemplateForm, m as TemplateNotification, n as TemplatePortal, o as TemplateRowAction, p as TemplateStageRules, q as TemplateView, r as TemplateMergeBinding, s as TemplateTryIt, t as TemplateWorkflow, u as TemplateFootprint, I as IndustryGroup, v as TemplateJob, w as TeachesFeature, x as TemplateViewKind, y as TemplateBookingWindow } from '../types-SezYoQ5_.cjs';
2
- export { z as CAPABILITY_WORDS, B as CATALOGUE_QUOTAS, D as CATALOGUE_STATUSES, E as CHOICE_COLORS, F as CHOICE_COLORS_DISTINCT_UP_TO, G as CatalogueRow, H as CatalogueStatus, J as ChoiceColor, K as ConfidentialLevel, L as ConfidentialRequest, M as DEFAULT_TEMPLATE_AGENT, N as ENTITY_REFERENCE_KINDS, O as INDUSTRY_GROUPS, R as RELATIVE_DATE, P as RetiredId, Q as SHARED_BLOCKS, U as SHARED_BLOCK_IDS, V as STRENGTHS, W as SharedBlock, X as SharedBlockField, Y as SharedBlockUse, Z as Strength, _ as TABLE_KERNEL_ID, $ as TEACHES_FEATURES, a0 as TEMPLATE_AUDIENCES, a1 as TEMPLATE_EXTRA_KINDS, a2 as TEMPLATE_JOBS, a3 as TEMPLATE_REFERENCE_DATE, a4 as TEMPLATE_SPEC_VERSION, a5 as TEMPLATE_VIEW_KINDS, a6 as TemplateAgentQuestion, a7 as TemplateAgentVariable, a8 as TemplateAudience, a9 as TemplateCalendarView, aa as TemplateChecklistStep, ab as TemplateConfidential, ac as TemplateConfidentialReader, ad as TemplateDashboardBlock, ae as TemplateDimensionOverride, af as TemplateDrillPath, ag as TemplateExtra, ah as TemplateExtraAgent, ai as TemplateExtraAgentVariable, aj as TemplateExtraKind, ak as TemplateFormField, al as TemplateFoundation, am as TemplateGalleryView, an as TemplateGridView, ao as TemplateGuideStep, ap as TemplateKanbanView, aq as TemplateMeasureOverride, ar as TemplatePortalTable, as as TemplateProvenance, at as TemplateSource, au as TemplateTableSettings, av as TemplateTimelineView, aw as TemplateViewSort, ax as UseCaseSingulars, ay as WalkAction, az as WalkAssertion, aA as WalkImport, aB as WalkMove, aC as WalkStep, aD as confidentialPending, aE as confidentialRequests, aF as footprintOf, aG as membersAddRowsSteps, aH as tableSettingsProblems, aI as whenRule } from '../types-SezYoQ5_.cjs';
1
+ import { A as AgentSnapshotRow, T as TemplateSpec, a as TemplateTable, S as SharedBlockId, C as CapabilityWord, b as TemplateField, c as TemplateAgent, d as TemplateAutomation, e as TemplateBooking, f as TemplateChecklist, g as TemplateDashboard, h as TemplateDigest, i as TemplateDocument, j as TemplateDrillDown, k as TemplateDimensions, l as TemplateForm, m as TemplateNotification, n as TemplatePortal, o as TemplateRowAction, p as TemplateStageRules, q as TemplateView, r as TemplateMergeBinding, s as TemplateTryIt, t as TemplateWorkflow, u as TemplateFootprint, I as IndustryGroup, v as TemplateJob, w as TeachesFeature, x as TemplateViewKind, y as TemplateBookingWindow } from '../types-BhGs3f8s.cjs';
2
+ export { z as CAPABILITY_WORDS, B as CATALOGUE_QUOTAS, D as CATALOGUE_STATUSES, E as CHOICE_COLORS, F as CHOICE_COLORS_DISTINCT_UP_TO, G as CatalogueRow, H as CatalogueStatus, J as ChoiceColor, K as ConfidentialLevel, L as ConfidentialRequest, M as DEFAULT_TEMPLATE_AGENT, N as ENTITY_REFERENCE_KINDS, O as INDUSTRY_GROUPS, R as RELATIVE_DATE, P as RetiredId, Q as SHARED_BLOCKS, U as SHARED_BLOCK_IDS, V as STRENGTHS, W as SharedBlock, X as SharedBlockField, Y as SharedBlockUse, Z as Strength, _ as TABLE_KERNEL_ID, $ as TEACHES_FEATURES, a0 as TEMPLATE_AUDIENCES, a1 as TEMPLATE_EXTRA_KINDS, a2 as TEMPLATE_JOBS, a3 as TEMPLATE_REFERENCE_DATE, a4 as TEMPLATE_SPEC_VERSION, a5 as TEMPLATE_VIEW_KINDS, a6 as TemplateAgentQuestion, a7 as TemplateAgentVariable, a8 as TemplateAudience, a9 as TemplateCalendarView, aa as TemplateChecklistStep, ab as TemplateConfidential, ac as TemplateConfidentialReader, ad as TemplateDashboardBlock, ae as TemplateDimensionOverride, af as TemplateDrillPath, ag as TemplateExtra, ah as TemplateExtraAgent, ai as TemplateExtraAgentVariable, aj as TemplateExtraKind, ak as TemplateFormField, al as TemplateFoundation, am as TemplateGalleryView, an as TemplateGridView, ao as TemplateGuideStep, ap as TemplateKanbanView, aq as TemplateMeasureOverride, ar as TemplatePortalTable, as as TemplateProvenance, at as TemplateSource, au as TemplateTableSettings, av as TemplateTimelineView, aw as TemplateViewSort, ax as UseCaseSingulars, ay as WalkAction, az as WalkAssertion, aA as WalkImport, aB as WalkMove, aC as WalkStep, aD as confidentialPending, aE as confidentialRequests, aF as footprintOf, aG as membersAddRowsSteps, aH as tableSettingsProblems, aI as whenRule } from '../types-BhGs3f8s.cjs';
3
3
  import { c as AggregateMeasure, b as AggregateFilter } from '../subscription-ycCVo9e2.cjs';
4
4
  import { U as UseCase, o as UseCaseRelationship } from '../types-DtEP7XLv.cjs';
5
5
  import { U as UseCaseProblem } from '../validate-QdnFP97_.cjs';
@@ -390,6 +390,15 @@ declare function digestSpec(digest: TemplateDigest, viewId: string): Record<stri
390
390
  declare function checklistSpec(checklist: TemplateChecklist, tables: Record<string, string>, forms: Record<string, string>, documents: Record<string, string>): Record<string, unknown>;
391
391
  /** An automation has no door yet: lane 11 owes it, and the validator holds such a template. */
392
392
  declare function automationHeld(a: TemplateAutomation): string;
393
+ /** The triggers a template automation installs, by the use-case event word. */
394
+ declare const AUTOMATION_EVENTS: readonly ["created", "due", "overdue"];
395
+ /**
396
+ * custom.automation_declare's spec for one template automation: a reminder that tells the person who set
397
+ * it up (the installer — `to: {author: true}`). `due` waits for the date `daysBefore` days ahead
398
+ * (offset_days negative), `overdue` the day after it, `created` runs on every new row. Field ids are
399
+ * install-time refs (`${ref:fields.<table>.<key>}`).
400
+ */
401
+ declare function automationSpec(a: TemplateAutomation, fieldIds: Record<string, string>): Record<string, unknown>;
393
402
  /**
394
403
  * What custom.booking_declare requires of its table, said BEFORE install: a `slot` column (the door
395
404
  * writes the booked time into it on confirm, and adds it as a required text column when missing),
@@ -444,7 +453,7 @@ declare const INSTALL_PLAN_VERSION: 1;
444
453
  */
445
454
  declare const SERVER_DATE_GRAMMAR: RegExp;
446
455
  /** The store doors a plan may call — the server's custom._template_doors(), mirrored. */
447
- declare const TEMPLATE_PLAN_DOORS: readonly ["person_kernel_id", "file_kernel_id", "record_write", "record_write_many", "record_change_many", "table_from_example", "table_declare", "field_declare", "applicable_fields", "table_dimensions_set", "view_declare", "form_declare", "anon_publish", "booking_declare", "dashboard_declare", "pipeline_declare", "doc_template_save", "action_declare", "subscription_declare", "rule_declare", "checklist_declare", "portal_declare", "query_table_homes"];
456
+ declare const TEMPLATE_PLAN_DOORS: readonly ["person_kernel_id", "file_kernel_id", "record_write", "record_write_many", "record_change_many", "table_from_example", "table_declare", "field_declare", "applicable_fields", "table_dimensions_set", "view_declare", "form_declare", "anon_publish", "booking_declare", "dashboard_declare", "pipeline_declare", "doc_template_save", "action_declare", "subscription_declare", "rule_declare", "checklist_declare", "portal_declare", "query_table_homes", "automation_declare"];
448
457
  type TemplatePlanDoor = (typeof TEMPLATE_PLAN_DOORS)[number];
449
458
  /** What uninstall archives for a step, by kind (custom.template_uninstall). */
450
459
  type TemplateMadeKind = "table" | "field" | "view" | "form" | "dashboard" | "document" | "portal" | "record" | "rule";
@@ -789,6 +798,8 @@ interface ExistingTable {
789
798
  interface DescribeCtx {
790
799
  plan?: DescribePlan;
791
800
  existingTables?: ExistingTable[];
801
+ /** Install day, YYYY-MM-DD in the business's zone: absolute seed dates become relative to it. Defaults to today in UTC. */
802
+ today?: string;
792
803
  }
793
804
  /** S7: the answer the frontend's describe box already reads. */
794
805
  interface DescribeResult {
@@ -837,7 +848,6 @@ interface AutofixResult {
837
848
  interface DescribeCheckResult extends AutofixResult {
838
849
  problems: DescribeProblem[];
839
850
  }
840
- /** S5 steps 2–9. Never mutates its input. */
841
851
  declare function autofixDescribeSpec(input: TemplateSpec | Record<string, unknown>, ctx?: DescribeCtx): AutofixResult;
842
852
  /** S5 whole: autofix, then the describe-profile check. */
843
853
  declare function describeCheck(spec: TemplateSpec | Record<string, unknown>, ctx?: DescribeCtx): DescribeCheckResult;
@@ -954,4 +964,4 @@ declare function describeResultJsonSchema(): Record<string, unknown>;
954
964
  /** The template as the check reads it: every JSON-text part opened (an object already open is left as it is). */
955
965
  declare function parseDescribeTemplate(template: Record<string, unknown>): Record<string, unknown>;
956
966
 
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 };
967
+ export { AUTOMATION_EVENTS, 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, automationSpec, 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 };
@@ -1,5 +1,5 @@
1
- import { A as AgentSnapshotRow, T as TemplateSpec, a as TemplateTable, S as SharedBlockId, C as CapabilityWord, b as TemplateField, c as TemplateAgent, d as TemplateAutomation, e as TemplateBooking, f as TemplateChecklist, g as TemplateDashboard, h as TemplateDigest, i as TemplateDocument, j as TemplateDrillDown, k as TemplateDimensions, l as TemplateForm, m as TemplateNotification, n as TemplatePortal, o as TemplateRowAction, p as TemplateStageRules, q as TemplateView, r as TemplateMergeBinding, s as TemplateTryIt, t as TemplateWorkflow, u as TemplateFootprint, I as IndustryGroup, v as TemplateJob, w as TeachesFeature, x as TemplateViewKind, y as TemplateBookingWindow } from '../types-Cl0b_Hy8.js';
2
- export { z as CAPABILITY_WORDS, B as CATALOGUE_QUOTAS, D as CATALOGUE_STATUSES, E as CHOICE_COLORS, F as CHOICE_COLORS_DISTINCT_UP_TO, G as CatalogueRow, H as CatalogueStatus, J as ChoiceColor, K as ConfidentialLevel, L as ConfidentialRequest, M as DEFAULT_TEMPLATE_AGENT, N as ENTITY_REFERENCE_KINDS, O as INDUSTRY_GROUPS, R as RELATIVE_DATE, P as RetiredId, Q as SHARED_BLOCKS, U as SHARED_BLOCK_IDS, V as STRENGTHS, W as SharedBlock, X as SharedBlockField, Y as SharedBlockUse, Z as Strength, _ as TABLE_KERNEL_ID, $ as TEACHES_FEATURES, a0 as TEMPLATE_AUDIENCES, a1 as TEMPLATE_EXTRA_KINDS, a2 as TEMPLATE_JOBS, a3 as TEMPLATE_REFERENCE_DATE, a4 as TEMPLATE_SPEC_VERSION, a5 as TEMPLATE_VIEW_KINDS, a6 as TemplateAgentQuestion, a7 as TemplateAgentVariable, a8 as TemplateAudience, a9 as TemplateCalendarView, aa as TemplateChecklistStep, ab as TemplateConfidential, ac as TemplateConfidentialReader, ad as TemplateDashboardBlock, ae as TemplateDimensionOverride, af as TemplateDrillPath, ag as TemplateExtra, ah as TemplateExtraAgent, ai as TemplateExtraAgentVariable, aj as TemplateExtraKind, ak as TemplateFormField, al as TemplateFoundation, am as TemplateGalleryView, an as TemplateGridView, ao as TemplateGuideStep, ap as TemplateKanbanView, aq as TemplateMeasureOverride, ar as TemplatePortalTable, as as TemplateProvenance, at as TemplateSource, au as TemplateTableSettings, av as TemplateTimelineView, aw as TemplateViewSort, ax as UseCaseSingulars, ay as WalkAction, az as WalkAssertion, aA as WalkImport, aB as WalkMove, aC as WalkStep, aD as confidentialPending, aE as confidentialRequests, aF as footprintOf, aG as membersAddRowsSteps, aH as tableSettingsProblems, aI as whenRule } from '../types-Cl0b_Hy8.js';
1
+ import { A as AgentSnapshotRow, T as TemplateSpec, a as TemplateTable, S as SharedBlockId, C as CapabilityWord, b as TemplateField, c as TemplateAgent, d as TemplateAutomation, e as TemplateBooking, f as TemplateChecklist, g as TemplateDashboard, h as TemplateDigest, i as TemplateDocument, j as TemplateDrillDown, k as TemplateDimensions, l as TemplateForm, m as TemplateNotification, n as TemplatePortal, o as TemplateRowAction, p as TemplateStageRules, q as TemplateView, r as TemplateMergeBinding, s as TemplateTryIt, t as TemplateWorkflow, u as TemplateFootprint, I as IndustryGroup, v as TemplateJob, w as TeachesFeature, x as TemplateViewKind, y as TemplateBookingWindow } from '../types-DAruHh1G.js';
2
+ export { z as CAPABILITY_WORDS, B as CATALOGUE_QUOTAS, D as CATALOGUE_STATUSES, E as CHOICE_COLORS, F as CHOICE_COLORS_DISTINCT_UP_TO, G as CatalogueRow, H as CatalogueStatus, J as ChoiceColor, K as ConfidentialLevel, L as ConfidentialRequest, M as DEFAULT_TEMPLATE_AGENT, N as ENTITY_REFERENCE_KINDS, O as INDUSTRY_GROUPS, R as RELATIVE_DATE, P as RetiredId, Q as SHARED_BLOCKS, U as SHARED_BLOCK_IDS, V as STRENGTHS, W as SharedBlock, X as SharedBlockField, Y as SharedBlockUse, Z as Strength, _ as TABLE_KERNEL_ID, $ as TEACHES_FEATURES, a0 as TEMPLATE_AUDIENCES, a1 as TEMPLATE_EXTRA_KINDS, a2 as TEMPLATE_JOBS, a3 as TEMPLATE_REFERENCE_DATE, a4 as TEMPLATE_SPEC_VERSION, a5 as TEMPLATE_VIEW_KINDS, a6 as TemplateAgentQuestion, a7 as TemplateAgentVariable, a8 as TemplateAudience, a9 as TemplateCalendarView, aa as TemplateChecklistStep, ab as TemplateConfidential, ac as TemplateConfidentialReader, ad as TemplateDashboardBlock, ae as TemplateDimensionOverride, af as TemplateDrillPath, ag as TemplateExtra, ah as TemplateExtraAgent, ai as TemplateExtraAgentVariable, aj as TemplateExtraKind, ak as TemplateFormField, al as TemplateFoundation, am as TemplateGalleryView, an as TemplateGridView, ao as TemplateGuideStep, ap as TemplateKanbanView, aq as TemplateMeasureOverride, ar as TemplatePortalTable, as as TemplateProvenance, at as TemplateSource, au as TemplateTableSettings, av as TemplateTimelineView, aw as TemplateViewSort, ax as UseCaseSingulars, ay as WalkAction, az as WalkAssertion, aA as WalkImport, aB as WalkMove, aC as WalkStep, aD as confidentialPending, aE as confidentialRequests, aF as footprintOf, aG as membersAddRowsSteps, aH as tableSettingsProblems, aI as whenRule } from '../types-DAruHh1G.js';
3
3
  import { c as AggregateMeasure, b as AggregateFilter } from '../subscription-DucBLG-Y.js';
4
4
  import { U as UseCase, o as UseCaseRelationship } from '../types-D31PewA2.js';
5
5
  import { U as UseCaseProblem } from '../validate-BWqeG2sK.js';
@@ -390,6 +390,15 @@ declare function digestSpec(digest: TemplateDigest, viewId: string): Record<stri
390
390
  declare function checklistSpec(checklist: TemplateChecklist, tables: Record<string, string>, forms: Record<string, string>, documents: Record<string, string>): Record<string, unknown>;
391
391
  /** An automation has no door yet: lane 11 owes it, and the validator holds such a template. */
392
392
  declare function automationHeld(a: TemplateAutomation): string;
393
+ /** The triggers a template automation installs, by the use-case event word. */
394
+ declare const AUTOMATION_EVENTS: readonly ["created", "due", "overdue"];
395
+ /**
396
+ * custom.automation_declare's spec for one template automation: a reminder that tells the person who set
397
+ * it up (the installer — `to: {author: true}`). `due` waits for the date `daysBefore` days ahead
398
+ * (offset_days negative), `overdue` the day after it, `created` runs on every new row. Field ids are
399
+ * install-time refs (`${ref:fields.<table>.<key>}`).
400
+ */
401
+ declare function automationSpec(a: TemplateAutomation, fieldIds: Record<string, string>): Record<string, unknown>;
393
402
  /**
394
403
  * What custom.booking_declare requires of its table, said BEFORE install: a `slot` column (the door
395
404
  * writes the booked time into it on confirm, and adds it as a required text column when missing),
@@ -444,7 +453,7 @@ declare const INSTALL_PLAN_VERSION: 1;
444
453
  */
445
454
  declare const SERVER_DATE_GRAMMAR: RegExp;
446
455
  /** The store doors a plan may call — the server's custom._template_doors(), mirrored. */
447
- declare const TEMPLATE_PLAN_DOORS: readonly ["person_kernel_id", "file_kernel_id", "record_write", "record_write_many", "record_change_many", "table_from_example", "table_declare", "field_declare", "applicable_fields", "table_dimensions_set", "view_declare", "form_declare", "anon_publish", "booking_declare", "dashboard_declare", "pipeline_declare", "doc_template_save", "action_declare", "subscription_declare", "rule_declare", "checklist_declare", "portal_declare", "query_table_homes"];
456
+ declare const TEMPLATE_PLAN_DOORS: readonly ["person_kernel_id", "file_kernel_id", "record_write", "record_write_many", "record_change_many", "table_from_example", "table_declare", "field_declare", "applicable_fields", "table_dimensions_set", "view_declare", "form_declare", "anon_publish", "booking_declare", "dashboard_declare", "pipeline_declare", "doc_template_save", "action_declare", "subscription_declare", "rule_declare", "checklist_declare", "portal_declare", "query_table_homes", "automation_declare"];
448
457
  type TemplatePlanDoor = (typeof TEMPLATE_PLAN_DOORS)[number];
449
458
  /** What uninstall archives for a step, by kind (custom.template_uninstall). */
450
459
  type TemplateMadeKind = "table" | "field" | "view" | "form" | "dashboard" | "document" | "portal" | "record" | "rule";
@@ -789,6 +798,8 @@ interface ExistingTable {
789
798
  interface DescribeCtx {
790
799
  plan?: DescribePlan;
791
800
  existingTables?: ExistingTable[];
801
+ /** Install day, YYYY-MM-DD in the business's zone: absolute seed dates become relative to it. Defaults to today in UTC. */
802
+ today?: string;
792
803
  }
793
804
  /** S7: the answer the frontend's describe box already reads. */
794
805
  interface DescribeResult {
@@ -837,7 +848,6 @@ interface AutofixResult {
837
848
  interface DescribeCheckResult extends AutofixResult {
838
849
  problems: DescribeProblem[];
839
850
  }
840
- /** S5 steps 2–9. Never mutates its input. */
841
851
  declare function autofixDescribeSpec(input: TemplateSpec | Record<string, unknown>, ctx?: DescribeCtx): AutofixResult;
842
852
  /** S5 whole: autofix, then the describe-profile check. */
843
853
  declare function describeCheck(spec: TemplateSpec | Record<string, unknown>, ctx?: DescribeCtx): DescribeCheckResult;
@@ -954,4 +964,4 @@ declare function describeResultJsonSchema(): Record<string, unknown>;
954
964
  /** The template as the check reads it: every JSON-text part opened (an object already open is left as it is). */
955
965
  declare function parseDescribeTemplate(template: Record<string, unknown>): Record<string, unknown>;
956
966
 
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 };
967
+ export { AUTOMATION_EVENTS, 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, automationSpec, 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 };
@@ -2546,7 +2546,21 @@ function checklistSpec(checklist, tables, forms, documents) {
2546
2546
  };
2547
2547
  }
2548
2548
  function automationHeld(a) {
2549
- return `The automation "${a.name}" is held for lane 11: no store door runs automations yet, so a template carrying one is held, never installed without it.`;
2549
+ return `The automation "${a.name}" has a trigger the install cannot set up (${a.when.event}); a template automation runs on created, due or overdue.`;
2550
+ }
2551
+ var AUTOMATION_EVENTS = ["created", "due", "overdue"];
2552
+ function automationSpec(a, fieldIds) {
2553
+ const text2 = (a.message?.trim() || a.then.trim()).slice(0, 600);
2554
+ const actions = [{ do: "notify", to: { author: true }, text: text2 }];
2555
+ const at = a.at && /^([01][0-9]|2[0-3]):[0-5][0-9]$/.test(a.at) ? a.at : "09:00";
2556
+ if (a.when.event === "created") return { name: a.name, trigger: { on: "row_added" }, actions };
2557
+ if (a.when.event === "due" || a.when.event === "overdue") {
2558
+ const field2 = a.when.field ? fieldIds[a.when.field] : void 0;
2559
+ if (!field2) throw new Error(`The automation "${a.name}" waits for "${a.when.field ?? "?"}", which "${a.when.table}" does not declare.`);
2560
+ const offset = a.when.event === "due" ? -Math.max(0, Math.round(a.when.daysBefore ?? 0)) : 1;
2561
+ return { name: a.name, trigger: { on: "date_arrives", field: field2, offset_days: offset, at }, actions };
2562
+ }
2563
+ throw new Error(automationHeld(a));
2550
2564
  }
2551
2565
  function bookingColumnsProblem(tables, booking) {
2552
2566
  const t = tables.find((x) => x.token === booking.table);
@@ -3048,6 +3062,7 @@ var DOOR_FOR = {
3048
3062
  document: "doc_template_save",
3049
3063
  "document.esign": "doc_sign",
3050
3064
  notification: "rule_declare",
3065
+ automation: "automation_declare",
3051
3066
  stage_rules: "pipeline_declare",
3052
3067
  row_action: "action_declare",
3053
3068
  "import.upsert": "io_import_begin",
@@ -3055,9 +3070,7 @@ var DOOR_FOR = {
3055
3070
  agent: "agent_context",
3056
3071
  "view.kanban.swimlanes": "view_declare"
3057
3072
  };
3058
- var OWED_BY = {
3059
- automation: "lane 11"
3060
- };
3073
+ var OWED_BY = {};
3061
3074
  var STORE_DOOR_NAMES = new Set(STORE_DOORS.map((d) => d.name));
3062
3075
  var STORE_FIELD_KINDS = new Set(BEHAVIOR_OF.keys());
3063
3076
  function capabilityStatus(word) {
@@ -3645,7 +3658,8 @@ function validateTemplate(raw, options = {}) {
3645
3658
  const e = effective(table, f);
3646
3659
  return e.contextPolicy !== "exclude" && e.sensitivity !== "restricted";
3647
3660
  };
3648
- if (own.length < TABLES_MIN || own.length > TABLES_MAX) say("tables", `A template installs ${TABLES_MIN}\u2013${TABLES_MAX} related tables; this one has ${own.length}.`);
3661
+ if (own.length === 0 || own.length > TABLES_MAX) say("tables", `A template installs ${TABLES_MIN}\u2013${TABLES_MAX} related tables; this one has ${own.length}.`);
3662
+ else if (own.length < TABLES_MIN) sayGallery("tables", `A template installs ${TABLES_MIN}\u2013${TABLES_MAX} related tables; this one has ${own.length}.`);
3649
3663
  const main = own[0];
3650
3664
  if (main && (main.rows.length < MAIN_TABLE_ROWS_MIN || main.rows.length > MAIN_TABLE_ROWS_MAX)) {
3651
3665
  say(`tables[0] (${main.token}).rows`, `The main table carries ${MAIN_TABLE_ROWS_MIN}\u2013${MAIN_TABLE_ROWS_MAX} realistic rows; it has ${main.rows.length}.`);
@@ -3683,12 +3697,12 @@ function validateTemplate(raw, options = {}) {
3683
3697
  if (seeds.length) {
3684
3698
  const hi = Math.max(...seeds);
3685
3699
  const lo = Math.min(...seeds);
3686
- if (new Set(seeds).size < 2) say(`${at}`, `Every seed row holds the same ${field2.label}; real records vary.`);
3700
+ if (new Set(seeds).size < 2) saySeed(`${at}`, `Every seed row holds the same ${field2.label}; real records vary.`);
3687
3701
  for (const rule of field2.rules ?? []) {
3688
3702
  const bound = Number(rule.value);
3689
- if (rule.kind === "max" && hi > 0 && bound > 100 * hi) say(`${at}.rules`, `The most "${field2.label}" allows (${rule.value}) is over 100\xD7 the largest real value (${hi}); write the real ceiling.`);
3690
- if (rule.kind === "min" && bound < -1e3 * Math.abs(lo)) say(`${at}.rules`, `The least "${field2.label}" allows (${rule.value}) is far below any real value (${lo}); write the real floor.`);
3691
- if (rule.kind === "min" && bound < 0 && lo >= 0) say(`${at}.rules`, `"${field2.label}" allows negative values, and no real one is negative; the floor is 0 or above.`);
3703
+ if (rule.kind === "max" && hi > 0 && bound > 100 * hi) saySeed(`${at}.rules`, `The most "${field2.label}" allows (${rule.value}) is over 100\xD7 the largest real value (${hi}); write the real ceiling.`);
3704
+ if (rule.kind === "min" && bound < -1e3 * Math.abs(lo)) saySeed(`${at}.rules`, `The least "${field2.label}" allows (${rule.value}) is far below any real value (${lo}); write the real floor.`);
3705
+ if (rule.kind === "min" && bound < 0 && lo >= 0) saySeed(`${at}.rules`, `"${field2.label}" allows negative values, and no real one is negative; the floor is 0 or above.`);
3692
3706
  }
3693
3707
  }
3694
3708
  }
@@ -4192,10 +4206,21 @@ function validateTemplate(raw, options = {}) {
4192
4206
  }
4193
4207
  } else if (!extra.prompt?.trim()) say(`${at}.prompt`, "An agent action says what the record chat opens with.");
4194
4208
  break;
4195
- case "automation":
4196
- if (needTable(extra.when.table, "when.table") && extra.when.field && !fieldOf(extra.when.table, extra.when.field)) say(`${at}.when.field`, `"${extra.when.table}" does not declare a field "${extra.when.field}".`);
4209
+ case "automation": {
4210
+ const ev = extra.when?.event;
4211
+ if (needTable(extra.when?.table, "when.table") && extra.when.field && !fieldOf(extra.when.table, extra.when.field)) say(`${at}.when.field`, `"${extra.when.table}" does not declare a field "${extra.when.field}".`);
4212
+ if (!AUTOMATION_EVENTS.includes(ev)) say(`${at}.when.event`, `An automation runs on ${AUTOMATION_EVENTS.join(", ")}; for "${ev}" use a notification.`);
4213
+ if (ev === "due" || ev === "overdue") {
4214
+ const f = extra.when.field ? fieldOf(extra.when.table, extra.when.field) : void 0;
4215
+ if (!extra.when.field) say(`${at}.when.field`, "A date reminder names the date field it waits for.");
4216
+ else if (f && f.parityType !== "datetime") say(`${at}.when.field`, `"${extra.when.field}" is not a date or datetime field, so nothing arrives to remind about.`);
4217
+ const d = extra.when.daysBefore;
4218
+ if (d != null && (!Number.isInteger(d) || d < 0 || d > 365)) say(`${at}.when.daysBefore`, "Say how many whole days before the date, 0 to 365.");
4219
+ }
4220
+ if (extra.at != null && !/^([01][0-9]|2[0-3]):[0-5][0-9]$/.test(extra.at)) say(`${at}.at`, "Say the time of day as HH:MM on a 24-hour clock, like 09:00.");
4197
4221
  if (!extra.then?.trim()) say(`${at}.then`, "Say what happens, in the business's words.");
4198
4222
  break;
4223
+ }
4199
4224
  default:
4200
4225
  say(at, `"${extra.kind}" is not an extra a template can carry.`);
4201
4226
  }
@@ -5876,7 +5901,8 @@ var TEMPLATE_PLAN_DOORS = [
5876
5901
  "rule_declare",
5877
5902
  "checklist_declare",
5878
5903
  "portal_declare",
5879
- "query_table_homes"
5904
+ "query_table_homes",
5905
+ "automation_declare"
5880
5906
  ];
5881
5907
  var ROW_BATCH = 10;
5882
5908
  var DERIVED = /* @__PURE__ */ new Set(["lookup", "rollup"]);
@@ -6056,6 +6082,8 @@ function compileInstallPlan(written) {
6056
6082
  }
6057
6083
  const needIds = /* @__PURE__ */ new Set([
6058
6084
  ...spec.extras.filter((e) => e.kind === "document" || e.kind === "row_action").map((e) => e.table),
6085
+ // A date reminder names its date Field by id.
6086
+ ...spec.extras.filter((e) => e.kind === "automation" && e.when.field).map((e) => e.when.table),
6059
6087
  ...spec.views.filter((v) => v.anyOf && Object.keys(v.anyOf).length).map((v) => v.table)
6060
6088
  ]);
6061
6089
  const fieldRefs = (token) => {
@@ -6221,7 +6249,13 @@ function compileInstallPlan(written) {
6221
6249
  });
6222
6250
  break;
6223
6251
  case "automation":
6224
- throw new Error(automationHeld(e));
6252
+ steps.push({
6253
+ label: `automations.${e.token}`,
6254
+ door: "automation_declare",
6255
+ args: { p_organization_id: "${org}", p_table_id: tableRef(e.when.table), p_spec: automationSpec(e, fieldRefs(e.when.table)), p_automation_id: null },
6256
+ save: { [`automations.${e.token}`]: ["automation_id"] }
6257
+ });
6258
+ break;
6225
6259
  default:
6226
6260
  throw new Error(`The install plan has no door for a ${e.kind} yet ("${e.token ?? "?"}"), so this template cannot be declared until it does.`);
6227
6261
  }
@@ -7382,6 +7416,36 @@ function switchJob(spec, fixes) {
7382
7416
  fixes.push(`job: ${spec.job} switched to ${to} (linked tables, no realism declarations)`);
7383
7417
  spec.job = to;
7384
7418
  }
7419
+ var ABSOLUTE_SEED = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
7420
+ function fixSeedDates(spec, ctx, fixes) {
7421
+ const today = ctx.today && /^\d{4}-\d{2}-\d{2}$/.test(ctx.today) ? ctx.today : (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7422
+ const t0 = Date.UTC(+today.slice(0, 4), +today.slice(5, 7) - 1, +today.slice(8, 10));
7423
+ for (const t of spec.tables) {
7424
+ const dates = t.fields.filter((f) => f.parityType === "datetime" && !f.absoluteDates);
7425
+ if (!dates.length || !t.rows?.length) continue;
7426
+ let rewritten = 0;
7427
+ for (const f of dates) {
7428
+ let timed = false;
7429
+ for (const r of t.rows) {
7430
+ const v = r.values?.[f.key];
7431
+ if (typeof v !== "string") continue;
7432
+ const m = ABSOLUTE_SEED.exec(v.trim());
7433
+ if (m) {
7434
+ const days = Math.round((Date.UTC(+m[1], +m[2] - 1, +m[3]) - t0) / 864e5);
7435
+ if (Math.abs(days) > 9999) continue;
7436
+ r.values[f.key] = `@today${days === 0 ? "" : days > 0 ? `+${days}d` : `${days}d`}${m[4] ? ` ${m[4]}:${m[5]}` : ""}`;
7437
+ rewritten++;
7438
+ }
7439
+ if (/ \d{2}:\d{2}$|T\d{2}:\d{2}/.test(String(r.values[f.key]))) timed = true;
7440
+ }
7441
+ if (timed && f.format !== "datetime") {
7442
+ f.format = "datetime";
7443
+ fixes.push(`tables.${t.token}.${f.key}: holds a time of day, so it is a date-and-time column`);
7444
+ }
7445
+ }
7446
+ if (rewritten) fixes.push(`tables.${t.token}.rows: ${rewritten} example date(s) written relative to today`);
7447
+ }
7448
+ }
7385
7449
  function autofixDescribeSpec(input, ctx = {}) {
7386
7450
  const spec = describeSpec(clone2(input));
7387
7451
  const autoFixes = [];
@@ -7404,14 +7468,51 @@ function autofixDescribeSpec(input, ctx = {}) {
7404
7468
  fixRelationships(spec, ctx, autoFixes);
7405
7469
  askRequired(spec, autoFixes);
7406
7470
  switchJob(spec, autoFixes);
7471
+ fixSeedDates(spec, ctx, autoFixes);
7407
7472
  return { spec, autoFixes };
7408
7473
  }
7474
+ var ROW_AT = /^tables(?:\[\d+\])? \((\w+)\)\.rows/;
7475
+ function rowProblemTables(spec, problems) {
7476
+ const out = /* @__PURE__ */ new Set();
7477
+ for (const p of problems) {
7478
+ const m = ROW_AT.exec(p.at);
7479
+ if (m) out.add(m[1]);
7480
+ else if (/^placeholder data "([^"]+)"/.test(p.says)) {
7481
+ const value = /^placeholder data "([^"]+)"/.exec(p.says)[1];
7482
+ for (const t of spec.tables) if (t.rows?.some((r) => JSON.stringify(r.values ?? {}).includes(value))) out.add(t.token);
7483
+ }
7484
+ }
7485
+ return out;
7486
+ }
7409
7487
  function describeCheck(spec, ctx = {}) {
7410
7488
  const fixed = autofixDescribeSpec(spec, ctx);
7411
7489
  const v = validateTemplate(fixed.spec, { profile: "describe" });
7412
7490
  const sameFields = (t) => (ctx.existingTables ?? []).some((e) => e.fields.map((f) => f.key).sort().join("|") === t.fields.map((f) => f.key).sort().join("|"));
7413
7491
  const reused = new Set(fixed.spec.tables.filter(sameFields).map((t) => t.token));
7414
- const problems = v.problems.filter((p) => !(/^This table copies the shared /.test(p.says) && reused.has(/\((\w+)\)/.exec(p.at)?.[1] ?? "")));
7492
+ const notReused = (ps) => ps.filter((p) => !(/^This table copies the shared /.test(p.says) && reused.has(/\((\w+)\)/.exec(p.at)?.[1] ?? "")));
7493
+ let problems = notReused(v.problems);
7494
+ for (let round = 0; round < 3; round++) {
7495
+ const bad = rowProblemTables(fixed.spec, problems);
7496
+ if (!bad.size) break;
7497
+ let grew = true;
7498
+ while (grew) {
7499
+ grew = false;
7500
+ for (const t of fixed.spec.tables) {
7501
+ if (bad.has(t.token) || !t.rows?.length) continue;
7502
+ if (t.fields.some((f) => f.relationTarget && bad.has(f.relationTarget) && t.rows.some((r) => r.values?.[f.key] != null))) {
7503
+ bad.add(t.token);
7504
+ grew = true;
7505
+ }
7506
+ }
7507
+ }
7508
+ for (const t of fixed.spec.tables) {
7509
+ if (!bad.has(t.token) || !t.rows?.length) continue;
7510
+ const why = problems.find((p) => ROW_AT.exec(p.at)?.[1] === t.token)?.says ?? "they did not pass the check";
7511
+ fixed.autoFixes.push(`tables.${t.token}.rows: example rows left out (${why.slice(0, 120)})`);
7512
+ t.rows = [];
7513
+ }
7514
+ problems = notReused(validateTemplate(fixed.spec, { profile: "describe" }).problems);
7515
+ }
7415
7516
  return { ...fixed, problems: problems.map((p) => ({ at: p.at, says: p.says })) };
7416
7517
  }
7417
7518
 
@@ -7640,6 +7741,10 @@ var FORMULA_SHAPE_FACTS = {
7640
7741
  rule: "a formula names every field by its LABEL in braces ({Quantity}), never by key; operators are + - * / % only (no >, <, = or comparisons), functions are IF, ROUND, SUM, DATEDIFF and the other store functions; it never reads a lookup or rollup, nor itself.",
7641
7742
  example: { key: "line_total", label: "Line total", parityType: "formula", formula: "{Quantity} * {Unit price}" }
7642
7743
  };
7744
+ var AUTOMATION_SHAPE_FACTS = {
7745
+ rule: `an automation extra is {kind:"automation", token, name, when:{table, event, field?, daysBefore?}, then, message?, at?}. event is one of: due (a date field is coming up \u2014 field = the key of a datetime field of that table, daysBefore = whole days ahead 0 to 365), overdue (the day after that date field), created (every new row). then says what happens in the business's words; message is the reminder text the person reads (no merge fields); at is the time of day HH:MM (default 09:00). It always tells the person who set it up. Add one only when the sentence asks for a reminder, a heads-up or a follow-up nudge.`,
7746
+ example: { kind: "automation", token: "remind_before_post", name: "Reminder 2 days before a post", when: { table: "post", event: "due", field: "publish_at", daysBefore: 2 }, then: "remind me two days before a post goes out", message: "A post goes out in 2 days \u2014 check the copy and image.", at: "09:00" }
7747
+ };
7643
7748
  var RELATIONSHIP_SHAPE_FACTS = {
7644
7749
  rule: "a relationship's inverseKey is the name the OTHER table sees this link under; it must not be a key that table already has as a field. A parent that lists its children owns ONE multi relation field (multi true); the child's single link to the parent is a second field, and their inverseKeys differ from every field key.",
7645
7750
  example: { fromTable: "request", fromField: "client", toTable: "client", flavor: "referenced", cardinality: "one", onDelete: "restrict", inverseKey: "requests_from" }
@@ -7663,7 +7768,7 @@ function describeVocabulary() {
7663
7768
  template_view_kinds: TEMPLATE_VIEW_KINDS,
7664
7769
  template_audiences: TEMPLATE_AUDIENCES,
7665
7770
  form_audiences: ["public", "member", "staff"],
7666
- extra_kinds_for_describe: ["booking"],
7771
+ extra_kinds_for_describe: ["booking", "automation"],
7667
7772
  booking_window: { weekday: "0 = Sunday \u2026 6 = Saturday", from: "HH:MM", to: "HH:MM later than from" },
7668
7773
  booking_availability: BOOKING_AVAILABILITY_FACTS,
7669
7774
  view_shape: VIEW_SHAPE_FACTS,
@@ -7673,6 +7778,7 @@ function describeVocabulary() {
7673
7778
  field_shape: FIELD_SHAPE_FACTS,
7674
7779
  formula_shape: FORMULA_SHAPE_FACTS,
7675
7780
  relationship_shape: RELATIONSHIP_SHAPE_FACTS,
7781
+ automation_shape: AUTOMATION_SHAPE_FACTS,
7676
7782
  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.",
7677
7783
  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.",
7678
7784
  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"
@@ -7792,6 +7898,7 @@ function parseDescribeTemplate(template) {
7792
7898
  return out;
7793
7899
  }
7794
7900
  export {
7901
+ AUTOMATION_EVENTS,
7795
7902
  BAD_OUTCOME,
7796
7903
  BOOKING_AVAILABILITY_FACTS,
7797
7904
  CAPABILITY_WORDS,
@@ -7842,6 +7949,7 @@ export {
7842
7949
  attachmentProblems,
7843
7950
  autofixDescribeSpec,
7844
7951
  automationHeld,
7952
+ automationSpec,
7845
7953
  blockTable,
7846
7954
  bookingArgs,
7847
7955
  bookingColumnsProblem,