systemoneprompts 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 (147) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +214 -0
  4. package/dist/answers.d.ts +21 -0
  5. package/dist/answers.d.ts.map +1 -0
  6. package/dist/answers.js +104 -0
  7. package/dist/answers.js.map +1 -0
  8. package/dist/cli/cache.d.ts +2 -0
  9. package/dist/cli/cache.d.ts.map +1 -0
  10. package/dist/cli/cache.js +26 -0
  11. package/dist/cli/cache.js.map +1 -0
  12. package/dist/cli/check.d.ts +2 -0
  13. package/dist/cli/check.d.ts.map +1 -0
  14. package/dist/cli/check.js +28 -0
  15. package/dist/cli/check.js.map +1 -0
  16. package/dist/cli/env.d.ts +2 -0
  17. package/dist/cli/env.d.ts.map +1 -0
  18. package/dist/cli/env.js +29 -0
  19. package/dist/cli/env.js.map +1 -0
  20. package/dist/cli/eval.d.ts +18 -0
  21. package/dist/cli/eval.d.ts.map +1 -0
  22. package/dist/cli/eval.js +314 -0
  23. package/dist/cli/eval.js.map +1 -0
  24. package/dist/cli/generate.d.ts +5 -0
  25. package/dist/cli/generate.d.ts.map +1 -0
  26. package/dist/cli/generate.js +93 -0
  27. package/dist/cli/generate.js.map +1 -0
  28. package/dist/cli/index.d.ts +3 -0
  29. package/dist/cli/index.d.ts.map +1 -0
  30. package/dist/cli/index.js +76 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/io.d.ts +28 -0
  33. package/dist/cli/io.d.ts.map +1 -0
  34. package/dist/cli/io.js +88 -0
  35. package/dist/cli/io.js.map +1 -0
  36. package/dist/cli/run.d.ts +7 -0
  37. package/dist/cli/run.d.ts.map +1 -0
  38. package/dist/cli/run.js +63 -0
  39. package/dist/cli/run.js.map +1 -0
  40. package/dist/client.d.ts +65 -0
  41. package/dist/client.d.ts.map +1 -0
  42. package/dist/client.js +301 -0
  43. package/dist/client.js.map +1 -0
  44. package/dist/cloudflare.d.ts +29 -0
  45. package/dist/cloudflare.d.ts.map +1 -0
  46. package/dist/cloudflare.js +159 -0
  47. package/dist/cloudflare.js.map +1 -0
  48. package/dist/definition/check.d.ts +9 -0
  49. package/dist/definition/check.d.ts.map +1 -0
  50. package/dist/definition/check.js +26 -0
  51. package/dist/definition/check.js.map +1 -0
  52. package/dist/definition/diagnostics.d.ts +29 -0
  53. package/dist/definition/diagnostics.d.ts.map +1 -0
  54. package/dist/definition/diagnostics.js +74 -0
  55. package/dist/definition/diagnostics.js.map +1 -0
  56. package/dist/definition/locate.d.ts +23 -0
  57. package/dist/definition/locate.d.ts.map +1 -0
  58. package/dist/definition/locate.js +211 -0
  59. package/dist/definition/locate.js.map +1 -0
  60. package/dist/definition/parse.d.ts +15 -0
  61. package/dist/definition/parse.d.ts.map +1 -0
  62. package/dist/definition/parse.js +170 -0
  63. package/dist/definition/parse.js.map +1 -0
  64. package/dist/definition/schema.d.ts +39 -0
  65. package/dist/definition/schema.d.ts.map +1 -0
  66. package/dist/definition/schema.js +11 -0
  67. package/dist/definition/schema.js.map +1 -0
  68. package/dist/dev/cache.d.ts +58 -0
  69. package/dist/dev/cache.d.ts.map +1 -0
  70. package/dist/dev/cache.js +287 -0
  71. package/dist/dev/cache.js.map +1 -0
  72. package/dist/dev/index.d.ts +2 -0
  73. package/dist/dev/index.d.ts.map +1 -0
  74. package/dist/dev/index.js +3 -0
  75. package/dist/dev/index.js.map +1 -0
  76. package/dist/factors/evaluate.d.ts +21 -0
  77. package/dist/factors/evaluate.d.ts.map +1 -0
  78. package/dist/factors/evaluate.js +199 -0
  79. package/dist/factors/evaluate.js.map +1 -0
  80. package/dist/factors/graph.d.ts +7 -0
  81. package/dist/factors/graph.d.ts.map +1 -0
  82. package/dist/factors/graph.js +39 -0
  83. package/dist/factors/graph.js.map +1 -0
  84. package/dist/factors/schema.d.ts +54 -0
  85. package/dist/factors/schema.d.ts.map +1 -0
  86. package/dist/factors/schema.js +235 -0
  87. package/dist/factors/schema.js.map +1 -0
  88. package/dist/generate/generate.d.ts +16 -0
  89. package/dist/generate/generate.d.ts.map +1 -0
  90. package/dist/generate/generate.js +100 -0
  91. package/dist/generate/generate.js.map +1 -0
  92. package/dist/generate/types.d.ts +10 -0
  93. package/dist/generate/types.d.ts.map +1 -0
  94. package/dist/generate/types.js +126 -0
  95. package/dist/generate/types.js.map +1 -0
  96. package/dist/index.d.ts +15 -0
  97. package/dist/index.d.ts.map +1 -0
  98. package/dist/index.js +13 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/json.d.ts +6 -0
  101. package/dist/json.d.ts.map +1 -0
  102. package/dist/json.js +52 -0
  103. package/dist/json.js.map +1 -0
  104. package/dist/model.d.ts +9 -0
  105. package/dist/model.d.ts.map +1 -0
  106. package/dist/model.js +22 -0
  107. package/dist/model.js.map +1 -0
  108. package/dist/native.d.ts +97 -0
  109. package/dist/native.d.ts.map +1 -0
  110. package/dist/native.js +2 -0
  111. package/dist/native.js.map +1 -0
  112. package/dist/patterns/index.d.ts +3 -0
  113. package/dist/patterns/index.d.ts.map +1 -0
  114. package/dist/patterns/index.js +3 -0
  115. package/dist/patterns/index.js.map +1 -0
  116. package/dist/patterns/options.d.ts +2 -0
  117. package/dist/patterns/options.d.ts.map +1 -0
  118. package/dist/patterns/options.js +7 -0
  119. package/dist/patterns/options.js.map +1 -0
  120. package/dist/patterns/run-many.d.ts +41 -0
  121. package/dist/patterns/run-many.d.ts.map +1 -0
  122. package/dist/patterns/run-many.js +51 -0
  123. package/dist/patterns/run-many.js.map +1 -0
  124. package/dist/patterns/walk-taxonomy.d.ts +37 -0
  125. package/dist/patterns/walk-taxonomy.d.ts.map +1 -0
  126. package/dist/patterns/walk-taxonomy.js +81 -0
  127. package/dist/patterns/walk-taxonomy.js.map +1 -0
  128. package/dist/questions/references.d.ts +12 -0
  129. package/dist/questions/references.d.ts.map +1 -0
  130. package/dist/questions/references.js +76 -0
  131. package/dist/questions/references.js.map +1 -0
  132. package/dist/questions/schema.d.ts +18 -0
  133. package/dist/questions/schema.d.ts.map +1 -0
  134. package/dist/questions/schema.js +169 -0
  135. package/dist/questions/schema.js.map +1 -0
  136. package/dist/state/paths.d.ts +13 -0
  137. package/dist/state/paths.d.ts.map +1 -0
  138. package/dist/state/paths.js +70 -0
  139. package/dist/state/paths.js.map +1 -0
  140. package/dist/state/requirements.d.ts +25 -0
  141. package/dist/state/requirements.d.ts.map +1 -0
  142. package/dist/state/requirements.js +189 -0
  143. package/dist/state/requirements.js.map +1 -0
  144. package/docs/SPEC.html +57 -0
  145. package/docs/skills/systemoneprompts/SKILL.md +239 -0
  146. package/docs/skills/systemoneprompts/references/application-data.md +79 -0
  147. package/package.json +94 -0
@@ -0,0 +1,51 @@
1
+ import { positiveInteger } from "./options.js";
2
+ /**
3
+ * Ask questions about many states with bounded concurrency.
4
+ * Pass shared `questions` + `states`, or per-item `{ state, questions }`.
5
+ * Results keep input order; a failed call yields its `Error` instead of aborting the batch.
6
+ */
7
+ export async function runMany(client, opts) {
8
+ const concurrency = positiveInteger("concurrency", opts.concurrency ?? 4);
9
+ const jobs = jobsOf(opts);
10
+ const results = new Array(jobs.length);
11
+ let next = 0;
12
+ const worker = async () => {
13
+ while (next < jobs.length) {
14
+ const index = next++;
15
+ const job = jobs[index];
16
+ try {
17
+ const result = (await client.systemOne({
18
+ state: job.state,
19
+ questions: job.questions,
20
+ model: job.model,
21
+ }));
22
+ results[index] = result;
23
+ }
24
+ catch (error) {
25
+ const err = error instanceof Error ? error : new Error(String(error));
26
+ results[index] = err;
27
+ }
28
+ opts.onResult?.(index, results[index]);
29
+ }
30
+ };
31
+ await Promise.all(Array.from({ length: Math.min(concurrency, jobs.length) }, () => worker()));
32
+ return results;
33
+ }
34
+ function jobsOf(opts) {
35
+ const { items, states, questions, model } = opts;
36
+ if (items !== undefined && (states !== undefined || questions !== undefined)) {
37
+ throw new Error("runMany accepts either items or states, not both");
38
+ }
39
+ if (items !== undefined) {
40
+ return items.map((item) => ({
41
+ state: item.state,
42
+ questions: item.questions,
43
+ model: item.model ?? model,
44
+ }));
45
+ }
46
+ if (questions === undefined || states === undefined) {
47
+ throw new Error("runMany requires questions and states");
48
+ }
49
+ return states.map((state) => ({ state, questions, model }));
50
+ }
51
+ //# sourceMappingURL=run-many.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-many.js","sourceRoot":"","sources":["../../src/patterns/run-many.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAwC/C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAuB,EACvB,IAAuB;IAEvB,MAAM,WAAW,GAAG,eAAe,CAAC,aAAa,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAC1E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAsC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1E,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;QACxB,OAAO,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;YACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC;oBACrC,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;iBACjB,CAAC,CAAuB,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtE,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;YACvB,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9F,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,MAAM,CAAsB,IAAuB;IAC1D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAK3C,CAAC;IACF,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;SAC3B,CAAC,CAAC,CAAC;IACN,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { EntryType } from "../native.js";
2
+ import type { SystemOneClient } from "./run-many.js";
3
+ /** An explicit node: a description for this label plus optional children. */
4
+ export interface TaxonomyNode {
5
+ description?: EntryType;
6
+ children?: TaxonomyTree;
7
+ }
8
+ /**
9
+ * Labels mapped to a leaf description (string), an explicit node, or a nested tree.
10
+ * A nested tree whose own labels are literally `description` / `children` must be
11
+ * written as an explicit `TaxonomyNode` to avoid being read as one.
12
+ */
13
+ export interface TaxonomyTree {
14
+ [label: string]: string | TaxonomyNode | TaxonomyTree;
15
+ }
16
+ export interface WalkTaxonomyOptions {
17
+ state: unknown;
18
+ /** Instructions reused at every level; the criteria are the current node's children. */
19
+ instructions?: EntryType;
20
+ tree: TaxonomyTree;
21
+ /** Paths kept alive at each level, ranked by cumulative probability. Default 1. */
22
+ beamWidth?: number;
23
+ model?: string;
24
+ }
25
+ export interface TaxonomyPath {
26
+ path: string[];
27
+ /** Product of the Choice probabilities along the path. */
28
+ probability: number;
29
+ }
30
+ /**
31
+ * Hierarchical Choice: at each level the criteria are the current node's children with
32
+ * their subtrees as descriptions, so the model sees what each branch leads to. Returns the
33
+ * best complete paths found within the beam, most probable first. Beam pruning
34
+ * is approximate: it can discard a branch containing a globally better leaf.
35
+ */
36
+ export declare function walkTaxonomy(client: SystemOneClient, opts: WalkTaxonomyOptions): Promise<TaxonomyPath[]>;
37
+ //# sourceMappingURL=walk-taxonomy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk-taxonomy.d.ts","sourceRoot":"","sources":["../../src/patterns/walk-taxonomy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,SAAS,EAAa,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;CACvD;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,wFAAwF;IACxF,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,CAkDzB"}
@@ -0,0 +1,81 @@
1
+ import { isPlainObject } from "../json.js";
2
+ import { positiveInteger } from "./options.js";
3
+ const STEP = "step";
4
+ /**
5
+ * Hierarchical Choice: at each level the criteria are the current node's children with
6
+ * their subtrees as descriptions, so the model sees what each branch leads to. Returns the
7
+ * best complete paths found within the beam, most probable first. Beam pruning
8
+ * is approximate: it can discard a branch containing a globally better leaf.
9
+ */
10
+ export async function walkTaxonomy(client, opts) {
11
+ const beamWidth = positiveInteger("beamWidth", opts.beamWidth ?? 1);
12
+ let beam = [{ path: [], probability: 1, node: opts.tree }];
13
+ const finished = [];
14
+ while (beam.length > 0) {
15
+ const expanded = [];
16
+ for (const item of beam) {
17
+ const labels = Object.keys(item.node);
18
+ if (labels.length === 0) {
19
+ finished.push({ path: item.path, probability: item.probability });
20
+ continue;
21
+ }
22
+ const criteria = Object.fromEntries(labels.map((label) => [label, subtreeDescription(item.node[label])]));
23
+ const questions = {
24
+ [STEP]: {
25
+ type: "choice",
26
+ ...(opts.instructions !== undefined ? { instructions: opts.instructions } : {}),
27
+ criteria,
28
+ },
29
+ };
30
+ const response = await client.systemOne({ state: opts.state, questions, model: opts.model });
31
+ const { probabilities } = response.answers[STEP];
32
+ for (const label of labels) {
33
+ expanded.push({
34
+ path: [...item.path, label],
35
+ probability: item.probability * (probabilities[label] ?? 0),
36
+ node: childrenOf(item.node[label]),
37
+ });
38
+ }
39
+ }
40
+ expanded.sort((a, b) => b.probability - a.probability);
41
+ const continuing = [];
42
+ for (const item of expanded) {
43
+ if (Object.keys(item.node).length === 0) {
44
+ finished.push({ path: item.path, probability: item.probability });
45
+ }
46
+ else {
47
+ continuing.push(item);
48
+ }
49
+ }
50
+ beam = continuing.slice(0, beamWidth);
51
+ }
52
+ finished.sort((a, b) => b.probability - a.probability);
53
+ return finished.slice(0, beamWidth);
54
+ }
55
+ function childrenOf(value) {
56
+ if (typeof value === "string")
57
+ return {};
58
+ if (isNode(value))
59
+ return value.children ?? {};
60
+ return value;
61
+ }
62
+ /** A leaf's description, or a nested object mirroring the subtree so the model sees where a branch leads. */
63
+ function subtreeDescription(value) {
64
+ if (typeof value === "string")
65
+ return value;
66
+ if (isNode(value)) {
67
+ if (value.children && Object.keys(value.children).length > 0) {
68
+ return treeDescription(value.children);
69
+ }
70
+ return value.description ?? null;
71
+ }
72
+ return treeDescription(value);
73
+ }
74
+ function treeDescription(tree) {
75
+ return Object.fromEntries(Object.entries(tree).map(([label, child]) => [label, subtreeDescription(child)]));
76
+ }
77
+ function isNode(value) {
78
+ return (isPlainObject(value) &&
79
+ (Object.hasOwn(value, "description") || Object.hasOwn(value, "children")));
80
+ }
81
+ //# sourceMappingURL=walk-taxonomy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk-taxonomy.js","sourceRoot":"","sources":["../../src/patterns/walk-taxonomy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type Diagnostic } from "../definition/diagnostics.js";
2
+ import { type SourceIndex } from "../definition/locate.js";
3
+ import type { Questions } from "../native.js";
4
+ import type { Requirements } from "../state/requirements.js";
5
+ /**
6
+ * Warn when a backticked, path-shaped token in `instructions` / `criteria` is not
7
+ * guaranteed by `[requires]`. A prefix of a guaranteed path (`ticket` when
8
+ * `ticket.message` is required) counts as guaranteed.
9
+ */
10
+ export declare function lintBackticks(questions: Questions, requires: Requirements, index: SourceIndex): Diagnostic[];
11
+ export declare function collectBackticks(...values: unknown[]): string[];
12
+ //# sourceMappingURL=references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../../src/questions/references.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAA4B,MAAM,8BAA8B,CAAC;AACzF,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAI7D;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,WAAW,GACjB,UAAU,EAAE,CA4Bd;AAqBD,wBAAgB,gBAAgB,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAS/D"}
@@ -0,0 +1,76 @@
1
+ import { diagnostic, nearestMatch } from "../definition/diagnostics.js";
2
+ import { locate } from "../definition/locate.js";
3
+ import { formatPath, parsePath } from "../state/paths.js";
4
+ const BACKTICK_RE = /`([^`]+)`/g;
5
+ /**
6
+ * Warn when a backticked, path-shaped token in `instructions` / `criteria` is not
7
+ * guaranteed by `[requires]`. A prefix of a guaranteed path (`ticket` when
8
+ * `ticket.message` is required) counts as guaranteed.
9
+ */
10
+ export function lintBackticks(questions, requires, index) {
11
+ const guaranteed = Object.keys(requires).flatMap((path) => {
12
+ const segments = parsePath(path);
13
+ return segments ? [{ formatted: formatPath(segments), segments }] : [];
14
+ });
15
+ const diagnostics = [];
16
+ const guaranteedPaths = guaranteed.map((entry) => entry.formatted);
17
+ for (const [id, question] of Object.entries(questions)) {
18
+ const loc = locate(index, { table: ["questions", id], section: "questions", key: id });
19
+ for (const token of collectBackticks(question.instructions, question.criteria)) {
20
+ const segments = parsePath(token);
21
+ if (!segments)
22
+ continue;
23
+ if (guaranteed.some((entry) => pathGuaranteesToken(entry.segments, segments)))
24
+ continue;
25
+ const suggestion = nearestMatch(token, guaranteedPaths);
26
+ diagnostics.push(diagnostic("warning", "unguaranteed-backtick", `\`${token}\` is not guaranteed by [requires]`, loc, suggestion ? `did you mean \`${suggestion}\`?` : undefined));
27
+ }
28
+ }
29
+ return diagnostics;
30
+ }
31
+ function pathGuaranteesToken(required, token) {
32
+ for (let i = 0; i < token.length; i += 1) {
33
+ const requiredSegment = required[i];
34
+ if (requiredSegment == null)
35
+ return false;
36
+ if (!segmentGuarantees(requiredSegment, token[i]))
37
+ return false;
38
+ }
39
+ return true;
40
+ }
41
+ function segmentGuarantees(required, token) {
42
+ if (required.kind === "key" && token.kind === "key")
43
+ return required.name === token.name;
44
+ if (required.kind === "index" && token.kind === "index")
45
+ return required.index === token.index;
46
+ if (required.kind === "all" && token.kind === "all")
47
+ return true;
48
+ return required.kind === "all" && token.kind === "index";
49
+ }
50
+ export function collectBackticks(...values) {
51
+ const found = [];
52
+ walk(values, (text) => {
53
+ for (const match of text.matchAll(BACKTICK_RE)) {
54
+ const token = match[1] ?? "";
55
+ if (token && !found.includes(token))
56
+ found.push(token);
57
+ }
58
+ });
59
+ return found;
60
+ }
61
+ function walk(value, onString) {
62
+ if (typeof value === "string") {
63
+ onString(value);
64
+ return;
65
+ }
66
+ if (Array.isArray(value)) {
67
+ for (const entry of value)
68
+ walk(entry, onString);
69
+ return;
70
+ }
71
+ if (value && typeof value === "object") {
72
+ for (const entry of Object.values(value))
73
+ walk(entry, onString);
74
+ }
75
+ }
76
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../../src/questions/references.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Diagnostic } from "../definition/diagnostics.js";
2
+ import { type SourceIndex } from "../definition/locate.js";
3
+ import type { Questions } from "../native.js";
4
+ export declare const QUESTION_TYPES: readonly ["noul", "choice", "score"];
5
+ export type QuestionType = (typeof QUESTION_TYPES)[number];
6
+ /** What factor validation needs to know about a question: its primitive and, for Choice, its labels. */
7
+ export interface QuestionInfo {
8
+ id: string;
9
+ type: QuestionType;
10
+ choiceLabels?: string[];
11
+ }
12
+ export declare function questionInfos(questions: Questions): Map<string, QuestionInfo>;
13
+ export declare function validateQuestions(raw: unknown, index: SourceIndex): {
14
+ questions: Questions;
15
+ infos: Map<string, QuestionInfo>;
16
+ diagnostics: Diagnostic[];
17
+ };
18
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/questions/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,8BAA8B,CAAC;AAE/E,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,cAAc,sCAAuC,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAK3D,wGAAwG;AACxG,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAU7E;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,GACjB;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CAuCvF"}
@@ -0,0 +1,169 @@
1
+ import { diagnostic } from "../definition/diagnostics.js";
2
+ import { locate } from "../definition/locate.js";
3
+ import { isJsonValue, isPlainObject } from "../json.js";
4
+ export const QUESTION_TYPES = ["noul", "choice", "score"];
5
+ const MAX_CHOICE_LABELS = 255;
6
+ const QUESTION_FIELDS = new Set(["type", "instructions", "criteria"]);
7
+ export function questionInfos(questions) {
8
+ const infos = new Map();
9
+ for (const [id, question] of Object.entries(questions)) {
10
+ infos.set(id, {
11
+ id,
12
+ type: question.type,
13
+ ...(question.type === "choice" ? { choiceLabels: Object.keys(question.criteria) } : {}),
14
+ });
15
+ }
16
+ return infos;
17
+ }
18
+ export function validateQuestions(raw, index) {
19
+ const diagnostics = [];
20
+ const questions = Object.create(null);
21
+ const infos = new Map();
22
+ if (raw == null || (isPlainObject(raw) && Object.keys(raw).length === 0)) {
23
+ diagnostics.push(diagnostic("error", "questions-empty", "[questions] must contain at least one question", locate(index, { table: "questions" })));
24
+ return { questions, infos, diagnostics };
25
+ }
26
+ if (!isPlainObject(raw)) {
27
+ diagnostics.push(diagnostic("error", "questions-not-table", "[questions] must be a table of question objects", locate(index, { table: "questions" })));
28
+ return { questions, infos, diagnostics };
29
+ }
30
+ for (const [id, value] of Object.entries(raw)) {
31
+ const loc = locate(index, { table: `questions.${id}`, section: "questions", key: id });
32
+ const result = validateQuestion(id, value, loc);
33
+ diagnostics.push(...result.diagnostics);
34
+ if (result.question && result.info) {
35
+ questions[id] = result.question;
36
+ infos.set(id, result.info);
37
+ }
38
+ }
39
+ return { questions, infos, diagnostics };
40
+ }
41
+ function validateQuestion(id, value, loc) {
42
+ const diagnostics = [];
43
+ if (!isPlainObject(value)) {
44
+ diagnostics.push(diagnostic("error", "question-not-table", `question \`${id}\` must be a table`, loc));
45
+ return { diagnostics };
46
+ }
47
+ const extraKeys = Object.keys(value).filter((k) => !QUESTION_FIELDS.has(k));
48
+ for (const key of extraKeys) {
49
+ diagnostics.push(diagnostic("error", "unknown-question-field", `question \`${id}\` has unknown field \`${key}\``, loc, "only `type`, `instructions`, and `criteria` are allowed"));
50
+ }
51
+ const type = value.type;
52
+ if (type !== "noul" && type !== "choice" && type !== "score") {
53
+ diagnostics.push(diagnostic("error", "invalid-question-type", `question \`${id}\` has ${type == null ? "missing" : `invalid`} type ${type == null ? "" : `\`${String(type)}\``}`.trim(), loc, 'type must be "noul", "choice", or "score"'));
54
+ return { diagnostics };
55
+ }
56
+ if (value.instructions !== undefined && !isEntryType(value.instructions)) {
57
+ diagnostics.push(diagnostic("error", "invalid-instructions", `question \`${id}\` instructions must be a string, table, or array`, loc));
58
+ return { diagnostics };
59
+ }
60
+ if (type === "noul") {
61
+ return validateNoul(id, value, loc, diagnostics);
62
+ }
63
+ if (type === "choice") {
64
+ return validateChoice(id, value, loc, diagnostics);
65
+ }
66
+ return validateScore(id, value, loc, diagnostics);
67
+ }
68
+ function validateNoul(id, value, loc, diagnostics) {
69
+ if (value.criteria != null) {
70
+ if (!isPlainObject(value.criteria)) {
71
+ diagnostics.push(diagnostic("error", "noul-criteria", `Noul \`${id}\` criteria must be a table with optional true/false keys`, loc));
72
+ return { diagnostics };
73
+ }
74
+ const unknown = Object.keys(value.criteria).filter((k) => k !== "true" && k !== "false");
75
+ if (unknown.length > 0) {
76
+ diagnostics.push(diagnostic("error", "noul-criteria-keys", `Noul \`${id}\` criteria may only contain true/false; found ${unknown.map((k) => `\`${k}\``).join(", ")}`, loc));
77
+ return { diagnostics };
78
+ }
79
+ for (const key of ["true", "false"]) {
80
+ const entry = value.criteria[key];
81
+ if (entry !== undefined && !isEntryType(entry)) {
82
+ diagnostics.push(diagnostic("error", "noul-criteria-entry", `Noul \`${id}\` criteria.${key} must be a string, table, or array`, loc));
83
+ return { diagnostics };
84
+ }
85
+ }
86
+ }
87
+ const question = stripUndefined({
88
+ type: "noul",
89
+ ...(value.instructions !== undefined
90
+ ? { instructions: value.instructions }
91
+ : {}),
92
+ ...(value.criteria !== undefined
93
+ ? { criteria: value.criteria }
94
+ : {}),
95
+ });
96
+ return { question, info: { id, type: "noul" }, diagnostics };
97
+ }
98
+ function validateChoice(id, value, loc, diagnostics) {
99
+ if (!isPlainObject(value.criteria)) {
100
+ diagnostics.push(diagnostic("error", "choice-criteria", `Choice \`${id}\` requires a non-empty criteria table`, loc));
101
+ return { diagnostics };
102
+ }
103
+ const labels = Object.keys(value.criteria);
104
+ if (labels.length === 0) {
105
+ diagnostics.push(diagnostic("error", "choice-criteria-empty", `Choice \`${id}\` criteria must not be empty`, loc));
106
+ return { diagnostics };
107
+ }
108
+ if (labels.length > MAX_CHOICE_LABELS) {
109
+ diagnostics.push(diagnostic("error", "choice-criteria-limit", `Choice \`${id}\` has ${labels.length} labels; maximum is ${MAX_CHOICE_LABELS}`, loc));
110
+ return { diagnostics };
111
+ }
112
+ for (const [label, entry] of Object.entries(value.criteria)) {
113
+ if (!isEntryType(entry)) {
114
+ diagnostics.push(diagnostic("error", "choice-criteria-entry", `Choice \`${id}\` criteria.${label} must be a string, table, or array`, loc));
115
+ return { diagnostics };
116
+ }
117
+ }
118
+ const question = stripUndefined({
119
+ type: "choice",
120
+ ...(value.instructions !== undefined
121
+ ? { instructions: value.instructions }
122
+ : {}),
123
+ criteria: value.criteria,
124
+ });
125
+ return { question, info: { id, type: "choice", choiceLabels: labels }, diagnostics };
126
+ }
127
+ function validateScore(id, value, loc, diagnostics) {
128
+ if (!Array.isArray(value.criteria)) {
129
+ diagnostics.push(diagnostic("error", "score-criteria", `Score \`${id}\` requires criteria as an array of at least 2 entries`, loc));
130
+ return { diagnostics };
131
+ }
132
+ if (value.criteria.length < 2) {
133
+ diagnostics.push(diagnostic("error", "score-criteria-min", `Score \`${id}\` criteria must have at least 2 entries`, loc));
134
+ return { diagnostics };
135
+ }
136
+ for (let i = 0; i < value.criteria.length; i++) {
137
+ const entry = value.criteria[i];
138
+ if (!isEntryType(entry)) {
139
+ diagnostics.push(diagnostic("error", "score-criteria-entry", `Score \`${id}\` criteria[${i}] must be a string, table, or array`, loc));
140
+ return { diagnostics };
141
+ }
142
+ }
143
+ const question = stripUndefined({
144
+ type: "score",
145
+ ...(value.instructions !== undefined
146
+ ? { instructions: value.instructions }
147
+ : {}),
148
+ criteria: value.criteria,
149
+ });
150
+ return { question, info: { id, type: "score" }, diagnostics };
151
+ }
152
+ function isEntryType(value) {
153
+ if (value === null)
154
+ return true;
155
+ if (typeof value === "string")
156
+ return true;
157
+ if (Array.isArray(value) || isPlainObject(value))
158
+ return isJsonValue(value);
159
+ return false;
160
+ }
161
+ function stripUndefined(value) {
162
+ const out = { ...value };
163
+ for (const [key, entry] of Object.entries(out)) {
164
+ if (entry === undefined)
165
+ delete out[key];
166
+ }
167
+ return out;
168
+ }
169
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/questions/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type PathSegment = {
2
+ kind: "key";
3
+ name: string;
4
+ } | {
5
+ kind: "index";
6
+ index: number;
7
+ } | {
8
+ kind: "all";
9
+ };
10
+ export declare function parsePath(path: string): PathSegment[] | null;
11
+ export declare function getAtPath(value: unknown, segments: readonly PathSegment[]): unknown;
12
+ export declare function formatPath(segments: readonly PathSegment[]): string;
13
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/state/paths.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AASpB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,IAAI,CAiB5D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,CAmBnF;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAYnE"}
@@ -0,0 +1,70 @@
1
+ const IDENT = "[A-Za-z_][A-Za-z0-9_]*";
2
+ const INDEX = "\\[(-?\\d+)\\]";
3
+ const ALL = "\\[\\]";
4
+ const PATH_RE = new RegExp(`^(${IDENT})((?:\\.${IDENT}|${INDEX}|${ALL})*)$`);
5
+ const TAIL_RE = new RegExp(`\\.(${IDENT})|${INDEX}|${ALL}`, "g");
6
+ const MAX_INDEX = 2 ** 32 - 2;
7
+ export function parsePath(path) {
8
+ const match = PATH_RE.exec(path);
9
+ if (!match)
10
+ return null;
11
+ const segments = [{ kind: "key", name: match[1] ?? "" }];
12
+ const tail = match[2] ?? "";
13
+ if (!tail)
14
+ return segments;
15
+ for (const part of tail.matchAll(TAIL_RE)) {
16
+ if (part[1] != null)
17
+ segments.push({ kind: "key", name: part[1] });
18
+ else if (part[2] != null) {
19
+ const index = Number(part[2]);
20
+ if (!Number.isInteger(index) || Math.abs(index) > MAX_INDEX)
21
+ return null;
22
+ segments.push({ kind: "index", index });
23
+ }
24
+ else {
25
+ segments.push({ kind: "all" });
26
+ }
27
+ }
28
+ return segments;
29
+ }
30
+ export function getAtPath(value, segments) {
31
+ let current = value;
32
+ for (const segment of segments) {
33
+ if (current == null)
34
+ return undefined;
35
+ if (segment.kind === "key") {
36
+ if (typeof current !== "object" || Array.isArray(current))
37
+ return undefined;
38
+ if (!Object.hasOwn(current, segment.name))
39
+ return undefined;
40
+ current = current[segment.name];
41
+ continue;
42
+ }
43
+ if (segment.kind === "all")
44
+ return undefined;
45
+ if (!Array.isArray(current) || !Number.isInteger(segment.index)) {
46
+ return undefined;
47
+ }
48
+ const index = segment.index >= 0 ? segment.index : current.length + segment.index;
49
+ if (index < 0 || index >= current.length)
50
+ return undefined;
51
+ current = current[index];
52
+ }
53
+ return current;
54
+ }
55
+ export function formatPath(segments) {
56
+ let out = "";
57
+ for (const segment of segments) {
58
+ if (segment.kind === "key") {
59
+ out = out === "" ? segment.name : `${out}.${segment.name}`;
60
+ }
61
+ else if (segment.kind === "all") {
62
+ out += "[]";
63
+ }
64
+ else {
65
+ out += `[${segment.index}]`;
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/state/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type Diagnostic } from "../definition/diagnostics.js";
2
+ import { type SourceIndex } from "../definition/locate.js";
3
+ export declare const REQUIREMENT_TYPES: readonly ["string", "number", "boolean", "array", "object", "null", "exists"];
4
+ export type RequirementType = (typeof REQUIREMENT_TYPES)[number];
5
+ /** `[requires]`: dotted / indexed state path → minimum runtime type. */
6
+ export type Requirements = Record<string, RequirementType>;
7
+ export type StateAssert<T = Record<string, unknown>> = (state: unknown) => asserts state is T;
8
+ export declare function parseRequirements(raw: unknown, index: SourceIndex): {
9
+ requires: Requirements;
10
+ diagnostics: Diagnostic[];
11
+ };
12
+ /**
13
+ * Check both explicit types and containers implied by dotted/indexed descendants.
14
+ * Compare parsed segments so spellings such as [0] and [00] refer to the same index.
15
+ */
16
+ export declare function checkRequirementConflicts(requires: Requirements, index: SourceIndex): Diagnostic[];
17
+ export declare function isRequirementType(value: unknown): value is RequirementType;
18
+ /**
19
+ * Build an assertion that every `[requires]` path exists with the expected type.
20
+ * The assertion narrows and throws; it never copies or reshapes the state.
21
+ * Invalid paths fail here, at construction, rather than on first use.
22
+ */
23
+ export declare function createStateAssert<T = Record<string, unknown>>(requires: Requirements): StateAssert<T>;
24
+ export declare function checkRequirement(path: string, expected: RequirementType, actual: unknown): Diagnostic | undefined;
25
+ //# sourceMappingURL=requirements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../src/state/requirements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAqC,MAAM,8BAA8B,CAAC;AAClG,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAInE,eAAO,MAAM,iBAAiB,+EAQpB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAE3D,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;AAE9F,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,GACjB;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CA8CvD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,WAAW,GACjB,UAAU,EAAE,CA6Dd;AA4DD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,QAAQ,EAAE,YAAY,GACrB,WAAW,CAAC,CAAC,CAAC,CAkBhB;AAyBD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,OAAO,GACd,UAAU,GAAG,SAAS,CAIxB"}