@inflexa-ai/harness 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/agents/report-session-agent.d.ts +32 -9
  2. package/dist/agents/report-session-agent.js +22 -6
  3. package/dist/app/report-session-runtime.js +26 -0
  4. package/dist/app/spawn-report-session.d.ts +32 -5
  5. package/dist/app/spawn-report-session.js +19 -0
  6. package/dist/auth/local-run-authorizer.d.ts +3 -2
  7. package/dist/auth/local-run-authorizer.js +4 -2
  8. package/dist/config/environment-stores.d.ts +12 -7
  9. package/dist/config/resource-limits.d.ts +6 -10
  10. package/dist/config/resource-limits.js +6 -44
  11. package/dist/contracts/report-reference.d.ts +4 -0
  12. package/dist/contracts/report-reference.js +3 -0
  13. package/dist/execution/run-authorizer.d.ts +18 -0
  14. package/dist/execution/run-canceler.d.ts +67 -0
  15. package/dist/execution/run-canceler.js +130 -0
  16. package/dist/index.d.ts +7 -3
  17. package/dist/index.js +6 -1
  18. package/dist/lib/chrome.d.ts +14 -0
  19. package/dist/lib/chrome.js +7 -0
  20. package/dist/lib/page-capture.d.ts +47 -0
  21. package/dist/lib/page-capture.js +83 -0
  22. package/dist/loop/run-agent.js +104 -15
  23. package/dist/memory/ai-sdk-message-storage.d.ts +9 -4
  24. package/dist/memory/ai-sdk-message-storage.js +9 -4
  25. package/dist/memory/count-tokens.js +34 -5
  26. package/dist/prompts/report-session.d.ts +1 -1
  27. package/dist/prompts/report-session.js +21 -0
  28. package/dist/providers/ai-sdk.d.ts +81 -3
  29. package/dist/providers/ai-sdk.js +91 -10
  30. package/dist/providers/types.d.ts +17 -0
  31. package/dist/report-model/assert-rules.d.ts +44 -0
  32. package/dist/report-model/assert-rules.js +97 -0
  33. package/dist/report-model/draft-hash.d.ts +14 -0
  34. package/dist/report-model/draft-hash.js +36 -0
  35. package/dist/report-model/fixture-resolver.js +2 -71
  36. package/dist/report-model/production-resolver.d.ts +124 -0
  37. package/dist/report-model/production-resolver.js +801 -0
  38. package/dist/report-model/reference-resolver.d.ts +6 -0
  39. package/dist/report-model/validate.js +5 -0
  40. package/dist/report-render/assets.d.ts +42 -0
  41. package/dist/report-render/assets.js +61 -0
  42. package/dist/report-render/chart.js +31 -10
  43. package/dist/report-render/design.d.ts +120 -0
  44. package/dist/report-render/design.js +808 -0
  45. package/dist/report-render/page.d.ts +51 -111
  46. package/dist/report-render/page.js +158 -268
  47. package/dist/report-render/render.js +34 -11
  48. package/dist/report-render/views/chart-view.d.ts +6 -3
  49. package/dist/report-render/views/chart-view.js +10 -5
  50. package/dist/report-render/views/page-view.d.ts +19 -8
  51. package/dist/report-render/views/page-view.js +31 -11
  52. package/dist/report-render/views/prose.d.ts +1 -0
  53. package/dist/report-render/views/prose.js +7 -13
  54. package/dist/report-render/views/references-view.js +5 -5
  55. package/dist/report-render/views/values.d.ts +15 -6
  56. package/dist/report-render/views/values.js +29 -10
  57. package/dist/runtime/assemble.d.ts +38 -4
  58. package/dist/runtime/assemble.js +43 -3
  59. package/dist/sandbox/k8s-client.js +18 -0
  60. package/dist/sandbox/mount-plan.d.ts +7 -0
  61. package/dist/sandbox/mount-plan.js +7 -2
  62. package/dist/sandbox/types.d.ts +6 -0
  63. package/dist/state/analyses.d.ts +3 -26
  64. package/dist/state/analyses.js +6 -64
  65. package/dist/state/index.d.ts +2 -2
  66. package/dist/state/index.js +2 -2
  67. package/dist/state/init.js +23 -10
  68. package/dist/state/report-session-state.d.ts +27 -0
  69. package/dist/state/report-session-state.js +29 -2
  70. package/dist/state/runs.d.ts +10 -0
  71. package/dist/state/runs.js +21 -0
  72. package/dist/tasks/data-profile.d.ts +4 -0
  73. package/dist/tasks/data-profile.js +14 -0
  74. package/dist/tasks/extract-values-script.d.ts +64 -0
  75. package/dist/tasks/extract-values-script.js +180 -0
  76. package/dist/tasks/extract-values.d.ts +124 -0
  77. package/dist/tasks/extract-values.js +193 -0
  78. package/dist/tools/approval/gateway.d.ts +8 -1
  79. package/dist/tools/approval/gateway.js +9 -2
  80. package/dist/tools/approval/queries.d.ts +9 -2
  81. package/dist/tools/approval/queries.js +12 -4
  82. package/dist/tools/define-tool.d.ts +29 -0
  83. package/dist/tools/define-tool.js +26 -0
  84. package/dist/tools/report/preview-snapshot.d.ts +1 -1
  85. package/dist/tools/report/preview-snapshot.js +11 -50
  86. package/dist/tools/report-authoring/authoring-tools.d.ts +54 -4
  87. package/dist/tools/report-authoring/authoring-tools.js +1 -1
  88. package/dist/tools/report-session/examine-page.d.ts +90 -0
  89. package/dist/tools/report-session/examine-page.js +136 -0
  90. package/dist/tools/report-session/index.d.ts +3 -1
  91. package/dist/tools/report-session/index.js +3 -1
  92. package/dist/tools/report-session/preview-report.d.ts +31 -6
  93. package/dist/tools/report-session/preview-report.js +63 -16
  94. package/dist/tools/report-session/record-version.d.ts +102 -0
  95. package/dist/tools/report-session/record-version.js +139 -0
  96. package/dist/tools/sandbox/list-available-packages.js +2 -1
  97. package/dist/tools/sandbox/list-available-refs.d.ts +5 -1
  98. package/dist/tools/sandbox/list-available-refs.js +13 -6
  99. package/dist/workflows/sandbox-step.d.ts +4 -0
  100. package/dist/workflows/sandbox-step.js +21 -2
  101. package/package.json +14 -8
@@ -4,18 +4,8 @@
4
4
  * assertion rules without a host.
5
5
  */
6
6
  import { err, ok } from "neverthrow";
7
+ import { asFiniteNumber, cellMatchesFilterValue, checkCitationAssertion, checkValueAssertion } from "./assert-rules.js";
7
8
  import { columnsHeldByNoRow, fileTypeHoldsNoCell, snapshotEntry, } from "./reference-resolver.js";
8
- /**
9
- * The relative epsilon of a value match with no authored tolerance.
10
- *
11
- * Float arithmetic shifts a computed value in its last bits. For example, `0.3 - 0.1` gives
12
- * 0.19999999999999998, and exact equality would report that noise as a fabrication.
13
- *
14
- * The epsilon absorbs the noise and nothing else. It is far below the difference that a rounded figure
15
- * makes, thus an author who writes 0.05 against a true 0.0499 still fails. An author who wants a rounded
16
- * figure to pass states a `tolerance`, which is the one place where the intent belongs.
17
- */
18
- const RELATIVE_EPSILON = 1e-9;
19
9
  /** Build an `Err` that carries the unresolved reference. The `detail` key is present only when there is a detail to carry. */
20
10
  function fail(reference, reason, detail) {
21
11
  const failure = detail !== undefined ? { reference, reason, detail } : { reference, reason };
@@ -25,65 +15,6 @@ function fail(reference, reason, detail) {
25
15
  function describeReference(reference) {
26
16
  return `artifact value at ${reference.path} column ${reference.locator.column}`;
27
17
  }
28
- /**
29
- * Read an authored value or a resolved cell as a finite number.
30
- *
31
- * A text-backed artifact such as a CSV holds every cell as a string, thus a numeric column arrives as
32
- * `"0.01"` and not as `0.01`. A comparison that respects the JavaScript type would fail an author who
33
- * states the number, and the arithmetic of a derivation could never run over a real CSV.
34
- *
35
- * The parse reads the whole string, thus `"12 genes"` stays text and never reads as 12. `Number` accepts
36
- * the exponent form that a p-value uses, for example `"1.2e-45"`. A blank string is not a number, because
37
- * `Number("")` gives 0 and an empty cell must never read as zero.
38
- */
39
- function asFiniteNumber(value) {
40
- if (typeof value === "number") {
41
- return Number.isFinite(value) ? value : undefined;
42
- }
43
- if (value.trim() === "") {
44
- return undefined;
45
- }
46
- const parsed = Number(value);
47
- return Number.isFinite(parsed) ? parsed : undefined;
48
- }
49
- /** Name a value with its type, so that a failed match never reads as two identical values. */
50
- function describeValue(value) {
51
- return typeof value === "string" ? `the string ${JSON.stringify(value)}` : `the number ${value}`;
52
- }
53
- /**
54
- * Match a resolved value against an authored one.
55
- *
56
- * The comparison is numeric whenever both sides read as a finite number, thus the CSV cell `"0.01"`
57
- * matches the number 0.01 that an author states. An authored tolerance is an absolute difference, and it
58
- * is the author's own statement of how close is close enough. With no tolerance the comparison is
59
- * relative, because an exact match would fail on the float noise of a computed value. Any other pair
60
- * matches on exact equality.
61
- */
62
- function valuesMatch(expected, actual, tolerance) {
63
- const expectedNumber = asFiniteNumber(expected);
64
- const actualNumber = asFiniteNumber(actual);
65
- if (expectedNumber !== undefined && actualNumber !== undefined) {
66
- if (tolerance !== undefined) {
67
- return Math.abs(expectedNumber - actualNumber) <= tolerance;
68
- }
69
- return Math.abs(expectedNumber - actualNumber) <= RELATIVE_EPSILON * Math.max(1, Math.abs(expectedNumber), Math.abs(actualNumber));
70
- }
71
- return expected === actual;
72
- }
73
- /** Match a resolved scalar against the authored value, under the authored tolerance. */
74
- function checkValueAssertion(reference, expected, tolerance, resolved) {
75
- if (expected === undefined || valuesMatch(expected, resolved, tolerance)) {
76
- return undefined;
77
- }
78
- return { reference, reason: "assertion-failed", detail: `expected ${describeValue(expected)} but resolved ${describeValue(resolved)}` };
79
- }
80
- /** Match the resolved citation key against the authored value. The key carries its `idKind:` prefix. */
81
- function checkCitationAssertion(reference, expected, resolved) {
82
- if (expected === undefined || expected === resolved) {
83
- return undefined;
84
- }
85
- return { reference, reason: "assertion-failed", detail: `expected ${String(expected)} but resolved citation ${resolved}` };
86
- }
87
18
  function resolveArtifactValue(reference, snapshot) {
88
19
  const artifact = snapshotEntry(snapshot, reference.path);
89
20
  if (artifact === undefined) {
@@ -111,7 +42,7 @@ function resolveArtifactValue(reference, snapshot) {
111
42
  }
112
43
  else if (locator.rowFilter !== undefined) {
113
44
  const filter = locator.rowFilter;
114
- const matches = rows.filter((row) => row[filter.column] === filter.value);
45
+ const matches = rows.filter((row) => cellMatchesFilterValue(row[filter.column], filter.value));
115
46
  if (matches.length === 0) {
116
47
  return fail(reference, "locator-out-of-range", `no row where ${filter.column} equals ${String(filter.value)}`);
117
48
  }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * The production realization of the reference resolver. It reads the pinned artifact on disk, and it
3
+ * gives the value that the belief points at.
4
+ *
5
+ * The realization holds three layers. Layer one is identity: membership through `snapshotEntry`, and a
6
+ * streamed hash compare with `computeSha256File`. A hash mismatch fails before any parse. Layer two is
7
+ * the host fast path: an in-process parse of a CSV, a TSV, a JSON, or a parquet file at or under the cap.
8
+ * Layer three is the fall-through: an over-cap file or a host parse fault goes to the extraction arm. On any
9
+ * doubt the read falls through, thus correctness never depends on the host parser. An extension that names
10
+ * no tabular format refuses here, because the host decides the format for both arms.
11
+ *
12
+ * A read of the bytes is the expensive part, thus an optional `ArtifactReadCache` outlives one resolver. It
13
+ * holds the streamed hash and the extracted rows against a stat signature. Two tool calls of one analysis
14
+ * share one cache, and each call still binds its own extraction arm with its own auth.
15
+ *
16
+ * The realization calls the shared assert functions in `assert-rules.ts`, and it mirrors the locator walk
17
+ * and the reason choices of `fixture-resolver.ts`. Thus one semantics exists, and the fixture stays the
18
+ * executable specification of the value tier. The two realizations are substitutable behind the seam.
19
+ */
20
+ import { type ReferenceResolver } from "./reference-resolver.js";
21
+ /**
22
+ * One artifact that the host fast path could not read, addressed for the extraction arm. The `hash` pins
23
+ * the exact bytes, thus the arm reads the same artifact that the identity layer verified.
24
+ *
25
+ * `format` carries the reader that the host decided. The arm never derives a reader from the extension,
26
+ * thus the host arm and the sandbox arm can never read one file two ways.
27
+ */
28
+ export interface ExtractionRequest {
29
+ readonly path: string;
30
+ readonly hash: string;
31
+ readonly format: TabularFormat;
32
+ }
33
+ /** The rows that the extraction arm read for one artifact. Downstream the rows share the host path logic. */
34
+ export interface ExtractionArtifact {
35
+ readonly rows: Array<Record<string, string | number>>;
36
+ }
37
+ /**
38
+ * The out-of-process read arm. One `extract` call covers every fall-through artifact of one document
39
+ * pass. The result maps each requested path to its rows. A path that the arm could not read is absent
40
+ * from the map, and the reference at that path fails as `unreadable-artifact`.
41
+ *
42
+ * The arm is a seam, thus a test stubs it. While no realization is wired, a fall-through reference fails
43
+ * with `extraction-unavailable`, and the detail names the absent arm.
44
+ */
45
+ export interface ExtractionArm {
46
+ extract(requests: readonly ExtractionRequest[]): Promise<ReadonlyMap<string, ExtractionArtifact>>;
47
+ }
48
+ /**
49
+ * The disk facts of one artifact that outlive one resolver.
50
+ *
51
+ * `signature` states the bytes that the pass read: the size, the modification time, and the inode. A later
52
+ * pass compares its own stat against it before it trusts anything here, thus a file that changed on disk is
53
+ * read again. `rows` is present only for a clean read, because a read fault is transient and it must not
54
+ * stick to the analysis.
55
+ */
56
+ export interface ArtifactRead {
57
+ readonly signature: string;
58
+ readonly hash: string;
59
+ readonly rows?: Array<Record<string, string | number>>;
60
+ }
61
+ /**
62
+ * The read cache of one analysis. It holds what a read of the bytes costs: the streamed hash, and the rows
63
+ * of a file that the host could not parse in process. Two resolvers of one analysis share one cache, thus a
64
+ * preview and the record that follows it hash one unchanged file one time and start one container.
65
+ *
66
+ * The cache holds no authorization and no session value. Each resolver still binds its own extraction arm
67
+ * over the auth of its own call.
68
+ */
69
+ export interface ArtifactReadCache {
70
+ get(absolutePath: string): ArtifactRead | undefined;
71
+ set(absolutePath: string, read: ArtifactRead): void;
72
+ }
73
+ /** The read caches that the host process holds, one for each recent analysis. */
74
+ export interface ArtifactReadStore {
75
+ forAnalysis(analysisId: string): ArtifactReadCache;
76
+ }
77
+ /**
78
+ * Make the read store of the report path. One host process serves many analyses, thus the store bounds both
79
+ * dimensions: how many analyses it holds, and how many artifacts one analysis holds. A dropped entry costs
80
+ * one read again, and it is never wrong.
81
+ */
82
+ export declare function createArtifactReadStore(): ArtifactReadStore;
83
+ /**
84
+ * The construction deps of the production resolver.
85
+ *
86
+ * `workspaceRoot` and `analysisId` contain the untrusted snapshot path through `resolveWorkspacePath`,
87
+ * the same containment as the preview tool. `cap` gates the cell extraction, and it defaults to 16 MiB.
88
+ * `extractionArm` is optional, because no sandbox realization is wired yet. `readCache` is optional, thus a
89
+ * resolver with no cache reads every artifact itself and its reads die with it.
90
+ */
91
+ export interface ProductionResolverDeps {
92
+ readonly workspaceRoot: string;
93
+ readonly analysisId: string;
94
+ readonly cap?: number;
95
+ readonly extractionArm?: ExtractionArm;
96
+ readonly readCache?: ArtifactReadCache;
97
+ }
98
+ /**
99
+ * The tabular formats that the host fast path reads. The host decides which one a file is, one time, and it
100
+ * carries the decision to the extraction arm. Another extension names no format at all.
101
+ */
102
+ export type TabularFormat = "csv" | "tsv" | "json" | "parquet";
103
+ /**
104
+ * Read one value as a cell, or drop it.
105
+ *
106
+ * A parquet integer column decodes as a `bigint`, thus the coercion narrows it to a number. A `null` or an
107
+ * absent value is not a cell, thus it drops and the row omits the key. The fixture row omits an empty cell
108
+ * the same way. An object or an array is structural doubt, thus it drops too and the format falls through
109
+ * where the caller detects the loss.
110
+ *
111
+ * A non-finite number is not a cell either. A parquet float column holds a `NaN` or an `Infinity`, thus the
112
+ * coercion drops it and the row omits the key. The extraction script (`tasks/extract-values-script.ts`)
113
+ * drops the same value to `None`, thus the host arm and the sandbox arm read the same bytes the same way.
114
+ */
115
+ export declare function coerceCell(value: unknown): string | number | undefined;
116
+ /**
117
+ * Make the production resolver over the workspace root and the optional extraction arm.
118
+ *
119
+ * The resolver holds a per-pass cache. `prepare` groups the references by artifact, reads each file one
120
+ * time, and fills the cache. `resolve` then answers from the cache. A `resolve` with no prior `prepare`
121
+ * still answers, and it writes what it read into the same cache. Thus the cost is one read for each
122
+ * artifact on both paths, and never one read for each reference.
123
+ */
124
+ export declare function createProductionResolver(deps: ProductionResolverDeps): ReferenceResolver;