@graview/tools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +47 -0
  3. package/dist/agent/adapters.d.ts +43 -0
  4. package/dist/agent/adapters.d.ts.map +1 -0
  5. package/dist/agent/adapters.js +52 -0
  6. package/dist/agent/adapters.js.map +1 -0
  7. package/dist/agent/tools.d.ts +105 -0
  8. package/dist/agent/tools.d.ts.map +1 -0
  9. package/dist/agent/tools.js +311 -0
  10. package/dist/agent/tools.js.map +1 -0
  11. package/dist/cli.d.ts +37 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +306 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/conversation.d.ts +108 -0
  16. package/dist/conversation.d.ts.map +1 -0
  17. package/dist/conversation.js +698 -0
  18. package/dist/conversation.js.map +1 -0
  19. package/dist/decide.d.ts +43 -0
  20. package/dist/decide.d.ts.map +1 -0
  21. package/dist/decide.js +125 -0
  22. package/dist/decide.js.map +1 -0
  23. package/dist/derive.d.ts +84 -0
  24. package/dist/derive.d.ts.map +1 -0
  25. package/dist/derive.js +302 -0
  26. package/dist/derive.js.map +1 -0
  27. package/dist/edit.d.ts +70 -0
  28. package/dist/edit.d.ts.map +1 -0
  29. package/dist/edit.js +97 -0
  30. package/dist/edit.js.map +1 -0
  31. package/dist/figure.d.ts +53 -0
  32. package/dist/figure.d.ts.map +1 -0
  33. package/dist/figure.js +86 -0
  34. package/dist/figure.js.map +1 -0
  35. package/dist/index.d.ts +44 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +31 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/intelligence.d.ts +132 -0
  40. package/dist/intelligence.d.ts.map +1 -0
  41. package/dist/intelligence.js +463 -0
  42. package/dist/intelligence.js.map +1 -0
  43. package/dist/local.d.ts +192 -0
  44. package/dist/local.d.ts.map +1 -0
  45. package/dist/local.js +365 -0
  46. package/dist/local.js.map +1 -0
  47. package/dist/loop.d.ts +84 -0
  48. package/dist/loop.d.ts.map +1 -0
  49. package/dist/loop.js +173 -0
  50. package/dist/loop.js.map +1 -0
  51. package/dist/mcp-stdio.d.ts +38 -0
  52. package/dist/mcp-stdio.d.ts.map +1 -0
  53. package/dist/mcp-stdio.js +83 -0
  54. package/dist/mcp-stdio.js.map +1 -0
  55. package/dist/pins.d.ts +29 -0
  56. package/dist/pins.d.ts.map +1 -0
  57. package/dist/pins.js +60 -0
  58. package/dist/pins.js.map +1 -0
  59. package/dist/plan.d.ts +150 -0
  60. package/dist/plan.d.ts.map +1 -0
  61. package/dist/plan.js +303 -0
  62. package/dist/plan.js.map +1 -0
  63. package/dist/providers/insight.d.ts +14 -0
  64. package/dist/providers/insight.d.ts.map +1 -0
  65. package/dist/providers/insight.js +81 -0
  66. package/dist/providers/insight.js.map +1 -0
  67. package/dist/providers/invariant.d.ts +14 -0
  68. package/dist/providers/invariant.d.ts.map +1 -0
  69. package/dist/providers/invariant.js +123 -0
  70. package/dist/providers/invariant.js.map +1 -0
  71. package/dist/providers/jev.d.ts +115 -0
  72. package/dist/providers/jev.d.ts.map +1 -0
  73. package/dist/providers/jev.js +148 -0
  74. package/dist/providers/jev.js.map +1 -0
  75. package/dist/providers/lens.d.ts +24 -0
  76. package/dist/providers/lens.d.ts.map +1 -0
  77. package/dist/providers/lens.js +36 -0
  78. package/dist/providers/lens.js.map +1 -0
  79. package/dist/providers/llm.d.ts +25 -0
  80. package/dist/providers/llm.d.ts.map +1 -0
  81. package/dist/providers/llm.js +44 -0
  82. package/dist/providers/llm.js.map +1 -0
  83. package/dist/providers/schema.d.ts +12 -0
  84. package/dist/providers/schema.d.ts.map +1 -0
  85. package/dist/providers/schema.js +508 -0
  86. package/dist/providers/schema.js.map +1 -0
  87. package/dist/providers/structure.d.ts +14 -0
  88. package/dist/providers/structure.d.ts.map +1 -0
  89. package/dist/providers/structure.js +211 -0
  90. package/dist/providers/structure.js.map +1 -0
  91. package/dist/questions.d.ts +162 -0
  92. package/dist/questions.d.ts.map +1 -0
  93. package/dist/questions.js +316 -0
  94. package/dist/questions.js.map +1 -0
  95. package/dist/run.d.ts +202 -0
  96. package/dist/run.d.ts.map +1 -0
  97. package/dist/run.js +453 -0
  98. package/dist/run.js.map +1 -0
  99. package/dist/space.d.ts +50 -0
  100. package/dist/space.d.ts.map +1 -0
  101. package/dist/space.js +55 -0
  102. package/dist/space.js.map +1 -0
  103. package/dist/types.d.ts +122 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +2 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/usage.d.ts +10 -0
  108. package/dist/usage.d.ts.map +1 -0
  109. package/dist/usage.js +59 -0
  110. package/dist/usage.js.map +1 -0
  111. package/package.json +61 -0
package/dist/plan.js ADDED
@@ -0,0 +1,303 @@
1
+ import { beginning, PermissionDeniedError, } from "@graview/core";
2
+ export function isPlanReference(value) {
3
+ return (typeof value === "object" &&
4
+ value !== null &&
5
+ typeof value.$plan === "string");
6
+ }
7
+ const refusal = (mutation, message) => ({ mutation, message, wouldNeed: [] });
8
+ /**
9
+ * Orders and judges a set of proposals.
10
+ *
11
+ * Ordering is by what each call NEEDS: a call referring to `{ $plan: "lawn" }`
12
+ * comes after the call named `lawn`; beyond that, by the declaration's own
13
+ * chain, so a zone is made before a feature even when nothing in the plan
14
+ * says so. A reference to a name the plan never makes, and a cycle between
15
+ * two of them, are refusals rather than a runtime surprise.
16
+ */
17
+ export function planFrom(store, proposals, options = {}) {
18
+ const named = new Map();
19
+ proposals.forEach((call, index) => {
20
+ if (call.as !== undefined && !named.has(call.as))
21
+ named.set(call.as, index);
22
+ });
23
+ /** The plan-names each call waits for. */
24
+ const waitsFor = (call) => {
25
+ const found = [];
26
+ const walk = (value) => {
27
+ if (isPlanReference(value))
28
+ found.push(value.$plan);
29
+ else if (Array.isArray(value))
30
+ for (const item of value)
31
+ walk(item);
32
+ else if (value !== null && typeof value === "object") {
33
+ for (const item of Object.values(value))
34
+ walk(item);
35
+ }
36
+ };
37
+ walk(call.args);
38
+ return found;
39
+ };
40
+ /*
41
+ * THE CHAIN THE DECLARATION STATES, as a tiebreak. Two calls that refer to
42
+ * nothing still have an order — a zone before a feature — and the app
43
+ * already said which. Without it a plan that happens to list the feature
44
+ * first fails on a picker that has nothing in it yet.
45
+ */
46
+ const depthOf = new Map();
47
+ if (options.app) {
48
+ for (const entry of beginning(options.app).order) {
49
+ depthOf.set(entry.kind, entry.depth ?? Number.MAX_SAFE_INTEGER);
50
+ }
51
+ }
52
+ const rank = (call) => {
53
+ let made = [];
54
+ try {
55
+ made = (store.mutation(call.mutation).creates ?? []);
56
+ }
57
+ catch {
58
+ return Number.MAX_SAFE_INTEGER;
59
+ }
60
+ if (made.length === 0)
61
+ return Number.MAX_SAFE_INTEGER - 1;
62
+ return Math.min(...made.map((kind) => depthOf.get(kind) ?? 0));
63
+ };
64
+ /* Kahn's, over the plan's own names, with the chain as the tiebreak. */
65
+ const remaining = proposals.map((call, index) => ({ call, index }));
66
+ const done = new Set();
67
+ const ordered = [];
68
+ const stuck = [];
69
+ while (remaining.length > 0) {
70
+ const ready = remaining.filter((entry) => waitsFor(entry.call).every((name) => done.has(name) || !named.has(name)));
71
+ if (ready.length === 0) {
72
+ /* A cycle: nothing left can go first. They are refused, not guessed at. */
73
+ stuck.push(...remaining.map((entry) => entry.call));
74
+ break;
75
+ }
76
+ ready.sort((a, b) => rank(a.call) - rank(b.call) || a.index - b.index);
77
+ const next = ready[0];
78
+ ordered.push(next.call);
79
+ if (next.call.as !== undefined)
80
+ done.add(next.call.as);
81
+ remaining.splice(remaining.indexOf(next), 1);
82
+ }
83
+ const entries = [...ordered, ...stuck].map((call, at) => {
84
+ const dependsOn = [...new Set(waitsFor(call).filter((name) => named.has(name)))];
85
+ const cycled = stuck.includes(call);
86
+ if (cycled) {
87
+ return {
88
+ call,
89
+ at,
90
+ dependsOn,
91
+ refusal: refusal(call.mutation, "This call and another wait for each other, so neither can go first."),
92
+ };
93
+ }
94
+ const dangling = waitsFor(call).filter((name) => !named.has(name));
95
+ if (dangling.length > 0) {
96
+ return {
97
+ call,
98
+ at,
99
+ dependsOn,
100
+ refusal: refusal(call.mutation, `Refers to ${dangling.map((name) => `"${name}"`).join(", ")}, which nothing in this plan makes.`),
101
+ };
102
+ }
103
+ let known = true;
104
+ try {
105
+ store.mutation(call.mutation);
106
+ }
107
+ catch {
108
+ known = false;
109
+ }
110
+ if (!known) {
111
+ return {
112
+ call,
113
+ at,
114
+ dependsOn,
115
+ refusal: refusal(call.mutation, `No act called "${call.mutation}" is registered.`),
116
+ };
117
+ }
118
+ /*
119
+ * The policy's own answer, asked now rather than at the press. A call
120
+ * whose arguments still hold plan references cannot be judged on its
121
+ * subject yet — the node does not exist — so the question asked is the
122
+ * one that can be: may this seat run this act at all.
123
+ */
124
+ if (options.principal) {
125
+ const verdict = store.permits({ name: call.mutation, args: {} }, options.principal);
126
+ if (!verdict.ok)
127
+ return { call, at, dependsOn, refusal: verdict.refusal };
128
+ }
129
+ return { call, at, dependsOn };
130
+ });
131
+ const makes = {};
132
+ for (const entry of entries) {
133
+ if (entry.refusal)
134
+ continue;
135
+ let created = [];
136
+ try {
137
+ created = (store.mutation(entry.call.mutation).creates ?? []);
138
+ }
139
+ catch {
140
+ created = [];
141
+ }
142
+ for (const kind of created)
143
+ makes[kind] = (makes[kind] ?? 0) + 1;
144
+ }
145
+ return {
146
+ entries,
147
+ ready: entries.filter((entry) => entry.refusal === undefined),
148
+ refused: entries.filter((entry) => entry.refusal !== undefined),
149
+ makes,
150
+ };
151
+ }
152
+ /**
153
+ * Applies a plan's ready entries as ONE TURN.
154
+ *
155
+ * Sequentially rather than in a single `applyAll`, because a call can refer
156
+ * to what an earlier one made and those ids do not exist until it has run —
157
+ * but under one batch, so the activity shows one entry and `store.undo(batch)`
158
+ * takes the whole seeding back the way it arrived.
159
+ *
160
+ * ALL OR NOTHING, and it says where it stopped. A plan that half-applied
161
+ * leaves a graph nobody meant and an undo nobody trusts, so what the batch
162
+ * has written is taken back before the error reaches the caller — and the
163
+ * result names the call that failed and why, because a plan that silently
164
+ * vanished would be its own kind of wrong. `keepWhatRan` is for a caller who
165
+ * would rather have the half: a long seeding whose last call was a typo.
166
+ */
167
+ export function applyPlan(store, plan, options = {}) {
168
+ const batch = options.batch ?? `plan:${Date.now().toString(36)}`;
169
+ const made = {};
170
+ let applied = 0;
171
+ const resolve = (value) => {
172
+ if (isPlanReference(value))
173
+ return made[value.$plan] ?? value.$plan;
174
+ if (Array.isArray(value))
175
+ return value.map(resolve);
176
+ if (value !== null && typeof value === "object") {
177
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolve(item)]));
178
+ }
179
+ return value;
180
+ };
181
+ for (const entry of plan.ready) {
182
+ const args = resolve(entry.call.args);
183
+ options.before?.(entry, args);
184
+ try {
185
+ /*
186
+ * THE LOG KEEPS THE NUMBER. A review shows how sure a proposer was
187
+ * beside each row and orders by it; the op that lands still records
188
+ * it in its intent, because the log is the record and "why" without
189
+ * "how sure" is half a reason.
190
+ */
191
+ const sure = entry.call.confidence;
192
+ const intent = sure !== undefined && !/\d+% sure/.test(entry.call.why ?? "")
193
+ ? `${entry.call.why ?? ""} (${Math.round(sure * 100)}% sure)`.trim()
194
+ : (entry.call.why ?? "");
195
+ // A plan with no `why` keeps the act's own sentence; an empty intent would silence it.
196
+ const result = store.apply({ name: entry.call.mutation, args }, { ...(options.author ? { author: options.author } : {}), batch, ...(intent ? { intent } : {}) });
197
+ applied += 1;
198
+ if (entry.call.as !== undefined) {
199
+ /* What it made: the one node this call added, if it added one. */
200
+ const added = result.ops
201
+ .flatMap((op) => op.primitives)
202
+ .filter((primitive) => primitive.op === "add-node")
203
+ .map((primitive) => primitive.node.id);
204
+ if (added.length === 1)
205
+ made[entry.call.as] = added[0];
206
+ }
207
+ }
208
+ catch (error) {
209
+ const why = error instanceof PermissionDeniedError
210
+ ? error.refusal.message
211
+ : error instanceof Error
212
+ ? error.message
213
+ : String(error);
214
+ let undone = false;
215
+ if (!options.keepWhatRan && applied > 0) {
216
+ store.undo(batch, options.author ? { author: options.author } : {});
217
+ undone = true;
218
+ }
219
+ return {
220
+ made,
221
+ batch,
222
+ applied,
223
+ stoppedAt: { at: entry.at, why },
224
+ ...(undone ? { undone: true } : {}),
225
+ store,
226
+ };
227
+ }
228
+ }
229
+ return { made, batch, applied, store };
230
+ }
231
+ /**
232
+ * EVERYTHING THAT GOES IF THIS GOES.
233
+ *
234
+ * Declining the area declines the tree standing in it. A review a person
235
+ * cannot disagree with is not a review — a model confident about eleven
236
+ * things and wrong about the twelfth is the normal case — and the twelfth
237
+ * is very often the one the other four point at. Saying so BEFORE the press
238
+ * is the difference between a review and a surprise.
239
+ *
240
+ * Only what POINTS AT it, transitively. A call that merely mentions the same
241
+ * subject is its own business.
242
+ */
243
+ export function dependentsOf(plan, name) {
244
+ const gone = new Set([name]);
245
+ const going = new Set();
246
+ for (let grew = true; grew;) {
247
+ grew = false;
248
+ for (const entry of plan.entries) {
249
+ if (going.has(entry))
250
+ continue;
251
+ if (!entry.dependsOn.some((wanted) => gone.has(wanted)))
252
+ continue;
253
+ going.add(entry);
254
+ /*
255
+ * A call that MAKES something carries its own dependents with it; one
256
+ * that makes nothing is a leaf. Both go, and only the first widens the
257
+ * set — which is why this is the entries rather than their names: half
258
+ * of what goes with a thing was never named.
259
+ */
260
+ if (entry.call.as !== undefined)
261
+ gone.add(entry.call.as);
262
+ grew = true;
263
+ }
264
+ }
265
+ return [...going];
266
+ }
267
+ /**
268
+ * The plan without those entries, and without anything left pointing at
269
+ * nothing — the same plan a person is left with after declining one thing.
270
+ *
271
+ * Re-planned rather than filtered, so what comes back is ordered, judged and
272
+ * counted exactly like the plan it came from.
273
+ */
274
+ export function without(store, plan, declined, options = {}) {
275
+ const out = new Set();
276
+ const names = new Set();
277
+ for (const name of declined) {
278
+ names.add(name);
279
+ for (const entry of dependentsOf(plan, name))
280
+ out.add(entry);
281
+ }
282
+ const kept = plan.entries
283
+ .filter((entry) => entry.call.as === undefined || !names.has(entry.call.as))
284
+ .filter((entry) => !out.has(entry))
285
+ .map((entry) => entry.call);
286
+ return planFrom(store, kept, options);
287
+ }
288
+ /** What a plan would do, in the words a person reviewing it needs. */
289
+ export function describePlan(plan) {
290
+ const makes = Object.entries(plan.makes)
291
+ .map(([kind, count]) => `${count} ${kind}${count === 1 ? "" : "s"}`)
292
+ .join(", ");
293
+ const lines = [
294
+ `${plan.ready.length} of ${plan.entries.length} to run${makes ? `, making ${makes}` : ""}.`,
295
+ ];
296
+ for (const entry of plan.entries) {
297
+ lines.push(`${entry.refusal ? "✗" : "→"} ${entry.call.mutation}${entry.call.as ? ` (${entry.call.as})` : ""}` +
298
+ `${entry.call.why ? ` — ${entry.call.why}` : ""}` +
299
+ `${entry.refusal ? ` REFUSED: ${entry.refusal.message}` : ""}`);
300
+ }
301
+ return lines.join("\n");
302
+ }
303
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type AnySchema } from "@graview/core";
2
+ import type { AffordanceProvider } from "../types.js";
3
+ /**
4
+ * THE GRAPH ITSELF IS THE FIRST INTELLIGENCE.
5
+ *
6
+ * Before any model or key exists, the typed graph already knows things
7
+ * worth saying: a selected node connected to nothing, one node carrying
8
+ * most of an edge kind, an empty kind that other kinds declare edges into.
9
+ * These ship as observations — statements, not suggestions — because their
10
+ * authority is structural fact, and a fact should not have to dress up as
11
+ * advice to be seen.
12
+ */
13
+ export declare function insightProvider<S extends AnySchema>(): AffordanceProvider<S>;
14
+ //# sourceMappingURL=insight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insight.d.ts","sourceRoot":"","sources":["../../src/providers/insight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,aAAa,CAAC;AAEnE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,KAAK,kBAAkB,CAAC,CAAC,CAAC,CAiF5E"}
@@ -0,0 +1,81 @@
1
+ import { labelOf } from "@graview/core";
2
+ /**
3
+ * THE GRAPH ITSELF IS THE FIRST INTELLIGENCE.
4
+ *
5
+ * Before any model or key exists, the typed graph already knows things
6
+ * worth saying: a selected node connected to nothing, one node carrying
7
+ * most of an edge kind, an empty kind that other kinds declare edges into.
8
+ * These ship as observations — statements, not suggestions — because their
9
+ * authority is structural fact, and a fact should not have to dress up as
10
+ * advice to be seen.
11
+ */
12
+ export function insightProvider() {
13
+ return {
14
+ name: "insight",
15
+ derive({ store, nodes, kindSelection }) {
16
+ const observations = [];
17
+ const name = (node) => labelOf(store.schema.tryDefinition(node.kind), node);
18
+ for (const node of nodes) {
19
+ // ------------------------------------------------------- an island
20
+ const degree = [...store.schema.edgeKinds].reduce((count, edgeKind) => count +
21
+ store.graph.out(node.id, edgeKind).length +
22
+ store.graph.in(node.id, edgeKind).length, 0);
23
+ if (degree === 0) {
24
+ observations.push({
25
+ id: `insight:island:${node.id}`,
26
+ text: `${name(node)} is connected to nothing yet`,
27
+ nodeIds: [node.id],
28
+ });
29
+ continue;
30
+ }
31
+ /*
32
+ * ------------------------------------------------- a concentration
33
+ * One node holding most of an edge kind is the structural shape of
34
+ * overload — "Ana carries 5 of 6 runs" — derivable with no idea
35
+ * what a run is.
36
+ */
37
+ for (const edgeKind of store.schema.edgeKinds) {
38
+ const mine = store.graph.in(node.id, edgeKind).length;
39
+ if (mine < 3)
40
+ continue;
41
+ const everywhere = [...store.graph.allEdges()].filter((edge) => edge.kind === edgeKind).length;
42
+ if (everywhere >= 4 && mine / everywhere > 0.6) {
43
+ observations.push({
44
+ id: `insight:load:${node.id}:${edgeKind}`,
45
+ text: `${name(node)} holds ${mine} of ${everywhere} "${edgeKind}" — most of them`,
46
+ nodeIds: [node.id],
47
+ });
48
+ }
49
+ }
50
+ }
51
+ // ------------------------------------------------------------- a gap
52
+ for (const kind of kindSelection) {
53
+ if (store.graph.nodesOfKind(kind).length > 0)
54
+ continue;
55
+ const expectedBy = store.schema.definitions
56
+ /*
57
+ * OTHER kinds, and only other kinds.
58
+ *
59
+ * A first kind with an edge to itself — which is what a scaffolded
60
+ * project starts with — made this say "Nothing here yet, though
61
+ * Items expect to connect to these" on an empty graph: the
62
+ * expectant party was the absent kind itself, so the sentence
63
+ * named no one and pointed at nothing. A gap is only worth
64
+ * stating when somebody ELSE is waiting on it.
65
+ */
66
+ .filter((definition) => definition.kind !== kind)
67
+ .filter((definition) => Object.values(definition.edges).some((edge) => edge.to !== "*" && edge.to.includes(kind)))
68
+ .map((definition) => definition.plural ?? `${definition.kind}s`);
69
+ if (expectedBy.length > 0) {
70
+ observations.push({
71
+ id: `insight:gap:${kind}`,
72
+ text: `Nothing here yet, though ${expectedBy.join(" and ")} expect to connect to these`,
73
+ nodeIds: [],
74
+ });
75
+ }
76
+ }
77
+ return { observations };
78
+ },
79
+ };
80
+ }
81
+ //# sourceMappingURL=insight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insight.js","sourceRoot":"","sources":["../../src/providers/insight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type AnySchema } from "@graview/core";
2
+ import type { AffordanceProvider } from "../types.js";
3
+ /**
4
+ * Violations touching the selection, and the repairs that would resolve them.
5
+ *
6
+ * This is why `repairs` exists on a violation at all: the invariant engine
7
+ * already knows both the problem and the mutations that would fix it, so a
8
+ * repair reaches the interface without anyone writing a rule to connect them.
9
+ * Repairs outrank every other provider — a thing that is currently broken is
10
+ * more interesting than a thing you could do.
11
+ */
12
+ export declare function invariantProvider<S extends AnySchema>(): AffordanceProvider<S>;
13
+ /** A node's own label, falling back to its id. */
14
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariant.d.ts","sourceRoot":"","sources":["../../src/providers/invariant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,KAAK,EAAc,kBAAkB,EAAe,MAAM,aAAa,CAAC;AAI/E;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,KAAK,kBAAkB,CAAC,CAAC,CAAC,CAsH9E;AAED,kDAAkD"}
@@ -0,0 +1,123 @@
1
+ import { argShape, labelOf, nodeRefArgs } from "@graview/core";
2
+ const REPAIR_SCORE = 100;
3
+ /**
4
+ * Violations touching the selection, and the repairs that would resolve them.
5
+ *
6
+ * This is why `repairs` exists on a violation at all: the invariant engine
7
+ * already knows both the problem and the mutations that would fix it, so a
8
+ * repair reaches the interface without anyone writing a rule to connect them.
9
+ * Repairs outrank every other provider — a thing that is currently broken is
10
+ * more interesting than a thing you could do.
11
+ */
12
+ export function invariantProvider() {
13
+ return {
14
+ name: "invariant",
15
+ derive({ store, selection, nodes, violations }) {
16
+ // A node's name as its kind says it, not its label field alone.
17
+ const named = (node) => labelOf(store.schema.tryDefinition(node.kind), node);
18
+ const selected = new Set(selection);
19
+ const touching = violations.filter((violation) => violation.nodeIds.some((id) => selected.has(id)) ||
20
+ (violation.subjectId !== undefined && selected.has(violation.subjectId)));
21
+ const affordances = [];
22
+ const observations = [];
23
+ touching.forEach((violation, index) => {
24
+ observations.push({
25
+ id: `violation:${violation.invariant}:${index}`,
26
+ text: violation.message,
27
+ nodeIds: violation.nodeIds,
28
+ });
29
+ violation.repairs.forEach((repair, repairIndex) => {
30
+ affordances.push({
31
+ id: `invariant:${violation.invariant}:${index}:${repairIndex}`,
32
+ label: repair.label,
33
+ provider: "invariant",
34
+ mutation: repair.mutation,
35
+ args: repair.args ?? {},
36
+ /*
37
+ * A repair names the mutation it would run, so everything the
38
+ * schema provider derives applies here too: what sort of answer
39
+ * the argument wants, and — when it names a node — which nodes
40
+ * would actually fit.
41
+ *
42
+ * The candidates were missing, and the omission only showed up
43
+ * in a second app: a repair saying "cover this in a section"
44
+ * with `sectionId` unanswered rendered as a free text box asking
45
+ * for a node id. Every repair that needed a node was unusable,
46
+ * and the household example never noticed because its repairs happened to
47
+ * carry their node arguments pre-filled.
48
+ */
49
+ open: (repair.missing ?? []).map((name) => {
50
+ const mutation = store
51
+ .allMutations()
52
+ .find((candidate) => candidate.name === repair.mutation);
53
+ if (!mutation)
54
+ return { name };
55
+ const ref = nodeRefArgs(mutation.input).find((arg) => arg.name === name);
56
+ const candidates = ref
57
+ ? ref.kinds.includes("*")
58
+ ? store.graph.allNodes().map((node) => node.id)
59
+ : ref.kinds.flatMap((kind) => store.graph.nodesOfKind(kind).map((node) => node.id))
60
+ : undefined;
61
+ return {
62
+ name,
63
+ shape: argShape(mutation.input, name),
64
+ ...(ref ? { kinds: ref.kinds } : {}),
65
+ ...(candidates ? { candidates } : {}),
66
+ };
67
+ }),
68
+ // A repair that needs nothing more is the readiest thing here.
69
+ score: REPAIR_SCORE - repairIndex - (repair.missing?.length ?? 0),
70
+ why: violation.message,
71
+ nodeIds: violation.nodeIds,
72
+ // Carried so the ranking can lead with the repairs of the RULE
73
+ // you clicked, the same way it leads with a task's own.
74
+ ...(violation.subjectId === undefined ? {} : { subjectId: violation.subjectId }),
75
+ });
76
+ });
77
+ });
78
+ /*
79
+ * A rule that is HOLDING says so, rather than showing nothing.
80
+ *
81
+ * A rule node has no edges, so selecting one used to change nothing on
82
+ * screen and read as broken. Lighting what it judges fixed half of
83
+ * that; the other half is the case where it judges everything
84
+ * correctly — silence there is indistinguishable from a rule that does
85
+ * not work, and "nothing is wrong" is an answer.
86
+ *
87
+ * Which nodes are rules is derivable: an invariant declares the kind it
88
+ * is scoped to, and a kind may declare the invariant it requires.
89
+ * Nothing is authored per app.
90
+ */
91
+ for (const node of nodes) {
92
+ const judged = store
93
+ .allInvariants()
94
+ .filter((invariant) => {
95
+ if (invariant.scope === "graph")
96
+ return false;
97
+ const scope = invariant.scope;
98
+ if (scope.kind !== node.kind)
99
+ return false;
100
+ return scope.match ? scope.match(node) : true;
101
+ });
102
+ if (judged.length === 0)
103
+ continue;
104
+ /*
105
+ * Not while ANY rule names it. A song implicated in its single's
106
+ * rule — the subject is the single — read "Kerosene holds — nothing
107
+ * currently breaks it" directly above the rule saying what was wrong
108
+ * with it.
109
+ */
110
+ if (touching.some((violation) => violation.subjectId === node.id || violation.nodeIds.includes(node.id)))
111
+ continue;
112
+ observations.push({
113
+ id: `holds:${node.id}`,
114
+ text: `${named(node)} holds — nothing currently breaks ${judged.length === 1 ? "it" : `any of its ${judged.length} rules`}`,
115
+ nodeIds: [node.id],
116
+ });
117
+ }
118
+ return { affordances, observations };
119
+ },
120
+ };
121
+ }
122
+ /** A node's own label, falling back to its id. */
123
+ //# sourceMappingURL=invariant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariant.js","sourceRoot":"","sources":["../../src/providers/invariant.ts"],"names":[],"mappings":"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"}