@graview/core 0.1.54 → 0.1.56

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.
Files changed (208) hide show
  1. package/dist/alias-findings.d.ts +40 -0
  2. package/dist/alias-findings.d.ts.map +1 -0
  3. package/dist/alias-findings.js +95 -0
  4. package/dist/alias-findings.js.map +1 -0
  5. package/dist/app.d.ts +13 -0
  6. package/dist/app.d.ts.map +1 -1
  7. package/dist/app.js.map +1 -1
  8. package/dist/arranging.d.ts +6 -1
  9. package/dist/arranging.d.ts.map +1 -1
  10. package/dist/arranging.js +21 -3
  11. package/dist/arranging.js.map +1 -1
  12. package/dist/capabilities.js +1 -1
  13. package/dist/capabilities.js.map +1 -1
  14. package/dist/catalog.d.ts +32 -0
  15. package/dist/catalog.d.ts.map +1 -1
  16. package/dist/catalog.js +17 -1
  17. package/dist/catalog.js.map +1 -1
  18. package/dist/check.d.ts +2 -0
  19. package/dist/check.d.ts.map +1 -1
  20. package/dist/check.js +2 -0
  21. package/dist/check.js.map +1 -1
  22. package/dist/cli/check/aliases.d.ts +11 -0
  23. package/dist/cli/check/aliases.d.ts.map +1 -0
  24. package/dist/cli/check/aliases.js +17 -0
  25. package/dist/cli/check/aliases.js.map +1 -0
  26. package/dist/cli/check/context.d.ts +2 -0
  27. package/dist/cli/check/context.d.ts.map +1 -1
  28. package/dist/cli/check/context.js.map +1 -1
  29. package/dist/cli/check/index.d.ts +2 -0
  30. package/dist/cli/check/index.d.ts.map +1 -1
  31. package/dist/cli/check/index.js +2 -0
  32. package/dist/cli/check/index.js.map +1 -1
  33. package/dist/cli/check/jobs.d.ts +12 -0
  34. package/dist/cli/check/jobs.d.ts.map +1 -0
  35. package/dist/cli/check/jobs.js +25 -0
  36. package/dist/cli/check/jobs.js.map +1 -0
  37. package/dist/cli/check.d.ts +13 -0
  38. package/dist/cli/check.d.ts.map +1 -1
  39. package/dist/cli/check.js +25 -2
  40. package/dist/cli/check.js.map +1 -1
  41. package/dist/cli/describe.d.ts.map +1 -1
  42. package/dist/cli/describe.js +41 -0
  43. package/dist/cli/describe.js.map +1 -1
  44. package/dist/cli/document-schema.d.ts.map +1 -1
  45. package/dist/cli/document-schema.js +7 -0
  46. package/dist/cli/document-schema.js.map +1 -1
  47. package/dist/compose.d.ts +99 -0
  48. package/dist/compose.d.ts.map +1 -0
  49. package/dist/compose.js +245 -0
  50. package/dist/compose.js.map +1 -0
  51. package/dist/conformance/fixtures.d.ts.map +1 -1
  52. package/dist/conformance/fixtures.js +15 -5
  53. package/dist/conformance/fixtures.js.map +1 -1
  54. package/dist/days.d.ts +14 -1
  55. package/dist/days.d.ts.map +1 -1
  56. package/dist/days.js +17 -2
  57. package/dist/days.js.map +1 -1
  58. package/dist/document/brand-check.d.ts.map +1 -1
  59. package/dist/document/brand-check.js +6 -2
  60. package/dist/document/brand-check.js.map +1 -1
  61. package/dist/document/compile-checked.d.ts.map +1 -1
  62. package/dist/document/compile-checked.js +11 -5
  63. package/dist/document/compile-checked.js.map +1 -1
  64. package/dist/document/compiled.d.ts.map +1 -1
  65. package/dist/document/compiled.js +20 -4
  66. package/dist/document/compiled.js.map +1 -1
  67. package/dist/document/design-findings.d.ts +32 -0
  68. package/dist/document/design-findings.d.ts.map +1 -0
  69. package/dist/document/design-findings.js +593 -0
  70. package/dist/document/design-findings.js.map +1 -0
  71. package/dist/document/edit.d.ts +1 -1
  72. package/dist/document/edit.d.ts.map +1 -1
  73. package/dist/document/edit.js +303 -16
  74. package/dist/document/edit.js.map +1 -1
  75. package/dist/document/field-spec.d.ts.map +1 -1
  76. package/dist/document/field-spec.js +3 -2
  77. package/dist/document/field-spec.js.map +1 -1
  78. package/dist/document/findings.d.ts +8 -2
  79. package/dist/document/findings.d.ts.map +1 -1
  80. package/dist/document/findings.js +4 -3
  81. package/dist/document/findings.js.map +1 -1
  82. package/dist/document/graview-template.d.ts +3 -3
  83. package/dist/document/purpose-spec.d.ts +37 -0
  84. package/dist/document/purpose-spec.d.ts.map +1 -0
  85. package/dist/document/purpose-spec.js +41 -0
  86. package/dist/document/purpose-spec.js.map +1 -0
  87. package/dist/document/schema.d.ts +29 -11
  88. package/dist/document/schema.d.ts.map +1 -1
  89. package/dist/document/schema.js +26 -0
  90. package/dist/document/schema.js.map +1 -1
  91. package/dist/document/template.js +2 -2
  92. package/dist/document/template.js.map +1 -1
  93. package/dist/document/to-document.d.ts.map +1 -1
  94. package/dist/document/to-document.js +5 -1
  95. package/dist/document/to-document.js.map +1 -1
  96. package/dist/document.schema.json +146 -2
  97. package/dist/friction-record.d.ts +52 -0
  98. package/dist/friction-record.d.ts.map +1 -0
  99. package/dist/friction-record.js +36 -0
  100. package/dist/friction-record.js.map +1 -0
  101. package/dist/friction.d.ts +209 -0
  102. package/dist/friction.d.ts.map +1 -0
  103. package/dist/friction.js +302 -0
  104. package/dist/friction.js.map +1 -0
  105. package/dist/import/coerce.d.ts.map +1 -1
  106. package/dist/import/coerce.js +3 -1
  107. package/dist/import/coerce.js.map +1 -1
  108. package/dist/import/rows.d.ts +8 -0
  109. package/dist/import/rows.d.ts.map +1 -1
  110. package/dist/import/rows.js +19 -3
  111. package/dist/import/rows.js.map +1 -1
  112. package/dist/index.d.ts +5 -1
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +5 -1
  115. package/dist/index.js.map +1 -1
  116. package/dist/job-findings.d.ts +39 -0
  117. package/dist/job-findings.d.ts.map +1 -0
  118. package/dist/job-findings.js +171 -0
  119. package/dist/job-findings.js.map +1 -0
  120. package/dist/job-shape.d.ts +57 -0
  121. package/dist/job-shape.d.ts.map +1 -0
  122. package/dist/job-shape.js +5 -0
  123. package/dist/job-shape.js.map +1 -0
  124. package/dist/jobs.d.ts +62 -0
  125. package/dist/jobs.d.ts.map +1 -0
  126. package/dist/jobs.js +112 -0
  127. package/dist/jobs.js.map +1 -0
  128. package/dist/learn.d.ts +151 -0
  129. package/dist/learn.d.ts.map +1 -0
  130. package/dist/learn.js +520 -0
  131. package/dist/learn.js.map +1 -0
  132. package/dist/mutations/arg-shape.d.ts +2 -0
  133. package/dist/mutations/arg-shape.d.ts.map +1 -1
  134. package/dist/mutations/arg-shape.js +2 -2
  135. package/dist/mutations/arg-shape.js.map +1 -1
  136. package/dist/mutations/define-mutation.d.ts.map +1 -1
  137. package/dist/mutations/define-mutation.js +25 -2
  138. package/dist/mutations/define-mutation.js.map +1 -1
  139. package/dist/mutations/derive-edits.d.ts.map +1 -1
  140. package/dist/mutations/derive-edits.js +17 -3
  141. package/dist/mutations/derive-edits.js.map +1 -1
  142. package/dist/mutations/derive-relations.d.ts +8 -3
  143. package/dist/mutations/derive-relations.d.ts.map +1 -1
  144. package/dist/mutations/derive-relations.js +18 -7
  145. package/dist/mutations/derive-relations.js.map +1 -1
  146. package/dist/mutations/form.d.ts +2 -0
  147. package/dist/mutations/form.d.ts.map +1 -1
  148. package/dist/mutations/form.js +1 -1
  149. package/dist/mutations/form.js.map +1 -1
  150. package/dist/mutations/types.d.ts +7 -0
  151. package/dist/mutations/types.d.ts.map +1 -1
  152. package/dist/ops/tidying.d.ts.map +1 -1
  153. package/dist/ops/tidying.js +3 -0
  154. package/dist/ops/tidying.js.map +1 -1
  155. package/dist/schema/choice-words.d.ts +16 -0
  156. package/dist/schema/choice-words.d.ts.map +1 -0
  157. package/dist/schema/choice-words.js +31 -0
  158. package/dist/schema/choice-words.js.map +1 -0
  159. package/dist/schema/define-node.d.ts +2 -1
  160. package/dist/schema/define-node.d.ts.map +1 -1
  161. package/dist/schema/define-node.js +3 -15
  162. package/dist/schema/define-node.js.map +1 -1
  163. package/dist/schema/humanize.d.ts +3 -0
  164. package/dist/schema/humanize.d.ts.map +1 -0
  165. package/dist/schema/humanize.js +18 -0
  166. package/dist/schema/humanize.js.map +1 -0
  167. package/dist/schema/json-schema.d.ts.map +1 -1
  168. package/dist/schema/json-schema.js +2 -1
  169. package/dist/schema/json-schema.js.map +1 -1
  170. package/dist/schema/reading.d.ts.map +1 -1
  171. package/dist/schema/reading.js +10 -2
  172. package/dist/schema/reading.js.map +1 -1
  173. package/dist/schema/types.d.ts +9 -0
  174. package/dist/schema/types.d.ts.map +1 -1
  175. package/dist/search.d.ts.map +1 -1
  176. package/dist/search.js +2 -0
  177. package/dist/search.js.map +1 -1
  178. package/dist/sync/connection.js +1 -1
  179. package/dist/theme/accent.d.ts.map +1 -1
  180. package/dist/theme/accent.js +2 -2
  181. package/dist/theme/accent.js.map +1 -1
  182. package/dist/theme/derive.d.ts +10 -1
  183. package/dist/theme/derive.d.ts.map +1 -1
  184. package/dist/theme/derive.js +1 -1
  185. package/dist/theme/derive.js.map +1 -1
  186. package/dist/theme/ground-check.d.ts +12 -0
  187. package/dist/theme/ground-check.d.ts.map +1 -1
  188. package/dist/theme/ground-check.js +37 -11
  189. package/dist/theme/ground-check.js.map +1 -1
  190. package/dist/theme/ground.d.ts +28 -7
  191. package/dist/theme/ground.d.ts.map +1 -1
  192. package/dist/theme/ground.js +62 -18
  193. package/dist/theme/ground.js.map +1 -1
  194. package/dist/tidying.d.ts +10 -0
  195. package/dist/tidying.d.ts.map +1 -1
  196. package/dist/tidying.js +17 -0
  197. package/dist/tidying.js.map +1 -1
  198. package/dist/version.d.ts +1 -1
  199. package/dist/version.js +1 -1
  200. package/dist/when-typed.d.ts +7 -0
  201. package/dist/when-typed.d.ts.map +1 -1
  202. package/dist/when-typed.js +24 -0
  203. package/dist/when-typed.js.map +1 -1
  204. package/dist/words.d.ts +1 -1
  205. package/dist/words.d.ts.map +1 -1
  206. package/dist/words.js +1 -1
  207. package/dist/words.js.map +1 -1
  208. package/package.json +17 -1
@@ -0,0 +1,209 @@
1
+ /**
2
+ * `@graview/core/friction` — WHAT PEOPLE LOOKED FOR AND COULD NOT DO
3
+ * (Roadmap f-friction-log).
4
+ *
5
+ * The op log records every change, with its author and lineage; an AI
6
+ * interaction keeps its outcome (`@graview/core/catalog`); a declined
7
+ * suggestion is remembered (`@graview/core/tidying`). What none of them
8
+ * records is what happened BEFORE a change, or instead of one: the words
9
+ * somebody searched for and found nothing, the question the seat could not
10
+ * answer, the act that was refused, the tool call an agent got wrong and
11
+ * the form that worked after it. This is that record, in the graph's own
12
+ * words — kinds, acts, refusal codes, the words people typed — never
13
+ * clicks or selectors.
14
+ *
15
+ * A visitor (a person answering a form, who never joined the app) is never
16
+ * recorded. Free text is bounded and kept as data. What anybody but the
17
+ * person reads is counted across DISTINCT people (`frictionOf`), never who,
18
+ * and words fewer than `minPeople` people used are not said at all; a
19
+ * person reads their own (`ownFriction`); a model is told a short digest
20
+ * (`frictionDigest`, `aiContextOf`'s `friction`) with no refusal's sentence
21
+ * in it. `withinRetention` lets the old go.
22
+ *
23
+ * Core keeps no storage of it: `memoryFriction` here, a file beside the
24
+ * store and a browser's storage in `@graview/ship`, a host's own anywhere.
25
+ * Its own entry, because a page draws nothing with it; what a page records
26
+ * through is `recordFriction` on the main entry, a weak map and a check.
27
+ */
28
+ import { type FrictionDraft, type FrictionSink } from "./friction-record.js";
29
+ import type { Author } from "./ops/types.js";
30
+ import type { Principal } from "./permissions/types.js";
31
+ import { type RefusalReason } from "./refused.js";
32
+ import type { AnySchema } from "./schema/schema.js";
33
+ export type { FrictionDraft, FrictionSink };
34
+ export declare const FRICTION_TYPES: readonly ["search-miss", "unanswered", "refused", "tool-invalid"];
35
+ export type FrictionType = (typeof FRICTION_TYPES)[number];
36
+ /** Every event: an id, when, who (the seat's kind and id, and whom an agent acted for), and the kind it was about. */
37
+ export interface FrictionBase {
38
+ readonly id: string;
39
+ readonly at: string;
40
+ readonly by: Author;
41
+ readonly kind?: string;
42
+ }
43
+ export interface SearchMiss extends FrictionBase {
44
+ readonly type: "search-miss";
45
+ readonly words: string;
46
+ }
47
+ export interface Unanswered extends FrictionBase {
48
+ readonly type: "unanswered";
49
+ readonly question: string;
50
+ readonly place?: string;
51
+ }
52
+ export interface RefusedAct extends FrictionBase {
53
+ readonly type: "refused";
54
+ readonly act: string;
55
+ readonly code: RefusalReason;
56
+ }
57
+ export interface ToolInvalid extends FrictionBase {
58
+ readonly type: "tool-invalid";
59
+ readonly tool: string;
60
+ readonly act?: string;
61
+ readonly message: string;
62
+ /** The form of the next call of the same tool that worked (`callShape`): argument names and types, never values. */
63
+ readonly then?: string;
64
+ }
65
+ export type FrictionEvent = SearchMiss | Unanswered | RefusedAct | ToolInvalid;
66
+ /** The caps on what an event keeps: text is cut to these, and a name longer than `name` is no name. */
67
+ export declare const FRICTION_LIMITS: {
68
+ readonly words: 120;
69
+ readonly question: 300;
70
+ readonly message: 300;
71
+ readonly then: 300;
72
+ readonly name: 80;
73
+ };
74
+ /** How long a host keeps friction when it says nothing: ninety days. */
75
+ export declare const FRICTION_RETENTION_DAYS = 90;
76
+ /**
77
+ * A DRAFT, KEPT AS AN EVENT: its text bounded, its names checked, stamped
78
+ * with an id, a time and its author. Undefined for a visitor (or an agent
79
+ * acting for one) and for a draft that is not one of the four.
80
+ */
81
+ export declare function frictionEvent(draft: FrictionDraft, by: Author, options?: {
82
+ readonly at?: string;
83
+ readonly id?: string;
84
+ }): FrictionEvent | undefined;
85
+ /**
86
+ * WHERE A HOST KEEPS FRICTION: append and read back. `memoryFriction` here;
87
+ * `fileFriction` (a file beside the store) and `browserFriction` (a
88
+ * browser's storage) in `@graview/ship`; a host's own anywhere.
89
+ */
90
+ export interface FrictionStore {
91
+ add(event: FrictionEvent): void | Promise<void>;
92
+ list(): readonly FrictionEvent[] | Promise<readonly FrictionEvent[]>;
93
+ }
94
+ /** A store that answers at once: memory, a file, a browser's storage. */
95
+ export interface HeldFriction extends FrictionStore {
96
+ add(event: FrictionEvent): void;
97
+ list(): readonly FrictionEvent[];
98
+ }
99
+ /** What a kept log holds at most, oldest let go first. */
100
+ export declare const FRICTION_KEPT_MOST = 5000;
101
+ /** What a store keeps after an event: within the retention, at most `most`, oldest let go first. */
102
+ export declare function keptFriction(events: readonly FrictionEvent[], options?: {
103
+ readonly retentionDays?: number;
104
+ readonly most?: number;
105
+ readonly now?: number;
106
+ }): readonly FrictionEvent[];
107
+ /** Friction kept in memory for as long as the process runs. */
108
+ export declare function memoryFriction(options?: {
109
+ readonly retentionDays?: number;
110
+ readonly most?: number;
111
+ }): HeldFriction;
112
+ /** A sink that keeps each draft in a `FrictionStore`, as `by` — or, unsaid, as `otherwise`. A visitor's never is. */
113
+ export declare function frictionSinkTo(store: FrictionStore, otherwise?: Author): FrictionSink;
114
+ /** The events within the last `days` days of `now`. */
115
+ export declare function withinRetention(events: readonly FrictionEvent[], days?: number, now?: number): readonly FrictionEvent[];
116
+ /** A person's own events — and an agent's acting for them. A seat with no id has none. */
117
+ export declare function ownFriction(events: readonly FrictionEvent[], principal: Principal): readonly FrictionEvent[];
118
+ /** One thing counted: by how many distinct people, and how many times. */
119
+ export interface FrictionCount {
120
+ readonly people: number;
121
+ readonly times: number;
122
+ }
123
+ /**
124
+ * WHAT PEOPLE COULD NOT DO, COUNTED — and never who. Each group is counted
125
+ * across distinct people (an agent acting for somebody counts as them),
126
+ * most people first; a group fewer than `minPeople` people share is left
127
+ * out, so a word one person typed is never said to anybody else. Tool
128
+ * mistakes say the tool, the act and the form that worked, never the
129
+ * refusal's sentence.
130
+ */
131
+ export interface FrictionSummary {
132
+ readonly events: number;
133
+ readonly people: number;
134
+ readonly byType: Readonly<Record<FrictionType, {
135
+ readonly events: number;
136
+ readonly people: number;
137
+ }>>;
138
+ readonly searches: readonly (FrictionCount & {
139
+ readonly words: string;
140
+ })[];
141
+ readonly questions: readonly (FrictionCount & {
142
+ readonly question: string;
143
+ })[];
144
+ readonly words: readonly (FrictionCount & {
145
+ readonly word: string;
146
+ })[];
147
+ readonly refusals: readonly (FrictionCount & {
148
+ readonly act: string;
149
+ readonly code: RefusalReason;
150
+ })[];
151
+ readonly tools: readonly (FrictionCount & {
152
+ readonly tool: string;
153
+ readonly act?: string;
154
+ readonly then?: string;
155
+ })[];
156
+ }
157
+ export interface FrictionOptions {
158
+ /** The fewest distinct people a group is said for. 2 unsaid. */
159
+ readonly minPeople?: number;
160
+ /** The most groups of each list. 12 unsaid. */
161
+ readonly most?: number;
162
+ }
163
+ export declare function frictionOf(events: readonly FrictionEvent[], options?: FrictionOptions): FrictionSummary;
164
+ /**
165
+ * WHAT A MODEL IS TOLD OF IT: the words people searched for that no kind,
166
+ * noun, plural or field of the app is called, the questions left
167
+ * unanswered, grouped, and the tool calls refused as invalid with the form
168
+ * that worked after them — and `said`, the same in a few lines.
169
+ */
170
+ export interface FrictionDigest {
171
+ readonly said: string;
172
+ readonly unknownWords: readonly {
173
+ readonly words: string;
174
+ readonly people: number;
175
+ }[];
176
+ readonly questions: readonly {
177
+ readonly question: string;
178
+ readonly people: number;
179
+ }[];
180
+ readonly toolMistakes: readonly {
181
+ readonly tool: string;
182
+ readonly act?: string;
183
+ readonly then?: string;
184
+ readonly times: number;
185
+ }[];
186
+ }
187
+ export declare function frictionDigest(events: readonly FrictionEvent[], schema: AnySchema, options?: FrictionOptions): FrictionDigest;
188
+ /** A call's form: each argument's name and type, an object's one level in — never a value. "{ label: string, due: string }". */
189
+ export declare function callShape(args: Readonly<Record<string, unknown>>, depth?: number): string;
190
+ /** What became of one tool call, as `toolMistakes` hears it. */
191
+ export type ToolOutcome = {
192
+ readonly ok: true;
193
+ } | {
194
+ readonly ok: false;
195
+ readonly reason?: string;
196
+ readonly message: string;
197
+ };
198
+ /**
199
+ * AN AGENT'S TOOL CALLS, WATCHED FOR MISTAKES IN THEIR FORM: a call refused
200
+ * as `invalid` is held until the next call of the same tool — recorded with
201
+ * that call's form as `then` when it worked, as it was when it too was
202
+ * refused — and `flush` records what is still held. A refusal for any
203
+ * other reason is not a mistake in the call's form, and is not recorded.
204
+ */
205
+ export declare function toolMistakes(record: (draft: FrictionDraft) => void): {
206
+ heard(tool: string, act: string | undefined, args: Readonly<Record<string, unknown>>, outcome: ToolOutcome): void;
207
+ flush(): void;
208
+ };
209
+ //# sourceMappingURL=friction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"friction.d.ts","sourceRoot":"","sources":["../src/friction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * `@graview/core/friction` — WHAT PEOPLE LOOKED FOR AND COULD NOT DO
3
+ * (Roadmap f-friction-log).
4
+ *
5
+ * The op log records every change, with its author and lineage; an AI
6
+ * interaction keeps its outcome (`@graview/core/catalog`); a declined
7
+ * suggestion is remembered (`@graview/core/tidying`). What none of them
8
+ * records is what happened BEFORE a change, or instead of one: the words
9
+ * somebody searched for and found nothing, the question the seat could not
10
+ * answer, the act that was refused, the tool call an agent got wrong and
11
+ * the form that worked after it. This is that record, in the graph's own
12
+ * words — kinds, acts, refusal codes, the words people typed — never
13
+ * clicks or selectors.
14
+ *
15
+ * A visitor (a person answering a form, who never joined the app) is never
16
+ * recorded. Free text is bounded and kept as data. What anybody but the
17
+ * person reads is counted across DISTINCT people (`frictionOf`), never who,
18
+ * and words fewer than `minPeople` people used are not said at all; a
19
+ * person reads their own (`ownFriction`); a model is told a short digest
20
+ * (`frictionDigest`, `aiContextOf`'s `friction`) with no refusal's sentence
21
+ * in it. `withinRetention` lets the old go.
22
+ *
23
+ * Core keeps no storage of it: `memoryFriction` here, a file beside the
24
+ * store and a browser's storage in `@graview/ship`, a host's own anywhere.
25
+ * Its own entry, because a page draws nothing with it; what a page records
26
+ * through is `recordFriction` on the main entry, a weak map and a check.
27
+ */
28
+ import { isVisitorAuthor } from "./friction-record.js";
29
+ import { REFUSAL_REASONS } from "./refused.js";
30
+ import { humanizeField, nounOf, pluralOf } from "./schema/define-node.js";
31
+ // ── the events ──────────────────────────────────────────────────────────────
32
+ export const FRICTION_TYPES = ["search-miss", "unanswered", "refused", "tool-invalid"];
33
+ /** The caps on what an event keeps: text is cut to these, and a name longer than `name` is no name. */
34
+ export const FRICTION_LIMITS = { words: 120, question: 300, message: 300, then: 300, name: 80 };
35
+ /** How long a host keeps friction when it says nothing: ninety days. */
36
+ export const FRICTION_RETENTION_DAYS = 90;
37
+ /** Control characters, zero-width marks and direction overrides: nothing a person reads, something a reader could be fooled by. */
38
+ // eslint-disable-next-line no-control-regex
39
+ const UNSEEN = new RegExp("[\\u0000-\\u001f\\u007f-\\u009f\\u200b-\\u200f\\u2028-\\u202e\\u2066-\\u2069]", "g");
40
+ /** Text as data: control characters gone, whitespace folded, cut to `max`. Empty is nothing. */
41
+ function textOf(value, max) {
42
+ if (typeof value !== "string")
43
+ return undefined;
44
+ const clean = value.replace(UNSEEN, " ").replace(/\s+/g, " ").trim();
45
+ return clean.length === 0 ? undefined : clean.slice(0, max).trimEnd();
46
+ }
47
+ /** A declared name (a kind, an act, a tool, a place): letters, digits, `-`, `_`, `.`, `:` and `/`, or nothing. */
48
+ function nameOf(value) {
49
+ return typeof value === "string" && value.length > 0 && value.length <= FRICTION_LIMITS.name && /^[\p{L}\p{N}_][\p{L}\p{N}_.:/-]*$/u.test(value) ? value : undefined;
50
+ }
51
+ /** Who, as an event keeps them: the kind and id, and whom an agent acted for — no session, no name. */
52
+ function whoOf(author) {
53
+ const id = typeof author.id === "string" ? author.id.slice(0, FRICTION_LIMITS.name) : undefined;
54
+ return {
55
+ kind: author.kind,
56
+ ...(id !== undefined ? { id } : {}),
57
+ ...(author.onBehalfOf ? { onBehalfOf: whoOf(author.onBehalfOf) } : {}),
58
+ };
59
+ }
60
+ const freshId = () => `fr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
61
+ /**
62
+ * A DRAFT, KEPT AS AN EVENT: its text bounded, its names checked, stamped
63
+ * with an id, a time and its author. Undefined for a visitor (or an agent
64
+ * acting for one) and for a draft that is not one of the four.
65
+ */
66
+ export function frictionEvent(draft, by, options = {}) {
67
+ if (!draft || typeof draft !== "object" || !by || isVisitorAuthor(by))
68
+ return undefined;
69
+ const asked = draft;
70
+ const kind = asked["kind"] === undefined ? undefined : nameOf(asked["kind"]);
71
+ if (asked["kind"] !== undefined && kind === undefined)
72
+ return undefined;
73
+ const base = { id: options.id ?? freshId(), at: options.at ?? new Date().toISOString(), by: whoOf(by), ...(kind ? { kind } : {}) };
74
+ switch (asked["type"]) {
75
+ case "search-miss": {
76
+ const words = textOf(asked["words"], FRICTION_LIMITS.words);
77
+ return words ? { ...base, type: "search-miss", words } : undefined;
78
+ }
79
+ case "unanswered": {
80
+ const question = textOf(asked["question"], FRICTION_LIMITS.question);
81
+ const place = asked["place"] === undefined ? undefined : nameOf(asked["place"]);
82
+ return question ? { ...base, type: "unanswered", question, ...(place ? { place } : {}) } : undefined;
83
+ }
84
+ case "refused": {
85
+ const act = nameOf(asked["act"]);
86
+ const code = asked["code"];
87
+ return act && REFUSAL_REASONS.includes(code) ? { ...base, type: "refused", act, code: code } : undefined;
88
+ }
89
+ case "tool-invalid": {
90
+ const tool = nameOf(asked["tool"]);
91
+ const message = textOf(asked["message"], FRICTION_LIMITS.message);
92
+ const act = asked["act"] === undefined ? undefined : nameOf(asked["act"]);
93
+ const then = textOf(asked["then"], FRICTION_LIMITS.then);
94
+ return tool && message ? { ...base, type: "tool-invalid", tool, message, ...(act ? { act } : {}), ...(then ? { then } : {}) } : undefined;
95
+ }
96
+ default:
97
+ return undefined;
98
+ }
99
+ }
100
+ /** What a kept log holds at most, oldest let go first. */
101
+ export const FRICTION_KEPT_MOST = 5000;
102
+ /** What a store keeps after an event: within the retention, at most `most`, oldest let go first. */
103
+ export function keptFriction(events, options = {}) {
104
+ const kept = withinRetention(events, options.retentionDays ?? FRICTION_RETENTION_DAYS, options.now);
105
+ const most = options.most ?? FRICTION_KEPT_MOST;
106
+ return kept.length > most ? kept.slice(kept.length - most) : kept;
107
+ }
108
+ /** Friction kept in memory for as long as the process runs. */
109
+ export function memoryFriction(options = {}) {
110
+ let held = [];
111
+ return {
112
+ add(event) {
113
+ if (isVisitorAuthor(event.by))
114
+ return;
115
+ held = keptFriction([...held, event], options);
116
+ },
117
+ list: () => keptFriction(held, options),
118
+ };
119
+ }
120
+ /** A sink that keeps each draft in a `FrictionStore`, as `by` — or, unsaid, as `otherwise`. A visitor's never is. */
121
+ export function frictionSinkTo(store, otherwise) {
122
+ return (draft, by) => {
123
+ const author = by ?? otherwise;
124
+ const event = author ? frictionEvent(draft, author) : undefined;
125
+ if (event)
126
+ void store.add(event);
127
+ };
128
+ }
129
+ /** The events within the last `days` days of `now`. */
130
+ export function withinRetention(events, days = FRICTION_RETENTION_DAYS, now = Date.now()) {
131
+ const since = now - days * 86_400_000;
132
+ return events.filter((event) => {
133
+ const time = Date.parse(event.at);
134
+ return Number.isFinite(time) && time >= since;
135
+ });
136
+ }
137
+ // ── reading it ──────────────────────────────────────────────────────────────
138
+ /** The person an event is of: whom an agent acted for, else the author; a seat with no id is one anonymous person per kind. */
139
+ const personOf = (author) => (author.onBehalfOf ? personOf(author.onBehalfOf) : author.id !== undefined ? `${author.kind}:${author.id}` : `${author.kind}:?`);
140
+ /** Words as they are counted: lower case, whitespace folded, the punctuation at the ends gone. */
141
+ const foldWords = (words) => words
142
+ .toLowerCase()
143
+ .replace(/\s+/g, " ")
144
+ .replace(/^[\s\p{P}]+|[\s\p{P}]+$/gu, "");
145
+ /** A person's own events — and an agent's acting for them. A seat with no id has none. */
146
+ export function ownFriction(events, principal) {
147
+ if (principal.id === undefined && principal.onBehalfOf?.id === undefined)
148
+ return [];
149
+ const me = personOf(principal);
150
+ return events.filter((event) => personOf(event.by) === me);
151
+ }
152
+ /** Words too common to say anything on their own. */
153
+ const STOP = new Set("a an and are at be by can do does for from has have how i in is it me my of on or our the their there this to was we what when where which who why will with you your".split(" "));
154
+ function grouped(events, keyOf, make, minPeople, most) {
155
+ const groups = new Map();
156
+ for (const event of events) {
157
+ const key = keyOf(event);
158
+ if (key === undefined)
159
+ continue;
160
+ const group = groups.get(key) ?? { first: event, people: new Set(), times: 0, last: event };
161
+ group.people.add(personOf(event.by));
162
+ group.times += 1;
163
+ group.last = event;
164
+ groups.set(key, group);
165
+ }
166
+ return [...groups.entries()]
167
+ .filter(([, group]) => group.people.size >= minPeople)
168
+ .sort(([a, one], [b, other]) => other.people.size - one.people.size || other.times - one.times || a.localeCompare(b))
169
+ .slice(0, most)
170
+ .map(([key, group]) => ({ ...make(group.last, key), people: group.people.size, times: group.times }));
171
+ }
172
+ export function frictionOf(events, options = {}) {
173
+ const minPeople = Math.max(1, options.minPeople ?? 2);
174
+ const most = options.most ?? 12;
175
+ const kept = events.filter((event) => !isVisitorAuthor(event.by));
176
+ const byType = Object.fromEntries(FRICTION_TYPES.map((type) => {
177
+ const of = kept.filter((event) => event.type === type);
178
+ return [type, { events: of.length, people: new Set(of.map((event) => personOf(event.by))).size }];
179
+ }));
180
+ // The words one at a time, from what was searched and asked, each said once per event.
181
+ const tokens = [];
182
+ const tokenOf = new Map();
183
+ for (const event of kept) {
184
+ const text = event.type === "search-miss" ? event.words : event.type === "unanswered" ? event.question : undefined;
185
+ if (text === undefined)
186
+ continue;
187
+ for (const word of new Set(foldWords(text).split(/[^\p{L}\p{N}]+/u))) {
188
+ if (word.length < 3 || STOP.has(word))
189
+ continue;
190
+ const one = { ...event, id: `${event.id}:${word}` };
191
+ tokens.push(one);
192
+ tokenOf.set(one, word);
193
+ }
194
+ }
195
+ return {
196
+ events: kept.length,
197
+ people: new Set(kept.map((event) => personOf(event.by))).size,
198
+ byType,
199
+ searches: grouped(kept, (event) => (event.type === "search-miss" ? foldWords(event.words) || undefined : undefined), (_event, words) => ({ words }), minPeople, most),
200
+ questions: grouped(kept, (event) => (event.type === "unanswered" ? foldWords(event.question) || undefined : undefined), (_event, question) => ({ question }), minPeople, most),
201
+ words: grouped(tokens, (event) => tokenOf.get(event), (_event, word) => ({ word }), minPeople, most),
202
+ refusals: grouped(kept, (event) => (event.type === "refused" ? `${event.act}|${event.code}` : undefined), (event) => ({ act: event.act, code: event.code }), minPeople, most),
203
+ tools: grouped(kept, (event) => (event.type === "tool-invalid" ? `${event.tool}|${event.act ?? ""}` : undefined), (event) => {
204
+ const tool = event;
205
+ return { tool: tool.tool, ...(tool.act ? { act: tool.act } : {}), ...(tool.then ? { then: tool.then } : {}) };
206
+ }, 1, most),
207
+ };
208
+ }
209
+ /** A word as it is compared with the app's names: lower case, a plural's `s` gone. */
210
+ const stem = (word) => (word.length > 3 && word.endsWith("s") && !word.endsWith("ss") ? word.slice(0, -1) : word);
211
+ /** Every word the app's kinds and fields are called by, their aliases among them. */
212
+ function namesOf(schema) {
213
+ const names = new Set();
214
+ const add = (text) => {
215
+ for (const word of text.toLowerCase().split(/[^\p{L}\p{N}]+/u))
216
+ if (word.length > 0)
217
+ names.add(stem(word));
218
+ };
219
+ for (const kind of schema.kinds) {
220
+ const definition = schema.tryDefinition(kind);
221
+ add(kind);
222
+ add(nounOf(definition, kind));
223
+ add(pluralOf(schema, kind));
224
+ // And the other words the app answers to (Roadmap f-learned-suggestions): a word it took as an alias is no longer unknown.
225
+ for (const alias of [...(definition?.aliases ?? []), ...Object.values(definition?.fieldAliases ?? {}).flat()])
226
+ add(alias);
227
+ for (const field of Object.keys(definition?.fields?.shape ?? {})) {
228
+ add(field);
229
+ add(humanizeField(field));
230
+ }
231
+ }
232
+ return names;
233
+ }
234
+ export function frictionDigest(events, schema, options = {}) {
235
+ const summary = frictionOf(events, { most: 8, ...options });
236
+ const names = namesOf(schema);
237
+ const unknownWords = summary.searches
238
+ .filter((search) => !search.words.split(/[^\p{L}\p{N}]+/u).some((word) => word.length > 0 && names.has(stem(word))))
239
+ .map((search) => ({ words: search.words, people: search.people }));
240
+ const questions = summary.questions.map((question) => ({ question: question.question, people: question.people }));
241
+ const toolMistakes = summary.tools.map((tool) => ({ tool: tool.tool, ...(tool.act ? { act: tool.act } : {}), ...(tool.then ? { then: tool.then } : {}), times: tool.times }));
242
+ const people = (count) => `${count} ${count === 1 ? "person" : "people"}`;
243
+ const lines = [
244
+ ...(unknownWords.length > 0 ? [`Searched for, found nothing, and nothing here is called it: ${unknownWords.map((one) => `“${one.words}” (${people(one.people)})`).join(", ")}.`] : []),
245
+ ...(questions.length > 0 ? [`Asked and not answered: ${questions.map((one) => `“${one.question}” (${people(one.people)})`).join(", ")}.`] : []),
246
+ ...(toolMistakes.length > 0
247
+ ? [`Tool calls refused as invalid: ${toolMistakes.map((one) => `${one.tool}${one.act ? ` (${one.act})` : ""} ${one.times === 1 ? "once" : `${one.times} times`}${one.then ? `, then worked as ${one.then}` : ""}`).join("; ")}.`]
248
+ : []),
249
+ ];
250
+ return { said: lines.join("\n"), unknownWords, questions, toolMistakes };
251
+ }
252
+ // ── an agent's tool calls ───────────────────────────────────────────────────
253
+ /** A call's form: each argument's name and type, an object's one level in — never a value. "{ label: string, due: string }". */
254
+ export function callShape(args, depth = 0) {
255
+ const typeOf = (value) => value === null ? "null" : Array.isArray(value) ? "array" : typeof value === "object" ? (depth < 1 ? callShape(value, depth + 1) : "object") : typeof value;
256
+ const parts = Object.keys(args)
257
+ .filter((name) => args[name] !== undefined)
258
+ .slice(0, 16)
259
+ .map((name) => `${name.slice(0, 40)}: ${typeOf(args[name])}`);
260
+ return (parts.length === 0 ? "{}" : `{ ${parts.join(", ")} }`).slice(0, FRICTION_LIMITS.then);
261
+ }
262
+ /**
263
+ * AN AGENT'S TOOL CALLS, WATCHED FOR MISTAKES IN THEIR FORM: a call refused
264
+ * as `invalid` is held until the next call of the same tool — recorded with
265
+ * that call's form as `then` when it worked, as it was when it too was
266
+ * refused — and `flush` records what is still held. A refusal for any
267
+ * other reason is not a mistake in the call's form, and is not recorded.
268
+ */
269
+ export function toolMistakes(record) {
270
+ const held = new Map();
271
+ const keep = (draft) => {
272
+ try {
273
+ record(draft);
274
+ }
275
+ catch {
276
+ // Recording is never why a call fails.
277
+ }
278
+ };
279
+ return {
280
+ heard(tool, act, args, outcome) {
281
+ const before = held.get(tool);
282
+ if (outcome.ok) {
283
+ if (before) {
284
+ held.delete(tool);
285
+ keep({ ...before, then: callShape(args) });
286
+ }
287
+ return;
288
+ }
289
+ if (outcome.reason !== "invalid")
290
+ return;
291
+ if (before)
292
+ keep(before);
293
+ held.set(tool, { type: "tool-invalid", tool, ...(act ? { act } : {}), message: outcome.message });
294
+ },
295
+ flush() {
296
+ for (const draft of held.values())
297
+ keep(draft);
298
+ held.clear();
299
+ },
300
+ };
301
+ }
302
+ //# sourceMappingURL=friction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"friction.js","sourceRoot":"","sources":["../src/friction.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../../src/import/coerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpH,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AAoBD,kIAAkI;AAClI,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,GAAG,SAAS,CAgCvF;AASD,gHAAgH;AAChH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,GAAG,SAAS,CA6B5F;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAoB7D;AAKD,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAM/D;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAU7H;AAED,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGhD;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAyE9G;AAED,mBAAmB;AACnB,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvD;AAED,oBAAoB;AACpB,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGxD"}
1
+ {"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../../src/import/coerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQvD;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpH,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AAoBD,kIAAkI;AAClI,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,GAAG,SAAS,CAgCvF;AASD,gHAAgH;AAChH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,GAAG,SAAS,CA6B5F;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAoB7D;AAKD,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAM/D;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAU7H;AAED,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGhD;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CA0E9G;AAED,mBAAmB;AACnB,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvD;AAED,oBAAoB;AACpB,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGxD"}
@@ -3,6 +3,7 @@ import { slug } from "../mutations/define-mutation.js";
3
3
  import { isAppAddress } from "../schema/app-link.js";
4
4
  import { PHONE } from "../schema/typed-fields.js";
5
5
  import { parseDuration } from "../schema/field-words.js";
6
+ import { readPartialDay } from "../when-typed.js";
6
7
  const MONTHS = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
7
8
  const pad = (n) => String(n).padStart(2, "0");
8
9
  /** Whether a day is on the calendar: February has no 30th. */
@@ -187,7 +188,8 @@ export function coerceCell(spec, input, said, options = {}) {
187
188
  return value === undefined ? { ok: false, why: `${quoted} under ${said} is not a yes or a no` } : { ok: true, value };
188
189
  }
189
190
  case "date": {
190
- const value = readDay(input, options);
191
+ // A day; else a year or a month alone, which the field keeps or refuses (Roadmap f-partial-dates).
192
+ const value = readDay(input, options) ?? readPartialDay(input);
191
193
  return value === undefined ? { ok: false, why: `${quoted} under ${said} is not a date` } : { ok: true, value };
192
194
  }
193
195
  case "datetime": {