@things-factory/ai-assistant 10.1.103 → 10.1.106

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.
@@ -60,4 +60,9 @@ export declare function entryProposalHandler(apply: (sessionId: string, proposal
60
60
  export declare function latestEntryKeys(proposalsInOrder: any[][]): Map<string, string>;
61
61
  /** A 입력안 and a 수정안 of one record are counted apart - a newer one of the same kind replaces the older. */
62
62
  export declare function entryGroupOf(proposal: any): string;
63
+ /**
64
+ * The card's title - the record's name from the target (`부서`, `거래처`) and the kind of card from here, so a
65
+ * 수정안 is never titled as a 입력안.
66
+ */
67
+ export declare function entryTitle(proposal: any, t: (key: string, options?: any) => string): string;
63
68
  export declare function isChangeProposal(proposal: any): boolean;
@@ -67,6 +67,16 @@ export function latestEntryKeys(proposalsInOrder) {
67
67
  export function entryGroupOf(proposal) {
68
68
  return `${proposal?.target}:${proposal?.op ?? 'create'}`;
69
69
  }
70
+ /**
71
+ * The card's title - the record's name from the target (`부서`, `거래처`) and the kind of card from here, so a
72
+ * 수정안 is never titled as a 입력안.
73
+ */
74
+ export function entryTitle(proposal, t) {
75
+ const name = proposal?.labelKey ? t(proposal.labelKey) : proposal?.target ?? '';
76
+ return proposal?.op === 'update'
77
+ ? t('ai-assistant.entry.title-update', { defaultValue: '{name} to change', name })
78
+ : t('ai-assistant.entry.title-create', { defaultValue: '{name} to enter', name });
79
+ }
70
80
  export function isChangeProposal(proposal) {
71
81
  return isEntryProposal(proposal) && proposal.op === 'update';
72
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entry-proposal.js","sourceRoot":"","sources":["../../client/utils/entry-proposal.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The data entry card's rules and its handler (operato-application/design/ai/data-entry.md §5).\n *\n * The card is a review, not an editor: a correction is said in the conversation and the model proposes\n * again - the newer card replaces the older one. Pressing asks the server to enter the stored rows; the\n * screen sends no rows of its own.\n */\nimport type { ProposalContext, ProposalOutcome } from './assistant-proposals.js'\n\nexport interface EntryIssueView {\n field?: string\n code: string\n messageKey?: string\n params?: Record<string, unknown>\n paramKeys?: Record<string, string>\n blocking: boolean\n}\n\nexport interface EntryRowView {\n index: number\n values: Record<string, unknown>\n sources: { attachmentId?: string; where?: string; person?: boolean }[]\n issues: EntryIssueView[]\n /** The server found this row's numbers and dates together on this line of the cited file. */\n evidence?: { attachmentId: string; line: number }\n}\n\nexport interface EntryTotalView {\n field: string\n all: number\n ready: number\n declared?: number\n declaredFound?: boolean\n difference?: number\n declaredBy?: 'model' | 'file'\n}\n\nexport interface EntryRowResult {\n index: number\n ok: boolean\n id?: string\n label?: string\n error?: string\n}\n\nexport interface EntryApplyAnswer extends ProposalOutcome {\n rows?: EntryRowResult[]\n /** Set by the handler from the card - which words the conversation line uses. */\n op?: string\n}\n\nexport function isEntryProposal(proposal: any): boolean {\n return proposal?.kind === 'entry' && Array.isArray(proposal?.rows)\n}\n\nexport function entryReadyCount(proposal: any): number {\n const rows: EntryRowView[] = proposal?.rows ?? []\n const blocked = (row: EntryRowView) => row.issues?.some(issue => issue.blocking)\n if (!proposal?.groupBy) return rows.filter(row => !blocked(row)).length\n /* Lines of one record go in together - a record with a line kept out is kept out whole, and its lines do not count. */\n const keyOf = (row: EntryRowView) => {\n const value: any = row.values?.[proposal.groupBy]\n return value === undefined || value === null || value === '' ? `row-${row.index}` : String(typeof value === 'object' ? value.id ?? value.text : value)\n }\n const out = new Set(rows.filter(blocked).map(keyOf))\n return rows.filter(row => !out.has(keyOf(row))).length\n}\n\n/** The i18n key of an issue - the target's own, or the framework's by code. */\nexport function entryIssueKey(issue: EntryIssueView): string {\n return issue.messageKey || `ai-assistant.entry.issue.${issue.code}`\n}\n\n/** The issues of one cell, and of the row as a whole (no field). */\nexport function entryCellIssues(row: EntryRowView, field?: string): EntryIssueView[] {\n return (row.issues ?? []).filter(issue => (field ? issue.field === field : !issue.field))\n}\n\n/** What stays in the conversation - the model reads it on its next turn, and the person sees what went in. */\nexport function entryOutcomeNote(answer: EntryApplyAnswer, t: (key: string, options?: any) => string): string {\n const refused = (answer.rows ?? []).filter(row => !row.ok)\n const head = answer.op === 'update'\n ? answer.applied\n ? t('ai-assistant.entry.changed', { defaultValue: 'changed {count} records.', count: answer.applied })\n : t('ai-assistant.entry.changed-none', { defaultValue: 'no record was changed.' })\n : answer.applied\n ? t('ai-assistant.entry.entered', { defaultValue: 'entered {count} rows.', count: answer.applied })\n : t('ai-assistant.entry.entered-none', { defaultValue: 'no row was entered.' })\n const lines = refused.slice(0, 20).map(row => t('ai-assistant.entry.row-refused', { defaultValue: 'row {n}: {reason}', n: row.index + 1, reason: row.error || '' }))\n const more = refused.length > 20 ? [t('ai-assistant.entry.more-refused', { defaultValue: '{count} more rows were not entered.', count: refused.length - 20 })] : []\n return [head, ...lines, ...more].join('\\n')\n}\n\n/** The handler every entry card runs - built with the mutation so the rules are tested without a server. */\nexport function entryProposalHandler(\n apply: (sessionId: string, proposalKey: string) => Promise<EntryApplyAnswer>,\n t: (key: string, options?: any) => string\n) {\n return async (proposal: any, context: ProposalContext): Promise<ProposalOutcome> => {\n if (!context.sessionId || !proposal?.key) return { verdict: 'unavailable', errorCode: 'no-conversation' }\n const answer = { ...(await apply(context.sessionId, proposal.key)), op: proposal.op }\n return {\n verdict: answer.verdict,\n ...(answer.errorCode ? { errorCode: answer.errorCode } : {}),\n applied: answer.applied ?? 0,\n missed: answer.missed ?? 0,\n note: entryOutcomeNote(answer, t)\n }\n }\n}\n\n/**\n * The newest card per record, over the conversation's proposals in order - an older one is replaced and\n * cannot be entered (the server refuses it as `superseded`; the card says so before anyone presses).\n */\nexport function latestEntryKeys(proposalsInOrder: any[][]): Map<string, string> {\n const latest = new Map<string, string>()\n for (const list of proposalsInOrder) for (const one of list ?? []) if (isEntryProposal(one) && one.key) latest.set(entryGroupOf(one), one.key)\n return latest\n}\n\n/** A 입력안 and a 수정안 of one record are counted apart - a newer one of the same kind replaces the older. */\nexport function entryGroupOf(proposal: any): string {\n return `${proposal?.target}:${proposal?.op ?? 'create'}`\n}\n\nexport function isChangeProposal(proposal: any): boolean {\n return isEntryProposal(proposal) && proposal.op === 'update'\n}\n"]}
1
+ {"version":3,"file":"entry-proposal.js","sourceRoot":"","sources":["../../client/utils/entry-proposal.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The data entry card's rules and its handler (operato-application/design/ai/data-entry.md §5).\n *\n * The card is a review, not an editor: a correction is said in the conversation and the model proposes\n * again - the newer card replaces the older one. Pressing asks the server to enter the stored rows; the\n * screen sends no rows of its own.\n */\nimport type { ProposalContext, ProposalOutcome } from './assistant-proposals.js'\n\nexport interface EntryIssueView {\n field?: string\n code: string\n messageKey?: string\n params?: Record<string, unknown>\n paramKeys?: Record<string, string>\n blocking: boolean\n}\n\nexport interface EntryRowView {\n index: number\n values: Record<string, unknown>\n sources: { attachmentId?: string; where?: string; person?: boolean }[]\n issues: EntryIssueView[]\n /** The server found this row's numbers and dates together on this line of the cited file. */\n evidence?: { attachmentId: string; line: number }\n}\n\nexport interface EntryTotalView {\n field: string\n all: number\n ready: number\n declared?: number\n declaredFound?: boolean\n difference?: number\n declaredBy?: 'model' | 'file'\n}\n\nexport interface EntryRowResult {\n index: number\n ok: boolean\n id?: string\n label?: string\n error?: string\n}\n\nexport interface EntryApplyAnswer extends ProposalOutcome {\n rows?: EntryRowResult[]\n /** Set by the handler from the card - which words the conversation line uses. */\n op?: string\n}\n\nexport function isEntryProposal(proposal: any): boolean {\n return proposal?.kind === 'entry' && Array.isArray(proposal?.rows)\n}\n\nexport function entryReadyCount(proposal: any): number {\n const rows: EntryRowView[] = proposal?.rows ?? []\n const blocked = (row: EntryRowView) => row.issues?.some(issue => issue.blocking)\n if (!proposal?.groupBy) return rows.filter(row => !blocked(row)).length\n /* Lines of one record go in together - a record with a line kept out is kept out whole, and its lines do not count. */\n const keyOf = (row: EntryRowView) => {\n const value: any = row.values?.[proposal.groupBy]\n return value === undefined || value === null || value === '' ? `row-${row.index}` : String(typeof value === 'object' ? value.id ?? value.text : value)\n }\n const out = new Set(rows.filter(blocked).map(keyOf))\n return rows.filter(row => !out.has(keyOf(row))).length\n}\n\n/** The i18n key of an issue - the target's own, or the framework's by code. */\nexport function entryIssueKey(issue: EntryIssueView): string {\n return issue.messageKey || `ai-assistant.entry.issue.${issue.code}`\n}\n\n/** The issues of one cell, and of the row as a whole (no field). */\nexport function entryCellIssues(row: EntryRowView, field?: string): EntryIssueView[] {\n return (row.issues ?? []).filter(issue => (field ? issue.field === field : !issue.field))\n}\n\n/** What stays in the conversation - the model reads it on its next turn, and the person sees what went in. */\nexport function entryOutcomeNote(answer: EntryApplyAnswer, t: (key: string, options?: any) => string): string {\n const refused = (answer.rows ?? []).filter(row => !row.ok)\n const head = answer.op === 'update'\n ? answer.applied\n ? t('ai-assistant.entry.changed', { defaultValue: 'changed {count} records.', count: answer.applied })\n : t('ai-assistant.entry.changed-none', { defaultValue: 'no record was changed.' })\n : answer.applied\n ? t('ai-assistant.entry.entered', { defaultValue: 'entered {count} rows.', count: answer.applied })\n : t('ai-assistant.entry.entered-none', { defaultValue: 'no row was entered.' })\n const lines = refused.slice(0, 20).map(row => t('ai-assistant.entry.row-refused', { defaultValue: 'row {n}: {reason}', n: row.index + 1, reason: row.error || '' }))\n const more = refused.length > 20 ? [t('ai-assistant.entry.more-refused', { defaultValue: '{count} more rows were not entered.', count: refused.length - 20 })] : []\n return [head, ...lines, ...more].join('\\n')\n}\n\n/** The handler every entry card runs - built with the mutation so the rules are tested without a server. */\nexport function entryProposalHandler(\n apply: (sessionId: string, proposalKey: string) => Promise<EntryApplyAnswer>,\n t: (key: string, options?: any) => string\n) {\n return async (proposal: any, context: ProposalContext): Promise<ProposalOutcome> => {\n if (!context.sessionId || !proposal?.key) return { verdict: 'unavailable', errorCode: 'no-conversation' }\n const answer = { ...(await apply(context.sessionId, proposal.key)), op: proposal.op }\n return {\n verdict: answer.verdict,\n ...(answer.errorCode ? { errorCode: answer.errorCode } : {}),\n applied: answer.applied ?? 0,\n missed: answer.missed ?? 0,\n note: entryOutcomeNote(answer, t)\n }\n }\n}\n\n/**\n * The newest card per record, over the conversation's proposals in order - an older one is replaced and\n * cannot be entered (the server refuses it as `superseded`; the card says so before anyone presses).\n */\nexport function latestEntryKeys(proposalsInOrder: any[][]): Map<string, string> {\n const latest = new Map<string, string>()\n for (const list of proposalsInOrder) for (const one of list ?? []) if (isEntryProposal(one) && one.key) latest.set(entryGroupOf(one), one.key)\n return latest\n}\n\n/** A 입력안 and a 수정안 of one record are counted apart - a newer one of the same kind replaces the older. */\nexport function entryGroupOf(proposal: any): string {\n return `${proposal?.target}:${proposal?.op ?? 'create'}`\n}\n\n/**\n * The card's title - the record's name from the target (`부서`, `거래처`) and the kind of card from here, so a\n * 수정안 is never titled as a 입력안.\n */\nexport function entryTitle(proposal: any, t: (key: string, options?: any) => string): string {\n const name = proposal?.labelKey ? t(proposal.labelKey) : proposal?.target ?? ''\n return proposal?.op === 'update'\n ? t('ai-assistant.entry.title-update', { defaultValue: '{name} to change', name })\n : t('ai-assistant.entry.title-create', { defaultValue: '{name} to enter', name })\n}\n\nexport function isChangeProposal(proposal: any): boolean {\n return isEntryProposal(proposal) && proposal.op === 'update'\n}\n"]}
@@ -155,7 +155,8 @@ async function applyChanges(key, proposal, target, deps) {
155
155
  return nothing('refused', 'read-failed');
156
156
  }
157
157
  const results = [];
158
- for (const row of (0, entry_update_js_1.stillAsProposed)(target, stored, now)) {
158
+ /* The target's checks of the changes again - another record may have taken the new name since the card was made. */
159
+ for (const row of await (0, entry_update_js_1.withChangeChecks)(target, (0, entry_update_js_1.stillAsProposed)(target, stored, now), now, { state: deps.state })) {
159
160
  if (row.issues.some(one => one.blocking)) {
160
161
  const issue = row.issues.find(one => one.blocking);
161
162
  results.push({ index: row.index, ok: false, error: issue.field ? `${issue.field}: ${issue.code}` : issue.code });
@@ -1 +1 @@
1
- {"version":3,"file":"entry-apply.js","sourceRoot":"","sources":["../../../server/service/data-entry/entry-apply.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Writing a proposal the person pressed (operato-application/design/ai/data-entry.md §4).\n *\n * The rows written are the **stored** proposal's, never rows the screen sends: what the person reviewed\n * on the card is what goes in. The server asks everything again - the door, whether a newer card replaced\n * this one, whether it was already answered, the target's checks (records move between proposing and\n * pressing) - and enters each row by running the application's own mutation with the person's request\n * state. Each call is its own request (the door's `@transaction`), so one refused row does not undo the\n * others and each is reported by its place.\n *\n * Dependencies come in as arguments so the rules are tested without a database.\n */\nimport { PROPOSAL_OUTCOME_PREFIX, PROPOSAL_VERDICTS } from '../chat-message/proposal-outcome.js'\nimport { readRecords, stillAsProposed, type ChangeRow } from './entry-update.js'\nimport { changeToolName, zonedDateTimes, entryGroups, resolveReferences, entryDoorOf, entryTargetOf, entryToolName, rootFieldOf, isBlocked, recordEntryEvent, normalizeEntryRows, withCheckedIssues, type EntryRow, type EntryTarget } from './entry-target.js'\n\nexport interface StoredProposalMessage {\n id: string\n proposals: any[]\n}\n\nexport interface EntryRowResult {\n index: number\n ok: boolean\n id?: string\n label?: string\n /** A blocking issue kept it out, or the target refused it. */\n error?: string\n}\n\nexport interface EntryApplyOutcome {\n verdict: 'accepted' | 'refused' | 'unavailable'\n errorCode?: string\n applied: number\n missed: number\n rows: EntryRowResult[]\n}\n\nexport interface EntryApplyDeps {\n /** The conversation's messages that carry proposals, oldest first. */\n messages: StoredProposalMessage[]\n /** Whether an outcome line already answers this key. */\n answered: boolean\n passesDoor(door: string): Promise<boolean>\n /**\n * Runs one of the application's queries or mutations with the person's request state - its API, its directives\n * and its own checks. Answers what GraphQL answers.\n */\n execute(document: string, variables: Record<string, unknown>): Promise<{ data?: any; errors?: readonly { message: string }[] }>\n state: any\n report?(message: string, error: unknown): void\n}\n\nconst nothing = (verdict: EntryApplyOutcome['verdict'], errorCode: string): EntryApplyOutcome => ({ verdict, errorCode, applied: 0, missed: 0, rows: [] })\n\nexport function findEntryProposal(messages: StoredProposalMessage[], key: string): { proposal?: any; superseded: boolean } {\n let at = -1\n let proposal: any\n messages.forEach((message, i) => {\n for (const one of message.proposals ?? []) if (one?.key === key) (at = i), (proposal = one)\n })\n if (!proposal) return { superseded: false }\n /* A later card of the same record and the same work replaces this one - pressing both would do the corrected work twice. */\n const superseded = messages\n .slice(at + 1)\n .some(message => (message.proposals ?? []).some(one => one?.kind === 'entry' && one?.target === proposal.target && (one?.op ?? 'create') === (proposal.op ?? 'create')))\n return { proposal, superseded }\n}\n\nexport async function applyEntryProposal(key: string, deps: EntryApplyDeps, targetOf: (key: string) => EntryTarget | undefined = entryTargetOf): Promise<EntryApplyOutcome> {\n const { proposal, superseded } = findEntryProposal(deps.messages, key)\n if (!proposal) return nothing('refused', 'proposal-not-found')\n if (proposal.kind !== 'entry') return nothing('refused', 'not-an-entry-proposal')\n if (superseded) return nothing('refused', 'superseded')\n if (deps.answered) return nothing('refused', 'already-answered')\n\n const target = targetOf(proposal.target)\n if (!target) return nothing('unavailable', 'unknown-entry-target')\n if (proposal.op === 'update') return applyChanges(key, proposal, target, deps)\n const door = entryDoorOf(target.mutation)\n if (!(await deps.passesDoor(door))) {\n await recordEntryEvent(target, { phase: 'apply', tool: entryToolName(target.key), rows: 0, ok: false, error: 'door-closed', detail: { proposalKey: key } }, { state: deps.state })\n return nothing('refused', 'door-closed')\n }\n\n /* Read again from the stored values - the same rules, and today's records for the target's checks. */\n let { rows } = normalizeEntryRows(target, (proposal.rows ?? []).map((row: EntryRow) => ({ values: row.values, sources: row.sources })))\n /* A reference that was not settled on the card is asked again - never entered as a name. */\n rows = await resolveReferences(target.fields, zonedDateTimes(target.fields, rows, deps.state?.domain?.timezone), deps.execute)\n if (target.check) {\n try {\n rows = withCheckedIssues(rows, await target.check(rows, { state: deps.state }))\n } catch (error) {\n deps.report?.(`[ai-assistant] entry check of '${target.key}' failed`, error)\n return nothing('refused', 'check-failed')\n }\n }\n\n const results: EntryRowResult[] = []\n if (target.group) {\n /* One call per group; a group with a row kept out stays out whole - an order missing a line is not entered. */\n for (const [, members] of entryGroups(rows, target.group.by)) {\n const blocked = members.find(isBlocked)\n if (blocked) {\n const issue = blocked.issues.find(one => one.blocking)!\n for (const row of members)\n results.push({ index: row.index, ok: false, error: row === blocked ? (issue.field ? `${issue.field}: ${issue.code}` : issue.code) : `group-kept-out (row ${blocked.index + 1})` })\n continue\n }\n try {\n const answer = await deps.execute(target.mutation, target.group.variables(members))\n const error = answer.errors?.length ? answer.errors.map(one => one.message).join('; ') || 'refused' : undefined\n const applied = error ? undefined : target.group.appliedOf?.(answer.data, members)\n for (const row of members) results.push(error ? { index: row.index, ok: false, error } : { index: row.index, ok: true, ...(applied?.id ? { id: applied.id } : {}), ...(applied?.label ? { label: applied.label } : {}) })\n } catch (error: any) {\n for (const row of members) results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n results.sort((a, b) => a.index - b.index)\n }\n for (const row of target.group ? [] : rows) {\n if (isBlocked(row)) {\n const issue = row.issues.find(one => one.blocking)!\n results.push({ index: row.index, ok: false, error: issue.field ? `${issue.field}: ${issue.code}` : issue.code })\n continue\n }\n try {\n const answer = await deps.execute(target.mutation, target.variables!(row))\n if (answer.errors?.length) {\n results.push({ index: row.index, ok: false, error: answer.errors.map(one => one.message).join('; ') || 'refused' })\n continue\n }\n const applied = target.appliedOf?.(answer.data, row)\n results.push({ index: row.index, ok: true, ...(applied?.id ? { id: applied.id } : {}), ...(applied?.label ? { label: applied.label } : {}) })\n } catch (error: any) {\n results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n\n const applied = results.filter(one => one.ok).length\n const missed = results.length - applied\n await recordEntryEvent(\n target,\n { phase: 'apply', tool: entryToolName(target.key), rows: results.length, ok: applied > 0, applied, missed, ...(applied ? {} : { error: 'no-row-entered' }), detail: { proposalKey: key, rows: results } },\n { state: deps.state }\n )\n return applied\n ? { verdict: 'accepted', applied, missed, rows: results }\n : { verdict: 'refused', errorCode: 'no-row-entered', applied, missed, rows: results }\n}\n\n/** An outcome line already answers this key - `requested` alone does not: the dock writes it just before calling here. */\nexport function entryProposalAnswered(key: string, lines: readonly (string | null | undefined)[]): boolean {\n const answered = `${PROPOSAL_OUTCOME_PREFIX}${key}: `\n return lines.some(line => {\n const text = (line ?? '').trim()\n if (!text.startsWith(answered)) return false\n const rest = text.slice(answered.length)\n return PROPOSAL_VERDICTS.some(verdict => rest === verdict || rest.startsWith(`${verdict} `))\n })\n}\n\n/**\n * A pressed 수정안: the doors again, each record read again as the person, a field that moved since the card was\n * made keeps its row out (`changed-since`), and each record is changed by the application's own mutation.\n */\nasync function applyChanges(key: string, proposal: any, target: EntryTarget, deps: EntryApplyDeps): Promise<EntryApplyOutcome> {\n const tool = changeToolName(target.key)\n const update = target.update\n if (!update) return nothing('unavailable', 'target-does-not-change')\n for (const door of [rootFieldOf(update.mutation, 'mutation'), rootFieldOf(update.read.query, 'query')]) {\n if (!(await deps.passesDoor(door))) {\n await recordEntryEvent(target, { phase: 'apply', tool, rows: 0, ok: false, error: 'door-closed', detail: { proposalKey: key } }, { state: deps.state })\n return nothing('refused', 'door-closed')\n }\n }\n\n const stored: ChangeRow[] = proposal.rows ?? []\n let now\n try {\n now = await readRecords(target, stored.map(row => row.id), deps.execute)\n } catch (error) {\n deps.report?.(`[ai-assistant] reading '${target.key}' again failed`, error)\n return nothing('refused', 'read-failed')\n }\n\n const results: EntryRowResult[] = []\n for (const row of stillAsProposed(target, stored, now)) {\n if (row.issues.some(one => one.blocking)) {\n const issue = row.issues.find(one => one.blocking)!\n results.push({ index: row.index, ok: false, error: issue.field ? `${issue.field}: ${issue.code}` : issue.code })\n continue\n }\n try {\n const answer = await deps.execute(update.mutation, update.variables({ id: row.id, record: row.now!, values: row.values }))\n if (answer.errors?.length) {\n results.push({ index: row.index, ok: false, error: answer.errors.map(one => one.message).join('; ') || 'refused' })\n continue\n }\n results.push({ index: row.index, ok: true, id: row.id, ...(row.label ? { label: row.label } : {}) })\n } catch (error: any) {\n results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n\n const applied = results.filter(one => one.ok).length\n const missed = results.length - applied\n await recordEntryEvent(\n target,\n { phase: 'apply', tool, rows: results.length, ok: applied > 0, applied, missed, ...(applied ? {} : { error: 'no-row-changed' }), detail: { proposalKey: key, op: 'update', rows: results } },\n { state: deps.state }\n )\n return applied ? { verdict: 'accepted', applied, missed, rows: results } : { verdict: 'refused', errorCode: 'no-row-changed', applied, missed, rows: results }\n}\n"]}
1
+ {"version":3,"file":"entry-apply.js","sourceRoot":"","sources":["../../../server/service/data-entry/entry-apply.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Writing a proposal the person pressed (operato-application/design/ai/data-entry.md §4).\n *\n * The rows written are the **stored** proposal's, never rows the screen sends: what the person reviewed\n * on the card is what goes in. The server asks everything again - the door, whether a newer card replaced\n * this one, whether it was already answered, the target's checks (records move between proposing and\n * pressing) - and enters each row by running the application's own mutation with the person's request\n * state. Each call is its own request (the door's `@transaction`), so one refused row does not undo the\n * others and each is reported by its place.\n *\n * Dependencies come in as arguments so the rules are tested without a database.\n */\nimport { PROPOSAL_OUTCOME_PREFIX, PROPOSAL_VERDICTS } from '../chat-message/proposal-outcome.js'\nimport { readRecords, stillAsProposed, withChangeChecks, type ChangeRow } from './entry-update.js'\nimport { changeToolName, zonedDateTimes, entryGroups, resolveReferences, entryDoorOf, entryTargetOf, entryToolName, rootFieldOf, isBlocked, recordEntryEvent, normalizeEntryRows, withCheckedIssues, type EntryRow, type EntryTarget } from './entry-target.js'\n\nexport interface StoredProposalMessage {\n id: string\n proposals: any[]\n}\n\nexport interface EntryRowResult {\n index: number\n ok: boolean\n id?: string\n label?: string\n /** A blocking issue kept it out, or the target refused it. */\n error?: string\n}\n\nexport interface EntryApplyOutcome {\n verdict: 'accepted' | 'refused' | 'unavailable'\n errorCode?: string\n applied: number\n missed: number\n rows: EntryRowResult[]\n}\n\nexport interface EntryApplyDeps {\n /** The conversation's messages that carry proposals, oldest first. */\n messages: StoredProposalMessage[]\n /** Whether an outcome line already answers this key. */\n answered: boolean\n passesDoor(door: string): Promise<boolean>\n /**\n * Runs one of the application's queries or mutations with the person's request state - its API, its directives\n * and its own checks. Answers what GraphQL answers.\n */\n execute(document: string, variables: Record<string, unknown>): Promise<{ data?: any; errors?: readonly { message: string }[] }>\n state: any\n report?(message: string, error: unknown): void\n}\n\nconst nothing = (verdict: EntryApplyOutcome['verdict'], errorCode: string): EntryApplyOutcome => ({ verdict, errorCode, applied: 0, missed: 0, rows: [] })\n\nexport function findEntryProposal(messages: StoredProposalMessage[], key: string): { proposal?: any; superseded: boolean } {\n let at = -1\n let proposal: any\n messages.forEach((message, i) => {\n for (const one of message.proposals ?? []) if (one?.key === key) (at = i), (proposal = one)\n })\n if (!proposal) return { superseded: false }\n /* A later card of the same record and the same work replaces this one - pressing both would do the corrected work twice. */\n const superseded = messages\n .slice(at + 1)\n .some(message => (message.proposals ?? []).some(one => one?.kind === 'entry' && one?.target === proposal.target && (one?.op ?? 'create') === (proposal.op ?? 'create')))\n return { proposal, superseded }\n}\n\nexport async function applyEntryProposal(key: string, deps: EntryApplyDeps, targetOf: (key: string) => EntryTarget | undefined = entryTargetOf): Promise<EntryApplyOutcome> {\n const { proposal, superseded } = findEntryProposal(deps.messages, key)\n if (!proposal) return nothing('refused', 'proposal-not-found')\n if (proposal.kind !== 'entry') return nothing('refused', 'not-an-entry-proposal')\n if (superseded) return nothing('refused', 'superseded')\n if (deps.answered) return nothing('refused', 'already-answered')\n\n const target = targetOf(proposal.target)\n if (!target) return nothing('unavailable', 'unknown-entry-target')\n if (proposal.op === 'update') return applyChanges(key, proposal, target, deps)\n const door = entryDoorOf(target.mutation)\n if (!(await deps.passesDoor(door))) {\n await recordEntryEvent(target, { phase: 'apply', tool: entryToolName(target.key), rows: 0, ok: false, error: 'door-closed', detail: { proposalKey: key } }, { state: deps.state })\n return nothing('refused', 'door-closed')\n }\n\n /* Read again from the stored values - the same rules, and today's records for the target's checks. */\n let { rows } = normalizeEntryRows(target, (proposal.rows ?? []).map((row: EntryRow) => ({ values: row.values, sources: row.sources })))\n /* A reference that was not settled on the card is asked again - never entered as a name. */\n rows = await resolveReferences(target.fields, zonedDateTimes(target.fields, rows, deps.state?.domain?.timezone), deps.execute)\n if (target.check) {\n try {\n rows = withCheckedIssues(rows, await target.check(rows, { state: deps.state }))\n } catch (error) {\n deps.report?.(`[ai-assistant] entry check of '${target.key}' failed`, error)\n return nothing('refused', 'check-failed')\n }\n }\n\n const results: EntryRowResult[] = []\n if (target.group) {\n /* One call per group; a group with a row kept out stays out whole - an order missing a line is not entered. */\n for (const [, members] of entryGroups(rows, target.group.by)) {\n const blocked = members.find(isBlocked)\n if (blocked) {\n const issue = blocked.issues.find(one => one.blocking)!\n for (const row of members)\n results.push({ index: row.index, ok: false, error: row === blocked ? (issue.field ? `${issue.field}: ${issue.code}` : issue.code) : `group-kept-out (row ${blocked.index + 1})` })\n continue\n }\n try {\n const answer = await deps.execute(target.mutation, target.group.variables(members))\n const error = answer.errors?.length ? answer.errors.map(one => one.message).join('; ') || 'refused' : undefined\n const applied = error ? undefined : target.group.appliedOf?.(answer.data, members)\n for (const row of members) results.push(error ? { index: row.index, ok: false, error } : { index: row.index, ok: true, ...(applied?.id ? { id: applied.id } : {}), ...(applied?.label ? { label: applied.label } : {}) })\n } catch (error: any) {\n for (const row of members) results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n results.sort((a, b) => a.index - b.index)\n }\n for (const row of target.group ? [] : rows) {\n if (isBlocked(row)) {\n const issue = row.issues.find(one => one.blocking)!\n results.push({ index: row.index, ok: false, error: issue.field ? `${issue.field}: ${issue.code}` : issue.code })\n continue\n }\n try {\n const answer = await deps.execute(target.mutation, target.variables!(row))\n if (answer.errors?.length) {\n results.push({ index: row.index, ok: false, error: answer.errors.map(one => one.message).join('; ') || 'refused' })\n continue\n }\n const applied = target.appliedOf?.(answer.data, row)\n results.push({ index: row.index, ok: true, ...(applied?.id ? { id: applied.id } : {}), ...(applied?.label ? { label: applied.label } : {}) })\n } catch (error: any) {\n results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n\n const applied = results.filter(one => one.ok).length\n const missed = results.length - applied\n await recordEntryEvent(\n target,\n { phase: 'apply', tool: entryToolName(target.key), rows: results.length, ok: applied > 0, applied, missed, ...(applied ? {} : { error: 'no-row-entered' }), detail: { proposalKey: key, rows: results } },\n { state: deps.state }\n )\n return applied\n ? { verdict: 'accepted', applied, missed, rows: results }\n : { verdict: 'refused', errorCode: 'no-row-entered', applied, missed, rows: results }\n}\n\n/** An outcome line already answers this key - `requested` alone does not: the dock writes it just before calling here. */\nexport function entryProposalAnswered(key: string, lines: readonly (string | null | undefined)[]): boolean {\n const answered = `${PROPOSAL_OUTCOME_PREFIX}${key}: `\n return lines.some(line => {\n const text = (line ?? '').trim()\n if (!text.startsWith(answered)) return false\n const rest = text.slice(answered.length)\n return PROPOSAL_VERDICTS.some(verdict => rest === verdict || rest.startsWith(`${verdict} `))\n })\n}\n\n/**\n * A pressed 수정안: the doors again, each record read again as the person, a field that moved since the card was\n * made keeps its row out (`changed-since`), and each record is changed by the application's own mutation.\n */\nasync function applyChanges(key: string, proposal: any, target: EntryTarget, deps: EntryApplyDeps): Promise<EntryApplyOutcome> {\n const tool = changeToolName(target.key)\n const update = target.update\n if (!update) return nothing('unavailable', 'target-does-not-change')\n for (const door of [rootFieldOf(update.mutation, 'mutation'), rootFieldOf(update.read.query, 'query')]) {\n if (!(await deps.passesDoor(door))) {\n await recordEntryEvent(target, { phase: 'apply', tool, rows: 0, ok: false, error: 'door-closed', detail: { proposalKey: key } }, { state: deps.state })\n return nothing('refused', 'door-closed')\n }\n }\n\n const stored: ChangeRow[] = proposal.rows ?? []\n let now\n try {\n now = await readRecords(target, stored.map(row => row.id), deps.execute)\n } catch (error) {\n deps.report?.(`[ai-assistant] reading '${target.key}' again failed`, error)\n return nothing('refused', 'read-failed')\n }\n\n const results: EntryRowResult[] = []\n /* The target's checks of the changes again - another record may have taken the new name since the card was made. */\n for (const row of await withChangeChecks(target, stillAsProposed(target, stored, now), now, { state: deps.state })) {\n if (row.issues.some(one => one.blocking)) {\n const issue = row.issues.find(one => one.blocking)!\n results.push({ index: row.index, ok: false, error: issue.field ? `${issue.field}: ${issue.code}` : issue.code })\n continue\n }\n try {\n const answer = await deps.execute(update.mutation, update.variables({ id: row.id, record: row.now!, values: row.values }))\n if (answer.errors?.length) {\n results.push({ index: row.index, ok: false, error: answer.errors.map(one => one.message).join('; ') || 'refused' })\n continue\n }\n results.push({ index: row.index, ok: true, id: row.id, ...(row.label ? { label: row.label } : {}) })\n } catch (error: any) {\n results.push({ index: row.index, ok: false, error: error?.message || 'refused' })\n }\n }\n\n const applied = results.filter(one => one.ok).length\n const missed = results.length - applied\n await recordEntryEvent(\n target,\n { phase: 'apply', tool, rows: results.length, ok: applied > 0, applied, missed, ...(applied ? {} : { error: 'no-row-changed' }), detail: { proposalKey: key, op: 'update', rows: results } },\n { state: deps.state }\n )\n return applied ? { verdict: 'accepted', applied, missed, rows: results } : { verdict: 'refused', errorCode: 'no-row-changed', applied, missed, rows: results }\n}\n"]}
@@ -171,6 +171,16 @@ export interface EntryUpdate {
171
171
  labelOf?(record: EntryRecord): string;
172
172
  /** The fields that may change. Default: every declared field. */
173
173
  fields?: string[];
174
+ /**
175
+ * Read-only checks of the changes - a new name that another record already has. Asked when the card is made and
176
+ * again when it is pressed, like an entry's check; one issue list per row. Without it a clash is caught only by
177
+ * the database's own refusal.
178
+ */
179
+ check?(rows: {
180
+ id: string;
181
+ record?: EntryRecord;
182
+ values: Record<string, unknown>;
183
+ }[], context: EntryContext): EntryIssue[][] | Promise<EntryIssue[][]>;
174
184
  }
175
185
  /**
176
186
  * `Mutation.<root field>` of the target's mutation - the one declaration both the tool's gate and the
@@ -1 +1 @@
1
- {"version":3,"file":"entry-target.js","sourceRoot":"","sources":["../../../server/service/data-entry/entry-target.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Data entry from material - what an application declares so the assistant can enter its records\n * (operato-application/design/ai/data-entry.md).\n *\n * A person hands the conversation what the records are made of - a bank export, a photo of a receipt,\n * lines pasted from a mail - and the assistant turns it into rows of one of the application's records.\n * Nothing is written by the model. It proposes the rows; the card shows them with what was wrong in\n * each and where each came from; a correction is said in the conversation and the model proposes again;\n * the person presses the button; the server enters each row **through the application's own GraphQL\n * mutation**, run with the person's request state - the same door, directives and checks as entering by hand.\n * There is no second way into the record.\n *\n * This file is pure - no framework, no database - so the rules a row passes are tested without a server.\n */\nimport { parse } from 'graphql'\n\nexport type EntryFieldType = 'string' | 'text' | 'number' | 'integer' | 'date' | 'datetime' | 'boolean' | 'enum' | 'reference'\n\nexport interface EntryField {\n name: string\n type: EntryFieldType\n required?: boolean\n /** The allowed values of an `enum` field. */\n values?: string[]\n /** What the model reads about the field - English, like every tool description. */\n description?: string\n /** i18n key of the column heading on the card. Absent: the field name. */\n labelKey?: string\n /** A number field the card sums - and compares with the total the material prints (§ totals). */\n total?: boolean\n /** An enum's values on the card: `<prefix><value in lowercase>` - `text.expense-payment-` shows PERSONAL_CARD as 개인카드. */\n valueKeyPrefix?: string\n /**\n * A `reference` field points at another record - a loan, an item, a location. The model knows it by a name or\n * a code; the server finds it through the application's query, as the person, and keeps its id. One match is\n * taken; none or several keep the row out and say so - the server never picks among several.\n */\n reference?: EntryReference\n}\n\nexport interface EntryReference {\n query: string\n /** The query's variables for what the model wrote - \"기업은행\", \"A-100\". */\n variables(text: string): Record<string, unknown>\n /** The records the answer holds that the text names - the application filters, the server does not guess. */\n recordsOf(data: any, text: string): { id: string; label?: string }[]\n}\n\n/** A resolved reference, as a row keeps it. */\nexport interface ReferenceValue {\n id: string\n label?: string\n}\n\n/** Where a row came from - which file, and where in it. Shown on the card beside the row. */\nexport interface EntrySource {\n attachmentId?: string\n /** \"row 3\", \"the receipt photo\" - the model's words, in the person's language. */\n where?: string\n /** The value came from what the person said in the conversation - shown in the screen's own words, never the model's. */\n person?: boolean\n}\n\nexport interface EntryIssue {\n /** The field it is about. Absent: the row as a whole. */\n field?: string\n /** A code the screen translates: `ai-assistant.entry.issue.<code>`, or the target's own `messageKey`. */\n code: string\n messageKey?: string\n params?: Record<string, unknown>\n /** A param that is a code the screen words - { status: 'text.state-' } shows `down` as 고장. */\n paramKeys?: Record<string, string>\n /** A blocking issue keeps the row out when the person presses the button. */\n blocking: boolean\n}\n\nexport interface EntryRowInput {\n values?: Record<string, unknown>\n sources?: EntrySource[]\n}\n\nexport interface EntryRow {\n index: number\n values: Record<string, unknown>\n sources: EntrySource[]\n issues: EntryIssue[]\n /** The line of a text source where this row's numbers and dates were all found - the server's check, not the model's word. */\n evidence?: { attachmentId: string; line: number }\n}\n\nexport interface EntryContext {\n /** The request state - domain, user, and when writing, `tx` and `afterCommit`. */\n state: any\n}\n\nexport interface EntryApplied {\n /** The created record's id, when there is one. */\n id?: string\n /** A short name for the conversation line - \"2026-09-12 · 택시 · ₩12,400\". */\n label?: string\n}\n\n/** What happened, for an application that writes down every assistant call (office's AI audit). */\nexport interface EntryEvent {\n phase: 'propose' | 'apply'\n tool: string\n rows: number\n ok: boolean\n applied?: number\n missed?: number\n error?: string\n /** propose: the rows as the model gave them; apply: the proposal key and each row's result. */\n detail?: unknown\n}\n\nexport interface EntryTarget {\n /** `<app>.<record>` - `office.expense-line`. */\n key: string\n /** i18n key of the record's name on the card. */\n labelKey: string\n /** What one row is, for the model. */\n description: string\n fields: EntryField[]\n /**\n * The application's own mutation that enters one record, as a GraphQL document with one root field -\n * `mutation ($line: NewExpenseLine!) { addExpenseLine(line: $line) { id } }`. Its root field is the door:\n * the propose tool is offered only to someone who passes it, and each row is entered by running it with\n * the person's request state, so `@privilege`, `@transaction` and the door's own checks apply as they do\n * to a person typing it in.\n */\n mutation: string\n /** The mutation's variables for one row. Absent when the target enters rows by group (below). */\n variables?(row: EntryRow): Record<string, unknown>\n /** What the conversation says of an entered row - its id and a short name. */\n appliedOf?(data: any, row: EntryRow): EntryApplied | undefined\n /**\n * A record with lines - one order, several item lines. Rows that share the value of `by` (the order number) are one\n * record, entered by one call of the mutation with `variables(rows)`. If any row of a group is kept out, the whole\n * group is: an order missing a line must not go in unseen.\n */\n group?: {\n by: string\n variables(rows: EntryRow[]): Record<string, unknown>\n appliedOf?(data: any, rows: EntryRow[]): EntryApplied | undefined\n }\n /** At most this many rows in one proposal. Default 200. */\n maxRows?: number\n /**\n * Read-only checks the application owns - a duplicate of what is already entered, a code that does not\n * exist. Asked when the rows are proposed and again when they are entered: the records may have moved.\n * Returns one list per row, in order.\n */\n check?(rows: EntryRow[], context: EntryContext): EntryIssue[][] | Promise<EntryIssue[][]>\n /** Told of every proposal and every entering - an application that audits its assistant writes it down. A throw is ignored. */\n record?(event: EntryEvent, context: EntryContext): void | Promise<void>\n /** Changing records that exist (design/ai/data-entry.md §5-1). Absent: this target only enters new ones. */\n update?: EntryUpdate\n}\n\n/** One record as the application's read query answers it - an `id` and the fields. */\nexport type EntryRecord = { id: string } & Record<string, unknown>\n\n/**\n * How records of a target are changed - every step through the application's API, as the person.\n *\n * Which record is meant is the server's to settle, never the model's memory: whichever way it was picked\n * (on screen, selected, described), the server reads it with `read` before a card is made and again before\n * it is written.\n */\nexport interface EntryUpdate {\n /** Reads the records by id, as the person - one they may not see is not found. */\n read: { query: string; variables(ids: string[]): Record<string, unknown>; recordsOf(data: any, ids: string[]): EntryRecord[] }\n /** Finds candidates from what the person said - \"last week's 12,400 taxi\". */\n find?: { query: string; variables(criteria: Record<string, unknown>): Record<string, unknown>; recordsOf(data: any, criteria: Record<string, unknown>): EntryRecord[]; criteria: EntryField[] }\n /** The application's own mutation that changes one record. */\n mutation: string\n variables(change: { id: string; record: EntryRecord; values: Record<string, unknown> }): Record<string, unknown>\n /** How a record is named on the card - \"2026-09-12 · 카카오T\". */\n labelOf?(record: EntryRecord): string\n /** The fields that may change. Default: every declared field. */\n fields?: string[]\n}\n\n/**\n * `Mutation.<root field>` of the target's mutation - the one declaration both the tool's gate and the\n * entering read. A document that is not one mutation with one root field is refused at boot.\n */\nexport function entryDoorOf(mutation: string): string {\n return rootFieldOf(mutation, 'mutation')\n}\n\n/** `Query.<field>` or `Mutation.<field>` of a document with one operation and one root field. */\nexport function rootFieldOf(document: string, operation: 'query' | 'mutation'): string {\n const doc = parse(document)\n const operations = doc.definitions.filter((one: any) => one.kind === 'OperationDefinition') as any[]\n if (operations.length !== 1 || operations[0].operation !== operation) throw new Error(`is not one ${operation}`)\n const fields = operations[0].selectionSet.selections.filter((one: any) => one.kind === 'Field')\n if (fields.length !== 1) throw new Error('must have exactly one root field')\n return `${operation === 'query' ? 'Query' : 'Mutation'}.${fields[0].name.value}`\n}\n\n/** Tells the target, and never lets its record keeping stop the work. */\nexport async function recordEntryEvent(target: EntryTarget, event: EntryEvent, context: EntryContext): Promise<void> {\n if (!target.record) return\n try {\n await target.record(event, context)\n } catch {\n /* an audit that failed to write is the application's to report */\n }\n}\n\nexport const DEFAULT_MAX_ROWS = 200\n\n/* The model's way of saying a value came from the person - kept only to read older rows and loose words. */\nconst PERSON = /person|message|user|사용자|말/i\n\nconst targets = new Map<string, EntryTarget>()\n\nconst KEY = /^[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*$/\n\n/** Validates and keeps a target - `registerEntryTarget` (entry-tools.ts) also opens its tool. A malformed declaration is refused at boot, not in a conversation. */\nexport function declareEntryTarget(target: EntryTarget): void {\n if (!KEY.test(target?.key ?? '')) throw new Error(`[ai-assistant] entry target key '${target?.key}' is not '<app>.<record>'.`)\n try {\n entryDoorOf(target.mutation ?? '')\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': its mutation ${error?.message ?? 'does not parse'}.`)\n }\n if (typeof target.variables !== 'function' && typeof target.group?.variables !== 'function')\n throw new Error(`[ai-assistant] entry target '${target.key}' has no variables (per row, or per group).`)\n if (target.group && !target.fields.some(field => field.name === target.group!.by))\n throw new Error(`[ai-assistant] entry target '${target.key}': group by '${target.group.by}' is not a declared field.`)\n if (target.update) {\n for (const [what, document, operation] of [\n ['update.read', target.update.read?.query, 'query'],\n ['update.mutation', target.update.mutation, 'mutation'],\n ...(target.update.find ? [['update.find', target.update.find.query, 'query']] : [])\n ] as [string, string, 'query' | 'mutation'][]) {\n try {\n rootFieldOf(document ?? '', operation)\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': ${what} ${error?.message ?? 'does not parse'}.`)\n }\n }\n const known = new Set(target.fields.map(field => field.name))\n for (const name of target.update.fields ?? []) if (!known.has(name)) throw new Error(`[ai-assistant] entry target '${target.key}': update field '${name}' is not declared.`)\n }\n if (!target.fields?.length) throw new Error(`[ai-assistant] entry target '${target.key}' declares no fields.`)\n const names = new Set<string>()\n for (const field of target.fields) {\n if (field.type === 'reference') {\n try {\n rootFieldOf(field.reference?.query ?? '', 'query')\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': reference field '${field.name}' ${error?.message ?? 'has no query'}.`)\n }\n }\n if (names.has(field.name)) throw new Error(`[ai-assistant] entry target '${target.key}' declares '${field.name}' twice.`)\n names.add(field.name)\n if (field.type === 'enum' && !field.values?.length)\n throw new Error(`[ai-assistant] entry target '${target.key}': enum field '${field.name}' lists no values.`)\n }\n targets.set(target.key, target)\n}\n\nexport function entryTargetOf(key: string | undefined): EntryTarget | undefined {\n return key ? targets.get(key) : undefined\n}\n\nexport function entryTargets(): EntryTarget[] {\n return [...targets.values()]\n}\n\n/** For tests. */\nexport function clearEntryTargets(): void {\n targets.clear()\n}\n\nconst pascalOf = (key: string) =>\n key\n .split(/[.-]/)\n .filter(Boolean)\n .map(part => part[0].toUpperCase() + part.slice(1))\n .join('')\n\n/** `office.expense-line` → `proposeOfficeExpenseLineChanges` / `findOfficeExpenseLine` - the tools of changing. */\nexport const changeToolName = (key: string) => `propose${pascalOf(key)}Changes`\nexport const findToolName = (key: string) => `find${pascalOf(key)}`\n\n/** `office.expense-line` → `proposeOfficeExpenseLineEntries` - one tool per target, so each has its own door. */\nexport function entryToolName(key: string): string {\n const pascal = key\n .split(/[.-]/)\n .filter(Boolean)\n .map(part => part[0].toUpperCase() + part.slice(1))\n .join('')\n return `propose${pascal}Entries`\n}\n\nexport function entryCategoryName(key: string): string {\n return `data-entry:${key}`\n}\n\nconst empty = (value: unknown) => value === undefined || value === null || (typeof value === 'string' && !value.trim())\n\n/** \"12,400\" · \"₩12,400\" · \"12 400\" → 12400. Only the separators people write; anything else is not a number. */\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value !== 'string') return undefined\n const cleaned = value.trim().replace(/^[₩$€¥£]\\s*/, '').replace(/[,\\s]/g, '').replace(/원$/, '')\n if (!/^-?\\d+(\\.\\d+)?$/.test(cleaned)) return undefined\n return Number(cleaned)\n}\n\n/** A calendar date as `YYYY-MM-DD` - \"2026.9.12\", \"2026/09/12\" too. A day that does not exist is not a date. */\nfunction toDate(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const match = value.trim().match(/^(\\d{4})[-./](\\d{1,2})[-./](\\d{1,2})\\.?$/)\n if (!match) return undefined\n const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])]\n const date = new Date(Date.UTC(year, month - 1, day))\n if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return undefined\n return `${match[1]}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`\n}\n\n/**\n * A moment as `YYYY-MM-DDTHH:mm:ss`, with the offset when it was written - \"2026-10-01 08:30\", \"2026.10.1 8:30\",\n * an ISO string. Without an offset it stays without one: the application reads it in its own time zone, as it\n * reads a time typed into its own screen.\n */\nfunction toDateTime(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const match = value.trim().match(/^(\\d{4})[-./](\\d{1,2})[-./](\\d{1,2})[ T](\\d{1,2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?\\s*(Z|[+-]\\d{2}:?\\d{2})?$/)\n if (!match) return undefined\n const day = toDate(`${match[1]}-${match[2]}-${match[3]}`)\n const [hour, minute, second] = [Number(match[4]), Number(match[5]), Number(match[6] ?? 0)]\n if (!day || hour > 23 || minute > 59 || second > 59) return undefined\n const offset = match[7] ? (match[7] === 'Z' ? 'Z' : match[7].replace(/^([+-]\\d{2})(\\d{2})$/, '$1:$2')) : ''\n return `${day}T${String(hour).padStart(2, '0')}:${match[5]}:${String(second).padStart(2, '0')}${offset}`\n}\n\nfunction toBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value\n if (typeof value !== 'string') return undefined\n const text = value.trim().toLowerCase()\n if (['true', 'yes', 'y', '1'].includes(text)) return true\n if (['false', 'no', 'n', '0'].includes(text)) return false\n return undefined\n}\n\n/** One value in its field's type - or the code of why it is not. An empty value is the caller's to judge. */\nexport function readFieldValue(field: EntryField, value: unknown): { read?: unknown; code?: string } {\n switch (field.type) {\n case 'number': {\n const read = toNumber(value)\n return read === undefined ? { code: 'not-a-number' } : { read }\n }\n case 'integer': {\n const read = toNumber(value)\n return read === undefined || !Number.isInteger(read) ? { code: 'not-an-integer' } : { read }\n }\n case 'date': {\n const read = toDate(value)\n return read === undefined ? { code: 'not-a-date' } : { read }\n }\n case 'datetime': {\n const read = toDateTime(value)\n return read === undefined ? { code: 'not-a-datetime' } : { read }\n }\n case 'boolean': {\n const read = toBoolean(value)\n return read === undefined ? { code: 'not-a-boolean' } : { read }\n }\n case 'enum':\n return field.values!.includes(String(value).trim()) ? { read: String(value).trim() } : { code: 'not-in-list' }\n case 'reference':\n /* Resolved already ({ id }), or a name to look up ({ text }) - resolveReferences settles the second. */\n if (value && typeof value === 'object' && typeof (value as any).id === 'string') return { read: { id: (value as any).id, ...((value as any).label ? { label: String((value as any).label) } : {}) } }\n if (value && typeof value === 'object' && typeof (value as any).text === 'string') return { read: { text: (value as any).text } }\n return typeof value === 'string' || typeof value === 'number' ? { read: { text: String(value).trim() } } : { code: 'not-a-reference' }\n default:\n return { read: String(value).trim() }\n }\n}\n\n/** Two values of one field the same - \"12400.00\" read from the database is 12400. */\nexport function sameFieldValue(field: EntryField, a: unknown, b: unknown): boolean {\n if (empty(a) && empty(b)) return true\n if (empty(a) || empty(b)) return false\n if (field.type === 'reference') {\n const idOf = (v: any) => (v && typeof v === 'object' ? v.id ?? v.text : String(v))\n return idOf(a) === idOf(b)\n }\n const x = readFieldValue(field, a)\n const y = readFieldValue(field, b)\n return x.read !== undefined && y.read !== undefined ? x.read === y.read : String(a) === String(b)\n}\n\n/**\n * The rows as the target reads them - each value in its field's type, and what was wrong said as an issue.\n *\n * A value that does not fit is **kept as it was written and marked**, never dropped or guessed: the card\n * shows what the material said, and the person corrects it in the conversation.\n */\nexport function normalizeEntryRows(target: EntryTarget, input: unknown): { rows: EntryRow[]; cut: number } {\n const list = Array.isArray(input) ? input : []\n const max = target.maxRows ?? DEFAULT_MAX_ROWS\n const fields = new Map(target.fields.map(field => [field.name, field]))\n\n const rows = list.slice(0, max).map((raw: any, index): EntryRow => {\n const given = raw && typeof raw.values === 'object' && raw.values ? raw.values : {}\n const values: Record<string, unknown> = {}\n const issues: EntryIssue[] = []\n\n for (const name of Object.keys(given)) {\n if (!fields.has(name)) issues.push({ field: name, code: 'unknown-field', blocking: false })\n }\n\n for (const field of target.fields) {\n const value = given[field.name]\n if (empty(value)) {\n if (field.required) issues.push({ field: field.name, code: 'required', blocking: true })\n continue\n }\n const { read, code } = readFieldValue(field, value)\n if (read === undefined) {\n values[field.name] = value\n issues.push({ field: field.name, code: code!, params: code === 'not-in-list' ? { values: field.values } : undefined, blocking: true })\n } else {\n values[field.name] = read\n }\n }\n\n const sources: EntrySource[] = Array.isArray(raw?.sources)\n ? raw.sources\n .filter((one: any) => one && (one.attachmentId || one.where || one.person === true))\n .map((one: any): EntrySource => {\n /* \"the person's message\" written by the model is the person flag - the screen says it in its own words. */\n if (one.person === true || (!one.attachmentId && typeof one.where === 'string' && PERSON.test(one.where))) return { person: true }\n return {\n ...(typeof one.attachmentId === 'string' ? { attachmentId: one.attachmentId } : {}),\n ...(typeof one.where === 'string' ? { where: one.where.slice(0, 120) } : {})\n }\n })\n : []\n if (!sources.length) issues.push({ code: 'no-source', blocking: false })\n\n return { index, values, sources, issues }\n })\n\n return { rows, cut: Math.max(0, list.length - max) }\n}\n\n/** Adds the target's own findings to each row. A check that throws marks nothing and is reported by the caller. */\nexport function withCheckedIssues(rows: EntryRow[], found: EntryIssue[][] | undefined): EntryRow[] {\n if (!found) return rows\n return rows.map((row, i) => (found[i]?.length ? { ...row, issues: [...row.issues, ...found[i]] } : row))\n}\n\nexport function isBlocked(row: EntryRow): boolean {\n return row.issues.some(issue => issue.blocking)\n}\n\n/* ── Checking the rows against the material (design/ai/data-entry.md §4-1) ─────────────────────────────\n *\n * A row cites where it came from; the model's word is not proof. For a text source the server looks: the\n * row's numbers and dates must stand together on one line of the cited file. Found - the row carries that\n * line as evidence. A value the file does not have is marked, unless the row also cites the person's\n * message (a correction said in the conversation). A photo cannot be read here - the row says so.\n * Names and descriptions are not looked for: the model tidies them, and a tidied name is not a wrong one.\n */\n\n\n/** The ways a number or a date is written in a file. */\nexport function writtenForms(type: EntryFieldType, value: unknown): string[] {\n if (type === 'number' || type === 'integer') {\n if (typeof value !== 'number' || !Number.isFinite(value)) return []\n const negative = value < 0\n const abs = Math.abs(value)\n const fixed = Number.isInteger(abs) ? String(abs) : abs.toFixed(2).replace(/0+$/, '').replace(/\\.$/, '')\n const [int, frac] = fixed.split('.')\n const grouped = int.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n const forms = new Set<string>()\n for (const whole of [int, grouped]) {\n forms.add(frac ? `${whole}.${frac}` : whole)\n if (!frac) forms.add(`${whole}.00`)\n }\n return [...forms].map(form => (negative ? `-${form}` : form))\n }\n if (type === 'datetime') {\n /* A moment is found by its day and its hh:mm - the file writes seconds and zones its own way. */\n const match = typeof value === 'string' ? value.match(/^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}):(\\d{2})/) : null\n if (!match) return []\n return writtenForms('date', match[1])\n }\n if (type === 'date') {\n const match = typeof value === 'string' ? value.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/) : null\n if (!match) return []\n const [, y, m, d] = match\n const mm = String(Number(m))\n const dd = String(Number(d))\n return [`${y}-${m}-${d}`, `${y}.${m}.${d}`, `${y}/${m}/${d}`, `${y}${m}${d}`, `${y}.${mm}.${dd}`, `${y}/${mm}/${dd}`, `${y}-${mm}-${dd}`, `${y.slice(2)}.${m}.${d}`, `${y.slice(2)}/${m}/${d}`]\n }\n return []\n}\n\n/**\n * A form found as a whole number - \"12,400\" is not found in \"112,400\", \"12,4001\", \"12,400.50\" or \"12,400,000\";\n * \"2026-09-12\" not in \"2026-09-120\". A CSV's own commas are not part of the number.\n */\nexport function lineHas(line: string, forms: string[]): boolean {\n const digit = (c: string | undefined) => !!c && c >= '0' && c <= '9'\n return forms.some(form => {\n for (let at = line.indexOf(form); at >= 0; at = line.indexOf(form, at + 1)) {\n const before = line[at - 1]\n const after = line[at + form.length]\n /* A comma is also the column separator of a CSV: only a comma and three digits more continue the number. */\n if (digit(before) || (before === '.' && digit(line[at - 2]))) continue\n if (digit(after) || (after === '.' && digit(line[at + form.length + 1]))) continue\n if (after === ',' && /^,\\d{3}(?!\\d)/.test(line.slice(at + form.length))) continue\n return true\n }\n return false\n })\n}\n\n/**\n * Checks each row against the text of the files it cites. `texts` holds what could be read, by attachment id;\n * an id that is not there was an image, or could not be opened.\n */\nexport function verifyRowsAgainstSources(rows: EntryRow[], fields: EntryField[], texts: Map<string, string>): EntryRow[] {\n const checked = fields.filter(field => ['number', 'integer', 'date'].includes(field.type))\n return rows.map(row => {\n const files = row.sources.map(source => source.attachmentId).filter((id): id is string => !!id)\n if (!files.length || !checked.length) return row\n const readable = files.filter(id => texts.has(id))\n if (!readable.length) return { ...row, issues: [...row.issues, { code: 'source-not-checked', blocking: false }] }\n\n const forms = checked\n .map(field => ({ field, forms: writtenForms(field.type, row.values[field.name]) }))\n .filter(one => one.forms.length)\n if (!forms.length) return row\n\n for (const id of readable) {\n const lines = texts.get(id)!.split(/\\r?\\n/)\n const at = lines.findIndex(line => forms.every(one => lineHas(line, one.forms)))\n if (at >= 0) return { ...row, evidence: { attachmentId: id, line: at + 1 } }\n }\n\n const saidByPerson = row.sources.some(source => source.person)\n const issues = [...row.issues]\n for (const one of forms) {\n const anywhere = readable.some(id => texts.get(id)!.split(/\\r?\\n/).some(line => lineHas(line, one.forms)))\n if (!anywhere && !saidByPerson) issues.push({ field: one.field.name, code: 'not-in-source', blocking: false })\n }\n if (issues.length === row.issues.length) issues.push({ code: 'source-scattered', blocking: false })\n return { ...row, issues }\n })\n}\n\n/**\n * The total a file prints - a line named 합계 · 총계 · 총액 · total · sum, and the last amount on it. The server\n * reads it itself, so the card can compare even when the model did not say it (2026-10-01: once it did, once not).\n */\nexport function printedTotalOf(text: string): { value: number; line: number } | undefined {\n const lines = text.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i--) {\n if (!/(합\\s*계|총\\s*계|총\\s*액|total|sum)/i.test(lines[i])) continue\n const amounts = [...lines[i].matchAll(/-?\\d{1,3}(?:,\\d{3})+(?:\\.\\d+)?|-?\\d+(?:\\.\\d+)?/g)].map(match => Number(match[0].replace(/,/g, '')))\n if (amounts.length) return { value: amounts[amounts.length - 1], line: i + 1 }\n }\n return undefined\n}\n\nexport interface EntryTotal {\n field: string\n /** The sum over every row, and over the rows that will be entered. */\n all: number\n ready: number\n /** The total the material prints, as the model read it - and whether the server found it in the file. */\n declared?: number\n declaredFound?: boolean\n /** declared - all. */\n difference?: number\n /** Where the declared total came from - the model's reading, or the server's own from a file's total line. */\n declaredBy?: 'model' | 'file'\n}\n\n/** The sums of the fields declared `total`, and how they stand against the total the material prints. */\nexport function entryTotals(\n rows: EntryRow[],\n fields: EntryField[],\n declared: { field?: string; value?: unknown; attachmentId?: string } | undefined,\n texts: Map<string, string>\n): EntryTotal[] {\n const totalled = fields.filter(field => field.total && (field.type === 'number' || field.type === 'integer'))\n /* With one totalled field and no total from the model, the server looks for the file's own total line. */\n const printed = !declared && totalled.length === 1 ? [...texts.values()].map(printedTotalOf).find(Boolean) : undefined\n return totalled\n .map(field => {\n const sum = (list: EntryRow[]) => Math.round(list.reduce((acc, row) => acc + (typeof row.values[field.name] === 'number' ? (row.values[field.name] as number) : 0), 0) * 100) / 100\n const total: EntryTotal = { field: field.name, all: sum(rows), ready: sum(rows.filter(row => !isBlocked(row))) }\n if (printed) {\n total.declared = printed.value\n total.declaredFound = true\n total.declaredBy = 'file'\n total.difference = Math.round((printed.value - total.all) * 100) / 100\n return total\n }\n /*\n * With one totalled field the model's total is that field's, whatever it named it - on office's second card it\n * wrote the file's column name (이용금액) for amount, and the total was dropped (2026-10-01).\n */\n const mine = declared && (totalled.length === 1 || (declared.field ?? field.name) === field.name)\n const value = mine ? toNumber(declared!.value) : undefined\n if (value !== undefined) {\n total.declaredBy = 'model'\n total.declared = value\n total.difference = Math.round((value - total.all) * 100) / 100\n const text = declared!.attachmentId ? texts.get(declared!.attachmentId) : undefined\n if (text !== undefined) total.declaredFound = text.split(/\\r?\\n/).some(line => lineHas(line, writtenForms(field.type, value)))\n }\n return total\n })\n}\n\n/** The doors of the queries a target's reference fields reach - the person must pass them too. */\nexport function referenceDoorsOf(fields: EntryField[]): string[] {\n return [...new Set(fields.filter(field => field.type === 'reference' && field.reference).map(field => rootFieldOf(field.reference!.query, 'query')))]\n}\n\n/**\n * Settles each reference a row names by text, through the application's query as the person. One match keeps its\n * id and name; none or several keep the row out - several with their names, so the person can say which.\n */\nexport async function resolveReferences<T extends { values: Record<string, unknown>; issues: EntryIssue[] }>(\n fields: EntryField[],\n rows: T[],\n run: (document: string, variables: Record<string, unknown>) => Promise<{ data?: any; errors?: readonly { message: string }[] }>\n): Promise<T[]> {\n const references = fields.filter(field => field.type === 'reference' && field.reference)\n if (!references.length) return rows\n const asked = new Map<string, { id: string; label?: string }[] | Error>()\n for (const row of rows) {\n for (const field of references) {\n const value: any = row.values[field.name]\n if (!value || typeof value !== 'object' || typeof value.text !== 'string') continue\n const key = `${field.name}\\u0000${value.text}`\n if (!asked.has(key)) {\n try {\n const answer = await run(field.reference!.query, field.reference!.variables(value.text))\n asked.set(key, answer.errors?.length ? new Error(answer.errors[0].message) : field.reference!.recordsOf(answer.data, value.text) ?? [])\n } catch (error: any) {\n asked.set(key, error instanceof Error ? error : new Error(String(error)))\n }\n }\n const found = asked.get(key)!\n if (found instanceof Error) {\n row.issues.push({ field: field.name, code: 'reference-unreadable', params: { text: value.text }, blocking: true })\n } else if (found.length === 1) {\n row.values[field.name] = { id: found[0].id, ...(found[0].label ? { label: found[0].label } : {}) }\n } else {\n row.issues.push({\n field: field.name,\n code: found.length ? 'reference-ambiguous' : 'reference-not-found',\n params: { text: value.text, ...(found.length ? { candidates: found.slice(0, 5).map(one => one.label || one.id).join(', ') } : {}) },\n blocking: true\n })\n }\n }\n }\n return rows\n}\n\n/** The rows by group, in the order groups first appear - `[key, rows]`. A row without the key is a group of its own. */\nexport function entryGroups<T extends { index: number; values: Record<string, unknown> }>(rows: T[], by: string): [string, T[]][] {\n const groups = new Map<string, T[]>()\n for (const row of rows) {\n const value = row.values[by]\n const key = value === undefined || value === null || value === '' ? `\\u0000row-${row.index}` : String(typeof value === 'object' ? (value as any).id ?? (value as any).text : value)\n groups.set(key, [...(groups.get(key) ?? []), row])\n }\n return [...groups.entries()]\n}\n\n/** The UTC offset a time zone has at a wall time - \"+09:00\". DST is taken at that day, not today. */\nexport function offsetAt(timeZone: string | undefined, wall: string): string | undefined {\n const match = wall.match(/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$/)\n if (!match) return undefined\n const [y, mo, d, h, mi, se] = match.slice(1).map(Number)\n let format: Intl.DateTimeFormat\n try {\n format = new Intl.DateTimeFormat('en-US', { timeZone: timeZone || undefined, timeZoneName: 'longOffset', year: 'numeric' })\n } catch {\n return undefined\n }\n const minutesOf = (at: number) => {\n const name = format.formatToParts(new Date(at)).find(part => part.type === 'timeZoneName')?.value ?? 'GMT'\n const m = name.match(/GMT([+-])(\\d{2}):?(\\d{2})?/)\n return m ? (m[1] === '-' ? -1 : 1) * (Number(m[2]) * 60 + Number(m[3] ?? 0)) : 0\n }\n /* The offset at the wall time read as UTC, then once more at the instant that gives - right across a DST change. */\n const asUtc = Date.UTC(y, mo - 1, d, h, mi, se)\n const minutes = minutesOf(asUtc - minutesOf(asUtc) * 60_000)\n const sign = minutes < 0 ? '-' : '+'\n const abs = Math.abs(minutes)\n return `${sign}${String(Math.floor(abs / 60)).padStart(2, '0')}:${String(abs % 60).padStart(2, '0')}`\n}\n\n/**\n * A moment written without an offset is the domain's wall time - \"08:30\" in a factory is 08:30 there. Each such\n * value gets the domain time zone's offset at that day, so an API taking DateTimeISO accepts it and reads the moment\n * meant (plant refused every downtime log without it, 2026-10-01).\n */\nexport function zonedDateTimes<T extends { values: Record<string, unknown> }>(fields: EntryField[], rows: T[], timeZone: string | undefined): T[] {\n const moments = fields.filter(field => field.type === 'datetime')\n if (!moments.length) return rows\n for (const row of rows) {\n for (const field of moments) {\n const value = row.values[field.name]\n if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/.test(value)) continue\n const offset = offsetAt(timeZone, value)\n if (offset) row.values[field.name] = `${value}${offset}`\n }\n }\n return rows\n}\n\n"]}
1
+ {"version":3,"file":"entry-target.js","sourceRoot":"","sources":["../../../server/service/data-entry/entry-target.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Data entry from material - what an application declares so the assistant can enter its records\n * (operato-application/design/ai/data-entry.md).\n *\n * A person hands the conversation what the records are made of - a bank export, a photo of a receipt,\n * lines pasted from a mail - and the assistant turns it into rows of one of the application's records.\n * Nothing is written by the model. It proposes the rows; the card shows them with what was wrong in\n * each and where each came from; a correction is said in the conversation and the model proposes again;\n * the person presses the button; the server enters each row **through the application's own GraphQL\n * mutation**, run with the person's request state - the same door, directives and checks as entering by hand.\n * There is no second way into the record.\n *\n * This file is pure - no framework, no database - so the rules a row passes are tested without a server.\n */\nimport { parse } from 'graphql'\n\nexport type EntryFieldType = 'string' | 'text' | 'number' | 'integer' | 'date' | 'datetime' | 'boolean' | 'enum' | 'reference'\n\nexport interface EntryField {\n name: string\n type: EntryFieldType\n required?: boolean\n /** The allowed values of an `enum` field. */\n values?: string[]\n /** What the model reads about the field - English, like every tool description. */\n description?: string\n /** i18n key of the column heading on the card. Absent: the field name. */\n labelKey?: string\n /** A number field the card sums - and compares with the total the material prints (§ totals). */\n total?: boolean\n /** An enum's values on the card: `<prefix><value in lowercase>` - `text.expense-payment-` shows PERSONAL_CARD as 개인카드. */\n valueKeyPrefix?: string\n /**\n * A `reference` field points at another record - a loan, an item, a location. The model knows it by a name or\n * a code; the server finds it through the application's query, as the person, and keeps its id. One match is\n * taken; none or several keep the row out and say so - the server never picks among several.\n */\n reference?: EntryReference\n}\n\nexport interface EntryReference {\n query: string\n /** The query's variables for what the model wrote - \"기업은행\", \"A-100\". */\n variables(text: string): Record<string, unknown>\n /** The records the answer holds that the text names - the application filters, the server does not guess. */\n recordsOf(data: any, text: string): { id: string; label?: string }[]\n}\n\n/** A resolved reference, as a row keeps it. */\nexport interface ReferenceValue {\n id: string\n label?: string\n}\n\n/** Where a row came from - which file, and where in it. Shown on the card beside the row. */\nexport interface EntrySource {\n attachmentId?: string\n /** \"row 3\", \"the receipt photo\" - the model's words, in the person's language. */\n where?: string\n /** The value came from what the person said in the conversation - shown in the screen's own words, never the model's. */\n person?: boolean\n}\n\nexport interface EntryIssue {\n /** The field it is about. Absent: the row as a whole. */\n field?: string\n /** A code the screen translates: `ai-assistant.entry.issue.<code>`, or the target's own `messageKey`. */\n code: string\n messageKey?: string\n params?: Record<string, unknown>\n /** A param that is a code the screen words - { status: 'text.state-' } shows `down` as 고장. */\n paramKeys?: Record<string, string>\n /** A blocking issue keeps the row out when the person presses the button. */\n blocking: boolean\n}\n\nexport interface EntryRowInput {\n values?: Record<string, unknown>\n sources?: EntrySource[]\n}\n\nexport interface EntryRow {\n index: number\n values: Record<string, unknown>\n sources: EntrySource[]\n issues: EntryIssue[]\n /** The line of a text source where this row's numbers and dates were all found - the server's check, not the model's word. */\n evidence?: { attachmentId: string; line: number }\n}\n\nexport interface EntryContext {\n /** The request state - domain, user, and when writing, `tx` and `afterCommit`. */\n state: any\n}\n\nexport interface EntryApplied {\n /** The created record's id, when there is one. */\n id?: string\n /** A short name for the conversation line - \"2026-09-12 · 택시 · ₩12,400\". */\n label?: string\n}\n\n/** What happened, for an application that writes down every assistant call (office's AI audit). */\nexport interface EntryEvent {\n phase: 'propose' | 'apply'\n tool: string\n rows: number\n ok: boolean\n applied?: number\n missed?: number\n error?: string\n /** propose: the rows as the model gave them; apply: the proposal key and each row's result. */\n detail?: unknown\n}\n\nexport interface EntryTarget {\n /** `<app>.<record>` - `office.expense-line`. */\n key: string\n /** i18n key of the record's name on the card. */\n labelKey: string\n /** What one row is, for the model. */\n description: string\n fields: EntryField[]\n /**\n * The application's own mutation that enters one record, as a GraphQL document with one root field -\n * `mutation ($line: NewExpenseLine!) { addExpenseLine(line: $line) { id } }`. Its root field is the door:\n * the propose tool is offered only to someone who passes it, and each row is entered by running it with\n * the person's request state, so `@privilege`, `@transaction` and the door's own checks apply as they do\n * to a person typing it in.\n */\n mutation: string\n /** The mutation's variables for one row. Absent when the target enters rows by group (below). */\n variables?(row: EntryRow): Record<string, unknown>\n /** What the conversation says of an entered row - its id and a short name. */\n appliedOf?(data: any, row: EntryRow): EntryApplied | undefined\n /**\n * A record with lines - one order, several item lines. Rows that share the value of `by` (the order number) are one\n * record, entered by one call of the mutation with `variables(rows)`. If any row of a group is kept out, the whole\n * group is: an order missing a line must not go in unseen.\n */\n group?: {\n by: string\n variables(rows: EntryRow[]): Record<string, unknown>\n appliedOf?(data: any, rows: EntryRow[]): EntryApplied | undefined\n }\n /** At most this many rows in one proposal. Default 200. */\n maxRows?: number\n /**\n * Read-only checks the application owns - a duplicate of what is already entered, a code that does not\n * exist. Asked when the rows are proposed and again when they are entered: the records may have moved.\n * Returns one list per row, in order.\n */\n check?(rows: EntryRow[], context: EntryContext): EntryIssue[][] | Promise<EntryIssue[][]>\n /** Told of every proposal and every entering - an application that audits its assistant writes it down. A throw is ignored. */\n record?(event: EntryEvent, context: EntryContext): void | Promise<void>\n /** Changing records that exist (design/ai/data-entry.md §5-1). Absent: this target only enters new ones. */\n update?: EntryUpdate\n}\n\n/** One record as the application's read query answers it - an `id` and the fields. */\nexport type EntryRecord = { id: string } & Record<string, unknown>\n\n/**\n * How records of a target are changed - every step through the application's API, as the person.\n *\n * Which record is meant is the server's to settle, never the model's memory: whichever way it was picked\n * (on screen, selected, described), the server reads it with `read` before a card is made and again before\n * it is written.\n */\nexport interface EntryUpdate {\n /** Reads the records by id, as the person - one they may not see is not found. */\n read: { query: string; variables(ids: string[]): Record<string, unknown>; recordsOf(data: any, ids: string[]): EntryRecord[] }\n /** Finds candidates from what the person said - \"last week's 12,400 taxi\". */\n find?: { query: string; variables(criteria: Record<string, unknown>): Record<string, unknown>; recordsOf(data: any, criteria: Record<string, unknown>): EntryRecord[]; criteria: EntryField[] }\n /** The application's own mutation that changes one record. */\n mutation: string\n variables(change: { id: string; record: EntryRecord; values: Record<string, unknown> }): Record<string, unknown>\n /** How a record is named on the card - \"2026-09-12 · 카카오T\". */\n labelOf?(record: EntryRecord): string\n /** The fields that may change. Default: every declared field. */\n fields?: string[]\n /**\n * Read-only checks of the changes - a new name that another record already has. Asked when the card is made and\n * again when it is pressed, like an entry's check; one issue list per row. Without it a clash is caught only by\n * the database's own refusal.\n */\n check?(rows: { id: string; record?: EntryRecord; values: Record<string, unknown> }[], context: EntryContext): EntryIssue[][] | Promise<EntryIssue[][]>\n}\n\n/**\n * `Mutation.<root field>` of the target's mutation - the one declaration both the tool's gate and the\n * entering read. A document that is not one mutation with one root field is refused at boot.\n */\nexport function entryDoorOf(mutation: string): string {\n return rootFieldOf(mutation, 'mutation')\n}\n\n/** `Query.<field>` or `Mutation.<field>` of a document with one operation and one root field. */\nexport function rootFieldOf(document: string, operation: 'query' | 'mutation'): string {\n const doc = parse(document)\n const operations = doc.definitions.filter((one: any) => one.kind === 'OperationDefinition') as any[]\n if (operations.length !== 1 || operations[0].operation !== operation) throw new Error(`is not one ${operation}`)\n const fields = operations[0].selectionSet.selections.filter((one: any) => one.kind === 'Field')\n if (fields.length !== 1) throw new Error('must have exactly one root field')\n return `${operation === 'query' ? 'Query' : 'Mutation'}.${fields[0].name.value}`\n}\n\n/** Tells the target, and never lets its record keeping stop the work. */\nexport async function recordEntryEvent(target: EntryTarget, event: EntryEvent, context: EntryContext): Promise<void> {\n if (!target.record) return\n try {\n await target.record(event, context)\n } catch {\n /* an audit that failed to write is the application's to report */\n }\n}\n\nexport const DEFAULT_MAX_ROWS = 200\n\n/* The model's way of saying a value came from the person - kept only to read older rows and loose words. */\nconst PERSON = /person|message|user|사용자|말/i\n\nconst targets = new Map<string, EntryTarget>()\n\nconst KEY = /^[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*$/\n\n/** Validates and keeps a target - `registerEntryTarget` (entry-tools.ts) also opens its tool. A malformed declaration is refused at boot, not in a conversation. */\nexport function declareEntryTarget(target: EntryTarget): void {\n if (!KEY.test(target?.key ?? '')) throw new Error(`[ai-assistant] entry target key '${target?.key}' is not '<app>.<record>'.`)\n try {\n entryDoorOf(target.mutation ?? '')\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': its mutation ${error?.message ?? 'does not parse'}.`)\n }\n if (typeof target.variables !== 'function' && typeof target.group?.variables !== 'function')\n throw new Error(`[ai-assistant] entry target '${target.key}' has no variables (per row, or per group).`)\n if (target.group && !target.fields.some(field => field.name === target.group!.by))\n throw new Error(`[ai-assistant] entry target '${target.key}': group by '${target.group.by}' is not a declared field.`)\n if (target.update) {\n for (const [what, document, operation] of [\n ['update.read', target.update.read?.query, 'query'],\n ['update.mutation', target.update.mutation, 'mutation'],\n ...(target.update.find ? [['update.find', target.update.find.query, 'query']] : [])\n ] as [string, string, 'query' | 'mutation'][]) {\n try {\n rootFieldOf(document ?? '', operation)\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': ${what} ${error?.message ?? 'does not parse'}.`)\n }\n }\n const known = new Set(target.fields.map(field => field.name))\n for (const name of target.update.fields ?? []) if (!known.has(name)) throw new Error(`[ai-assistant] entry target '${target.key}': update field '${name}' is not declared.`)\n }\n if (!target.fields?.length) throw new Error(`[ai-assistant] entry target '${target.key}' declares no fields.`)\n const names = new Set<string>()\n for (const field of target.fields) {\n if (field.type === 'reference') {\n try {\n rootFieldOf(field.reference?.query ?? '', 'query')\n } catch (error: any) {\n throw new Error(`[ai-assistant] entry target '${target.key}': reference field '${field.name}' ${error?.message ?? 'has no query'}.`)\n }\n }\n if (names.has(field.name)) throw new Error(`[ai-assistant] entry target '${target.key}' declares '${field.name}' twice.`)\n names.add(field.name)\n if (field.type === 'enum' && !field.values?.length)\n throw new Error(`[ai-assistant] entry target '${target.key}': enum field '${field.name}' lists no values.`)\n }\n targets.set(target.key, target)\n}\n\nexport function entryTargetOf(key: string | undefined): EntryTarget | undefined {\n return key ? targets.get(key) : undefined\n}\n\nexport function entryTargets(): EntryTarget[] {\n return [...targets.values()]\n}\n\n/** For tests. */\nexport function clearEntryTargets(): void {\n targets.clear()\n}\n\nconst pascalOf = (key: string) =>\n key\n .split(/[.-]/)\n .filter(Boolean)\n .map(part => part[0].toUpperCase() + part.slice(1))\n .join('')\n\n/** `office.expense-line` → `proposeOfficeExpenseLineChanges` / `findOfficeExpenseLine` - the tools of changing. */\nexport const changeToolName = (key: string) => `propose${pascalOf(key)}Changes`\nexport const findToolName = (key: string) => `find${pascalOf(key)}`\n\n/** `office.expense-line` → `proposeOfficeExpenseLineEntries` - one tool per target, so each has its own door. */\nexport function entryToolName(key: string): string {\n const pascal = key\n .split(/[.-]/)\n .filter(Boolean)\n .map(part => part[0].toUpperCase() + part.slice(1))\n .join('')\n return `propose${pascal}Entries`\n}\n\nexport function entryCategoryName(key: string): string {\n return `data-entry:${key}`\n}\n\nconst empty = (value: unknown) => value === undefined || value === null || (typeof value === 'string' && !value.trim())\n\n/** \"12,400\" · \"₩12,400\" · \"12 400\" → 12400. Only the separators people write; anything else is not a number. */\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value !== 'string') return undefined\n const cleaned = value.trim().replace(/^[₩$€¥£]\\s*/, '').replace(/[,\\s]/g, '').replace(/원$/, '')\n if (!/^-?\\d+(\\.\\d+)?$/.test(cleaned)) return undefined\n return Number(cleaned)\n}\n\n/** A calendar date as `YYYY-MM-DD` - \"2026.9.12\", \"2026/09/12\" too. A day that does not exist is not a date. */\nfunction toDate(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const match = value.trim().match(/^(\\d{4})[-./](\\d{1,2})[-./](\\d{1,2})\\.?$/)\n if (!match) return undefined\n const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])]\n const date = new Date(Date.UTC(year, month - 1, day))\n if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return undefined\n return `${match[1]}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`\n}\n\n/**\n * A moment as `YYYY-MM-DDTHH:mm:ss`, with the offset when it was written - \"2026-10-01 08:30\", \"2026.10.1 8:30\",\n * an ISO string. Without an offset it stays without one: the application reads it in its own time zone, as it\n * reads a time typed into its own screen.\n */\nfunction toDateTime(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const match = value.trim().match(/^(\\d{4})[-./](\\d{1,2})[-./](\\d{1,2})[ T](\\d{1,2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?\\s*(Z|[+-]\\d{2}:?\\d{2})?$/)\n if (!match) return undefined\n const day = toDate(`${match[1]}-${match[2]}-${match[3]}`)\n const [hour, minute, second] = [Number(match[4]), Number(match[5]), Number(match[6] ?? 0)]\n if (!day || hour > 23 || minute > 59 || second > 59) return undefined\n const offset = match[7] ? (match[7] === 'Z' ? 'Z' : match[7].replace(/^([+-]\\d{2})(\\d{2})$/, '$1:$2')) : ''\n return `${day}T${String(hour).padStart(2, '0')}:${match[5]}:${String(second).padStart(2, '0')}${offset}`\n}\n\nfunction toBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value\n if (typeof value !== 'string') return undefined\n const text = value.trim().toLowerCase()\n if (['true', 'yes', 'y', '1'].includes(text)) return true\n if (['false', 'no', 'n', '0'].includes(text)) return false\n return undefined\n}\n\n/** One value in its field's type - or the code of why it is not. An empty value is the caller's to judge. */\nexport function readFieldValue(field: EntryField, value: unknown): { read?: unknown; code?: string } {\n switch (field.type) {\n case 'number': {\n const read = toNumber(value)\n return read === undefined ? { code: 'not-a-number' } : { read }\n }\n case 'integer': {\n const read = toNumber(value)\n return read === undefined || !Number.isInteger(read) ? { code: 'not-an-integer' } : { read }\n }\n case 'date': {\n const read = toDate(value)\n return read === undefined ? { code: 'not-a-date' } : { read }\n }\n case 'datetime': {\n const read = toDateTime(value)\n return read === undefined ? { code: 'not-a-datetime' } : { read }\n }\n case 'boolean': {\n const read = toBoolean(value)\n return read === undefined ? { code: 'not-a-boolean' } : { read }\n }\n case 'enum':\n return field.values!.includes(String(value).trim()) ? { read: String(value).trim() } : { code: 'not-in-list' }\n case 'reference':\n /* Resolved already ({ id }), or a name to look up ({ text }) - resolveReferences settles the second. */\n if (value && typeof value === 'object' && typeof (value as any).id === 'string') return { read: { id: (value as any).id, ...((value as any).label ? { label: String((value as any).label) } : {}) } }\n if (value && typeof value === 'object' && typeof (value as any).text === 'string') return { read: { text: (value as any).text } }\n return typeof value === 'string' || typeof value === 'number' ? { read: { text: String(value).trim() } } : { code: 'not-a-reference' }\n default:\n return { read: String(value).trim() }\n }\n}\n\n/** Two values of one field the same - \"12400.00\" read from the database is 12400. */\nexport function sameFieldValue(field: EntryField, a: unknown, b: unknown): boolean {\n if (empty(a) && empty(b)) return true\n if (empty(a) || empty(b)) return false\n if (field.type === 'reference') {\n const idOf = (v: any) => (v && typeof v === 'object' ? v.id ?? v.text : String(v))\n return idOf(a) === idOf(b)\n }\n const x = readFieldValue(field, a)\n const y = readFieldValue(field, b)\n return x.read !== undefined && y.read !== undefined ? x.read === y.read : String(a) === String(b)\n}\n\n/**\n * The rows as the target reads them - each value in its field's type, and what was wrong said as an issue.\n *\n * A value that does not fit is **kept as it was written and marked**, never dropped or guessed: the card\n * shows what the material said, and the person corrects it in the conversation.\n */\nexport function normalizeEntryRows(target: EntryTarget, input: unknown): { rows: EntryRow[]; cut: number } {\n const list = Array.isArray(input) ? input : []\n const max = target.maxRows ?? DEFAULT_MAX_ROWS\n const fields = new Map(target.fields.map(field => [field.name, field]))\n\n const rows = list.slice(0, max).map((raw: any, index): EntryRow => {\n const given = raw && typeof raw.values === 'object' && raw.values ? raw.values : {}\n const values: Record<string, unknown> = {}\n const issues: EntryIssue[] = []\n\n for (const name of Object.keys(given)) {\n if (!fields.has(name)) issues.push({ field: name, code: 'unknown-field', blocking: false })\n }\n\n for (const field of target.fields) {\n const value = given[field.name]\n if (empty(value)) {\n if (field.required) issues.push({ field: field.name, code: 'required', blocking: true })\n continue\n }\n const { read, code } = readFieldValue(field, value)\n if (read === undefined) {\n values[field.name] = value\n issues.push({ field: field.name, code: code!, params: code === 'not-in-list' ? { values: field.values } : undefined, blocking: true })\n } else {\n values[field.name] = read\n }\n }\n\n const sources: EntrySource[] = Array.isArray(raw?.sources)\n ? raw.sources\n .filter((one: any) => one && (one.attachmentId || one.where || one.person === true))\n .map((one: any): EntrySource => {\n /* \"the person's message\" written by the model is the person flag - the screen says it in its own words. */\n if (one.person === true || (!one.attachmentId && typeof one.where === 'string' && PERSON.test(one.where))) return { person: true }\n return {\n ...(typeof one.attachmentId === 'string' ? { attachmentId: one.attachmentId } : {}),\n ...(typeof one.where === 'string' ? { where: one.where.slice(0, 120) } : {})\n }\n })\n : []\n if (!sources.length) issues.push({ code: 'no-source', blocking: false })\n\n return { index, values, sources, issues }\n })\n\n return { rows, cut: Math.max(0, list.length - max) }\n}\n\n/** Adds the target's own findings to each row. A check that throws marks nothing and is reported by the caller. */\nexport function withCheckedIssues(rows: EntryRow[], found: EntryIssue[][] | undefined): EntryRow[] {\n if (!found) return rows\n return rows.map((row, i) => (found[i]?.length ? { ...row, issues: [...row.issues, ...found[i]] } : row))\n}\n\nexport function isBlocked(row: EntryRow): boolean {\n return row.issues.some(issue => issue.blocking)\n}\n\n/* ── Checking the rows against the material (design/ai/data-entry.md §4-1) ─────────────────────────────\n *\n * A row cites where it came from; the model's word is not proof. For a text source the server looks: the\n * row's numbers and dates must stand together on one line of the cited file. Found - the row carries that\n * line as evidence. A value the file does not have is marked, unless the row also cites the person's\n * message (a correction said in the conversation). A photo cannot be read here - the row says so.\n * Names and descriptions are not looked for: the model tidies them, and a tidied name is not a wrong one.\n */\n\n\n/** The ways a number or a date is written in a file. */\nexport function writtenForms(type: EntryFieldType, value: unknown): string[] {\n if (type === 'number' || type === 'integer') {\n if (typeof value !== 'number' || !Number.isFinite(value)) return []\n const negative = value < 0\n const abs = Math.abs(value)\n const fixed = Number.isInteger(abs) ? String(abs) : abs.toFixed(2).replace(/0+$/, '').replace(/\\.$/, '')\n const [int, frac] = fixed.split('.')\n const grouped = int.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n const forms = new Set<string>()\n for (const whole of [int, grouped]) {\n forms.add(frac ? `${whole}.${frac}` : whole)\n if (!frac) forms.add(`${whole}.00`)\n }\n return [...forms].map(form => (negative ? `-${form}` : form))\n }\n if (type === 'datetime') {\n /* A moment is found by its day and its hh:mm - the file writes seconds and zones its own way. */\n const match = typeof value === 'string' ? value.match(/^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}):(\\d{2})/) : null\n if (!match) return []\n return writtenForms('date', match[1])\n }\n if (type === 'date') {\n const match = typeof value === 'string' ? value.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/) : null\n if (!match) return []\n const [, y, m, d] = match\n const mm = String(Number(m))\n const dd = String(Number(d))\n return [`${y}-${m}-${d}`, `${y}.${m}.${d}`, `${y}/${m}/${d}`, `${y}${m}${d}`, `${y}.${mm}.${dd}`, `${y}/${mm}/${dd}`, `${y}-${mm}-${dd}`, `${y.slice(2)}.${m}.${d}`, `${y.slice(2)}/${m}/${d}`]\n }\n return []\n}\n\n/**\n * A form found as a whole number - \"12,400\" is not found in \"112,400\", \"12,4001\", \"12,400.50\" or \"12,400,000\";\n * \"2026-09-12\" not in \"2026-09-120\". A CSV's own commas are not part of the number.\n */\nexport function lineHas(line: string, forms: string[]): boolean {\n const digit = (c: string | undefined) => !!c && c >= '0' && c <= '9'\n return forms.some(form => {\n for (let at = line.indexOf(form); at >= 0; at = line.indexOf(form, at + 1)) {\n const before = line[at - 1]\n const after = line[at + form.length]\n /* A comma is also the column separator of a CSV: only a comma and three digits more continue the number. */\n if (digit(before) || (before === '.' && digit(line[at - 2]))) continue\n if (digit(after) || (after === '.' && digit(line[at + form.length + 1]))) continue\n if (after === ',' && /^,\\d{3}(?!\\d)/.test(line.slice(at + form.length))) continue\n return true\n }\n return false\n })\n}\n\n/**\n * Checks each row against the text of the files it cites. `texts` holds what could be read, by attachment id;\n * an id that is not there was an image, or could not be opened.\n */\nexport function verifyRowsAgainstSources(rows: EntryRow[], fields: EntryField[], texts: Map<string, string>): EntryRow[] {\n const checked = fields.filter(field => ['number', 'integer', 'date'].includes(field.type))\n return rows.map(row => {\n const files = row.sources.map(source => source.attachmentId).filter((id): id is string => !!id)\n if (!files.length || !checked.length) return row\n const readable = files.filter(id => texts.has(id))\n if (!readable.length) return { ...row, issues: [...row.issues, { code: 'source-not-checked', blocking: false }] }\n\n const forms = checked\n .map(field => ({ field, forms: writtenForms(field.type, row.values[field.name]) }))\n .filter(one => one.forms.length)\n if (!forms.length) return row\n\n for (const id of readable) {\n const lines = texts.get(id)!.split(/\\r?\\n/)\n const at = lines.findIndex(line => forms.every(one => lineHas(line, one.forms)))\n if (at >= 0) return { ...row, evidence: { attachmentId: id, line: at + 1 } }\n }\n\n const saidByPerson = row.sources.some(source => source.person)\n const issues = [...row.issues]\n for (const one of forms) {\n const anywhere = readable.some(id => texts.get(id)!.split(/\\r?\\n/).some(line => lineHas(line, one.forms)))\n if (!anywhere && !saidByPerson) issues.push({ field: one.field.name, code: 'not-in-source', blocking: false })\n }\n if (issues.length === row.issues.length) issues.push({ code: 'source-scattered', blocking: false })\n return { ...row, issues }\n })\n}\n\n/**\n * The total a file prints - a line named 합계 · 총계 · 총액 · total · sum, and the last amount on it. The server\n * reads it itself, so the card can compare even when the model did not say it (2026-10-01: once it did, once not).\n */\nexport function printedTotalOf(text: string): { value: number; line: number } | undefined {\n const lines = text.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i--) {\n if (!/(합\\s*계|총\\s*계|총\\s*액|total|sum)/i.test(lines[i])) continue\n const amounts = [...lines[i].matchAll(/-?\\d{1,3}(?:,\\d{3})+(?:\\.\\d+)?|-?\\d+(?:\\.\\d+)?/g)].map(match => Number(match[0].replace(/,/g, '')))\n if (amounts.length) return { value: amounts[amounts.length - 1], line: i + 1 }\n }\n return undefined\n}\n\nexport interface EntryTotal {\n field: string\n /** The sum over every row, and over the rows that will be entered. */\n all: number\n ready: number\n /** The total the material prints, as the model read it - and whether the server found it in the file. */\n declared?: number\n declaredFound?: boolean\n /** declared - all. */\n difference?: number\n /** Where the declared total came from - the model's reading, or the server's own from a file's total line. */\n declaredBy?: 'model' | 'file'\n}\n\n/** The sums of the fields declared `total`, and how they stand against the total the material prints. */\nexport function entryTotals(\n rows: EntryRow[],\n fields: EntryField[],\n declared: { field?: string; value?: unknown; attachmentId?: string } | undefined,\n texts: Map<string, string>\n): EntryTotal[] {\n const totalled = fields.filter(field => field.total && (field.type === 'number' || field.type === 'integer'))\n /* With one totalled field and no total from the model, the server looks for the file's own total line. */\n const printed = !declared && totalled.length === 1 ? [...texts.values()].map(printedTotalOf).find(Boolean) : undefined\n return totalled\n .map(field => {\n const sum = (list: EntryRow[]) => Math.round(list.reduce((acc, row) => acc + (typeof row.values[field.name] === 'number' ? (row.values[field.name] as number) : 0), 0) * 100) / 100\n const total: EntryTotal = { field: field.name, all: sum(rows), ready: sum(rows.filter(row => !isBlocked(row))) }\n if (printed) {\n total.declared = printed.value\n total.declaredFound = true\n total.declaredBy = 'file'\n total.difference = Math.round((printed.value - total.all) * 100) / 100\n return total\n }\n /*\n * With one totalled field the model's total is that field's, whatever it named it - on office's second card it\n * wrote the file's column name (이용금액) for amount, and the total was dropped (2026-10-01).\n */\n const mine = declared && (totalled.length === 1 || (declared.field ?? field.name) === field.name)\n const value = mine ? toNumber(declared!.value) : undefined\n if (value !== undefined) {\n total.declaredBy = 'model'\n total.declared = value\n total.difference = Math.round((value - total.all) * 100) / 100\n const text = declared!.attachmentId ? texts.get(declared!.attachmentId) : undefined\n if (text !== undefined) total.declaredFound = text.split(/\\r?\\n/).some(line => lineHas(line, writtenForms(field.type, value)))\n }\n return total\n })\n}\n\n/** The doors of the queries a target's reference fields reach - the person must pass them too. */\nexport function referenceDoorsOf(fields: EntryField[]): string[] {\n return [...new Set(fields.filter(field => field.type === 'reference' && field.reference).map(field => rootFieldOf(field.reference!.query, 'query')))]\n}\n\n/**\n * Settles each reference a row names by text, through the application's query as the person. One match keeps its\n * id and name; none or several keep the row out - several with their names, so the person can say which.\n */\nexport async function resolveReferences<T extends { values: Record<string, unknown>; issues: EntryIssue[] }>(\n fields: EntryField[],\n rows: T[],\n run: (document: string, variables: Record<string, unknown>) => Promise<{ data?: any; errors?: readonly { message: string }[] }>\n): Promise<T[]> {\n const references = fields.filter(field => field.type === 'reference' && field.reference)\n if (!references.length) return rows\n const asked = new Map<string, { id: string; label?: string }[] | Error>()\n for (const row of rows) {\n for (const field of references) {\n const value: any = row.values[field.name]\n if (!value || typeof value !== 'object' || typeof value.text !== 'string') continue\n const key = `${field.name}\\u0000${value.text}`\n if (!asked.has(key)) {\n try {\n const answer = await run(field.reference!.query, field.reference!.variables(value.text))\n asked.set(key, answer.errors?.length ? new Error(answer.errors[0].message) : field.reference!.recordsOf(answer.data, value.text) ?? [])\n } catch (error: any) {\n asked.set(key, error instanceof Error ? error : new Error(String(error)))\n }\n }\n const found = asked.get(key)!\n if (found instanceof Error) {\n row.issues.push({ field: field.name, code: 'reference-unreadable', params: { text: value.text }, blocking: true })\n } else if (found.length === 1) {\n row.values[field.name] = { id: found[0].id, ...(found[0].label ? { label: found[0].label } : {}) }\n } else {\n row.issues.push({\n field: field.name,\n code: found.length ? 'reference-ambiguous' : 'reference-not-found',\n params: { text: value.text, ...(found.length ? { candidates: found.slice(0, 5).map(one => one.label || one.id).join(', ') } : {}) },\n blocking: true\n })\n }\n }\n }\n return rows\n}\n\n/** The rows by group, in the order groups first appear - `[key, rows]`. A row without the key is a group of its own. */\nexport function entryGroups<T extends { index: number; values: Record<string, unknown> }>(rows: T[], by: string): [string, T[]][] {\n const groups = new Map<string, T[]>()\n for (const row of rows) {\n const value = row.values[by]\n const key = value === undefined || value === null || value === '' ? `\\u0000row-${row.index}` : String(typeof value === 'object' ? (value as any).id ?? (value as any).text : value)\n groups.set(key, [...(groups.get(key) ?? []), row])\n }\n return [...groups.entries()]\n}\n\n/** The UTC offset a time zone has at a wall time - \"+09:00\". DST is taken at that day, not today. */\nexport function offsetAt(timeZone: string | undefined, wall: string): string | undefined {\n const match = wall.match(/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$/)\n if (!match) return undefined\n const [y, mo, d, h, mi, se] = match.slice(1).map(Number)\n let format: Intl.DateTimeFormat\n try {\n format = new Intl.DateTimeFormat('en-US', { timeZone: timeZone || undefined, timeZoneName: 'longOffset', year: 'numeric' })\n } catch {\n return undefined\n }\n const minutesOf = (at: number) => {\n const name = format.formatToParts(new Date(at)).find(part => part.type === 'timeZoneName')?.value ?? 'GMT'\n const m = name.match(/GMT([+-])(\\d{2}):?(\\d{2})?/)\n return m ? (m[1] === '-' ? -1 : 1) * (Number(m[2]) * 60 + Number(m[3] ?? 0)) : 0\n }\n /* The offset at the wall time read as UTC, then once more at the instant that gives - right across a DST change. */\n const asUtc = Date.UTC(y, mo - 1, d, h, mi, se)\n const minutes = minutesOf(asUtc - minutesOf(asUtc) * 60_000)\n const sign = minutes < 0 ? '-' : '+'\n const abs = Math.abs(minutes)\n return `${sign}${String(Math.floor(abs / 60)).padStart(2, '0')}:${String(abs % 60).padStart(2, '0')}`\n}\n\n/**\n * A moment written without an offset is the domain's wall time - \"08:30\" in a factory is 08:30 there. Each such\n * value gets the domain time zone's offset at that day, so an API taking DateTimeISO accepts it and reads the moment\n * meant (plant refused every downtime log without it, 2026-10-01).\n */\nexport function zonedDateTimes<T extends { values: Record<string, unknown> }>(fields: EntryField[], rows: T[], timeZone: string | undefined): T[] {\n const moments = fields.filter(field => field.type === 'datetime')\n if (!moments.length) return rows\n for (const row of rows) {\n for (const field of moments) {\n const value = row.values[field.name]\n if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/.test(value)) continue\n const offset = offsetAt(timeZone, value)\n if (offset) row.values[field.name] = `${value}${offset}`\n }\n }\n return rows\n}\n\n"]}
@@ -98,3 +98,10 @@ export declare function findRecords(target: EntryTarget, args: any, run: Graphql
98
98
  export declare function stillAsProposed(target: EntryTarget, rows: ChangeRow[], now: Map<string, EntryRecord>): (ChangeRow & {
99
99
  now?: EntryRecord;
100
100
  })[];
101
+ /**
102
+ * The target's own checks of the changes, added to each row. A check that could not run keeps every row out - a
103
+ * change is not written unchecked (an entry's failed check refuses its card the same way).
104
+ */
105
+ export declare function withChangeChecks<T extends ChangeRow>(target: EntryTarget, rows: T[], records: Map<string, EntryRecord>, context: {
106
+ state: any;
107
+ }): Promise<T[]>;