@inflexa-ai/harness 0.28.0 → 0.29.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 (87) hide show
  1. package/dist/app/data-profile-orientation.d.ts +52 -27
  2. package/dist/app/data-profile-orientation.js +331 -92
  3. package/dist/app/data-profile-view.d.ts +70 -0
  4. package/dist/app/data-profile-view.js +123 -0
  5. package/dist/app/synthesize-run.js +1 -1
  6. package/dist/contracts/data-profile.d.ts +276 -25
  7. package/dist/contracts/index.d.ts +3 -1
  8. package/dist/contracts/index.js +1 -0
  9. package/dist/contracts/profile-vocabulary.d.ts +103 -0
  10. package/dist/contracts/profile-vocabulary.js +449 -0
  11. package/dist/contracts/target-dossier.d.ts +21 -21
  12. package/dist/execution/artifact-registration.js +9 -0
  13. package/dist/execution/artifact-registry.d.ts +14 -0
  14. package/dist/execution/input-signature.d.ts +16 -3
  15. package/dist/execution/input-signature.js +0 -0
  16. package/dist/execution/post-step-pipeline.d.ts +6 -4
  17. package/dist/execution/post-step-pipeline.js +18 -9
  18. package/dist/execution/staged-input.d.ts +4 -4
  19. package/dist/index.d.ts +5 -1
  20. package/dist/index.js +7 -0
  21. package/dist/input-scan/clustering.d.ts +63 -0
  22. package/dist/input-scan/clustering.js +208 -0
  23. package/dist/input-scan/companions.d.ts +30 -0
  24. package/dist/input-scan/companions.js +138 -0
  25. package/dist/input-scan/decoder/container_readout.py +171 -0
  26. package/dist/input-scan/detect-sets.d.ts +24 -0
  27. package/dist/input-scan/detect-sets.js +279 -0
  28. package/dist/input-scan/enrich.d.ts +62 -19
  29. package/dist/input-scan/enrich.js +132 -187
  30. package/dist/input-scan/formats.d.ts +13 -5
  31. package/dist/input-scan/formats.js +13 -5
  32. package/dist/input-scan/index.d.ts +10 -4
  33. package/dist/input-scan/index.js +7 -4
  34. package/dist/input-scan/markers.d.ts +21 -0
  35. package/dist/input-scan/markers.js +89 -0
  36. package/dist/input-scan/menu.d.ts +127 -0
  37. package/dist/input-scan/menu.js +0 -0
  38. package/dist/input-scan/quarantine.d.ts +17 -0
  39. package/dist/input-scan/quarantine.js +69 -0
  40. package/dist/input-scan/readout-budget.d.ts +32 -0
  41. package/dist/input-scan/readout-budget.js +61 -0
  42. package/dist/input-scan/readout.d.ts +33 -0
  43. package/dist/input-scan/readout.js +336 -0
  44. package/dist/input-scan/scan.d.ts +5 -4
  45. package/dist/input-scan/scan.js +5 -5
  46. package/dist/input-scan/set-types.d.ts +209 -0
  47. package/dist/input-scan/set-types.js +15 -0
  48. package/dist/input-scan/templates.d.ts +93 -0
  49. package/dist/input-scan/templates.js +369 -0
  50. package/dist/input-scan/tokens.d.ts +94 -0
  51. package/dist/input-scan/tokens.js +267 -0
  52. package/dist/input-scan/tuning.d.ts +55 -0
  53. package/dist/input-scan/tuning.js +55 -0
  54. package/dist/input-scan/types.d.ts +2 -2
  55. package/dist/prompts/conversation.d.ts +1 -1
  56. package/dist/prompts/conversation.js +8 -6
  57. package/dist/prompts/report-session.d.ts +1 -1
  58. package/dist/prompts/report-session.js +3 -2
  59. package/dist/prompts/sandbox/data-profiler.d.ts +10 -1
  60. package/dist/prompts/sandbox/data-profiler.js +197 -53
  61. package/dist/prompts/sandbox-standards.d.ts +1 -1
  62. package/dist/prompts/sandbox-standards.js +10 -7
  63. package/dist/schemas/data-profile-schemas.d.ts +943 -80
  64. package/dist/schemas/data-profile-schemas.js +300 -115
  65. package/dist/state/data-profile.d.ts +1 -1
  66. package/dist/state/index.d.ts +1 -1
  67. package/dist/state/vector-store.d.ts +13 -0
  68. package/dist/state/vector-store.js +8 -0
  69. package/dist/tasks/data-profile-absorb.d.ts +78 -0
  70. package/dist/tasks/data-profile-absorb.js +285 -0
  71. package/dist/tasks/data-profile-index.d.ts +34 -25
  72. package/dist/tasks/data-profile-index.js +160 -59
  73. package/dist/tasks/data-profile-resolve.d.ts +72 -0
  74. package/dist/tasks/data-profile-resolve.js +639 -0
  75. package/dist/tasks/data-profile.d.ts +16 -5
  76. package/dist/tasks/data-profile.js +270 -131
  77. package/dist/tools/research/inspect-data-profile.d.ts +48 -22
  78. package/dist/tools/research/inspect-data-profile.js +73 -54
  79. package/dist/tools/workspace/scan-inputs.d.ts +4 -4
  80. package/dist/tools/workspace/scan-inputs.js +13 -14
  81. package/dist/tools/workspace/workspace-search.d.ts +11 -2
  82. package/dist/tools/workspace/workspace-search.js +44 -16
  83. package/dist/workflows/sandbox-step.js +36 -6
  84. package/dist/workflows/target-assessment/phase4-assemble.d.ts +21 -21
  85. package/package.json +5 -3
  86. package/dist/input-scan/coverage.d.ts +0 -22
  87. package/dist/input-scan/coverage.js +0 -85
@@ -4,8 +4,8 @@
4
4
  * Runs in the harness process over the workspace read seam, which is
5
5
  * sandbox-independent: the walk touches names and metadata, and format detection
6
6
  * compares a bounded byte prefix against a table. Neither is a decode, so neither
7
- * needs a container. Only the per-shape header readout (`enrich.ts`) runs a decoder,
8
- * and it runs in the sandbox.
7
+ * needs a container. Only a footer-indexed container reaches the sandbox, and only
8
+ * through the per-shape header readout (`enrich.ts`).
9
9
  *
10
10
  * The scan is the SOLE enumeration pass. Before it, the profiler agent discovered
11
11
  * structure by issuing one command per input file, so its cost scaled with file
@@ -19,8 +19,8 @@ import type { InputScan, InputScanManifest, ScannedFile } from "./types.js";
19
19
  *
20
20
  * Header decode is O(shapes), but the walk and its per-file prefix read are O(files),
21
21
  * and that arm needs a stated ceiling rather than an implicit one. 100k files is ~30s
22
- * of stat-and-prefix work against a 20-minute profile deadline, and two orders of
23
- * magnitude above the largest tree the platform has seen (3513). Past it the scan
22
+ * of stat-and-prefix work against a 20-minute profile deadline, and well above the
23
+ * largest input trees the platform is expected to stage. Past it the scan
24
24
  * stops and SAYS it stopped: a silently sampled manifest would describe a fraction of
25
25
  * the tree while reading as a description of all of it, which is the failure mode this
26
26
  * capability exists to remove.
@@ -39,6 +39,7 @@ export interface ScanInputTreeArgs {
39
39
  export declare function buildManifest(root: string, files: readonly ScannedFile[], truncated: boolean, limit?: number): InputScan;
40
40
  /** Walk a staged input tree and observe its shapes. No model, no container. */
41
41
  export declare function scanInputTree(args: ScanInputTreeArgs): Promise<InputScan>;
42
+ export declare function formatBytes(bytes: number): string;
42
43
  /**
43
44
  * Render a manifest for a briefing or a tool result.
44
45
  *
@@ -4,8 +4,8 @@
4
4
  * Runs in the harness process over the workspace read seam, which is
5
5
  * sandbox-independent: the walk touches names and metadata, and format detection
6
6
  * compares a bounded byte prefix against a table. Neither is a decode, so neither
7
- * needs a container. Only the per-shape header readout (`enrich.ts`) runs a decoder,
8
- * and it runs in the sandbox.
7
+ * needs a container. Only a footer-indexed container reaches the sandbox, and only
8
+ * through the per-shape header readout (`enrich.ts`).
9
9
  *
10
10
  * The scan is the SOLE enumeration pass. Before it, the profiler agent discovered
11
11
  * structure by issuing one command per input file, so its cost scaled with file
@@ -19,8 +19,8 @@ import { observeShapes } from "./shapes.js";
19
19
  *
20
20
  * Header decode is O(shapes), but the walk and its per-file prefix read are O(files),
21
21
  * and that arm needs a stated ceiling rather than an implicit one. 100k files is ~30s
22
- * of stat-and-prefix work against a 20-minute profile deadline, and two orders of
23
- * magnitude above the largest tree the platform has seen (3513). Past it the scan
22
+ * of stat-and-prefix work against a 20-minute profile deadline, and well above the
23
+ * largest input trees the platform is expected to stage. Past it the scan
24
24
  * stops and SAYS it stopped: a silently sampled manifest would describe a fraction of
25
25
  * the tree while reading as a description of all of it, which is the failure mode this
26
26
  * capability exists to remove.
@@ -95,7 +95,7 @@ export async function scanInputTree(args) {
95
95
  const { files, truncated } = await walk(args);
96
96
  return buildManifest(args.root, files, truncated, limit);
97
97
  }
98
- function formatBytes(bytes) {
98
+ export function formatBytes(bytes) {
99
99
  if (bytes < 1024)
100
100
  return `${bytes} B`;
101
101
  const units = ["KB", "MB", "GB", "TB"];
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Detected-set vocabulary.
3
+ *
4
+ * A **set** is a mechanical fact: these paths instantiate one template. A **slot** is
5
+ * a position in that template whose token varies, reported with its class, its
6
+ * distinct-value count, and a bounded sample of the values themselves — a count alone
7
+ * cannot tell an entity identifier from a categorical label from a shard index, and
8
+ * those readings imply entirely different groupings.
9
+ *
10
+ * Nothing here decides a grouping, and nothing here is named `groups` or `dimensions`:
11
+ * that half belongs to the profiler agent, and a result an agent could copy into its
12
+ * submission would make its central judgement invisible (see the input-scan-manifest
13
+ * spec).
14
+ */
15
+ import type { FormatCount, UnstructuredEntry } from "./types.js";
16
+ import type { SlotTokenClass } from "./tokens.js";
17
+ /** Why a file never reached the menu. */
18
+ export type QuarantineReason = "os-junk" | "editor-temp" | "partial-download" | "atomic-write-temp";
19
+ export interface QuarantineReasonCount {
20
+ readonly reason: QuarantineReason;
21
+ readonly count: number;
22
+ }
23
+ /**
24
+ * Quarantine is visible, never silent: a wrongly excluded file has to be discoverable
25
+ * by the agent and the user, so the counts and a bounded path sample are reported.
26
+ */
27
+ export interface QuarantineSummary {
28
+ readonly count: number;
29
+ readonly totalBytes: number;
30
+ readonly reasons: readonly QuarantineReasonCount[];
31
+ readonly sample: readonly string[];
32
+ }
33
+ /** A helper file that carries no meaning apart from the data file it serves. */
34
+ export interface CompanionFile {
35
+ readonly path: string;
36
+ /** The suffix that identified it — `.tbi`, `.bai`, `.md5`. */
37
+ readonly suffix: string;
38
+ readonly size: number;
39
+ }
40
+ /**
41
+ * A data file plus its companions — the logical unit the pipeline mines and counts.
42
+ *
43
+ * Membership counts logical units, so a variant file and its index are one member, and
44
+ * "N files, M indexed" becomes a computed completeness rather than a claim.
45
+ */
46
+ export interface MemberFile {
47
+ readonly path: string;
48
+ readonly name: string;
49
+ readonly size: number;
50
+ readonly format: string;
51
+ readonly wrapper?: string;
52
+ readonly companions: readonly CompanionFile[];
53
+ }
54
+ export interface SetMember extends MemberFile {
55
+ /** Companion suffixes the rest of the set carries and this member does not. */
56
+ readonly missingCompanions: readonly string[];
57
+ }
58
+ export interface IncompleteMember {
59
+ readonly path: string;
60
+ readonly missingCompanions: readonly string[];
61
+ }
62
+ /**
63
+ * Companion coverage across a set, reported per member rather than averaged: an
64
+ * average hides the one member whose index is missing, which is exactly the fact a
65
+ * downstream step will fail on.
66
+ */
67
+ export interface SetCompleteness {
68
+ /** Suffixes enough of the set carries that their absence is a gap, not a variation. */
69
+ readonly expectedCompanions: readonly string[];
70
+ readonly completeMembers: number;
71
+ readonly incompleteMembers: number;
72
+ readonly incompleteSample: readonly IncompleteMember[];
73
+ }
74
+ export type SlotLocation = "directory" | "name";
75
+ /**
76
+ * A varying position in a set's path template.
77
+ *
78
+ * `sampleValues` is bounded and normative — it is the material a grouping decision
79
+ * rests on. The complete value set stays on {@link DetectedSets.slotValues},
80
+ * host-side, for arithmetic a bounded sample cannot do.
81
+ */
82
+ export interface SetSlot {
83
+ /** Unique within one scan, so a cross-check can name the slot it links to. */
84
+ readonly id: string;
85
+ readonly location: SlotLocation;
86
+ /** Directory segment index, or token index within the name. */
87
+ readonly index: number;
88
+ readonly tokenClass: SlotTokenClass;
89
+ readonly width?: number;
90
+ readonly minLength?: number;
91
+ readonly maxLength?: number;
92
+ readonly skeleton?: string;
93
+ /** Literal text fused to the front of the token, recovered from what every value shares. */
94
+ readonly prefix?: string;
95
+ readonly suffix?: string;
96
+ readonly distinctValues: number;
97
+ readonly sampleValues: readonly string[];
98
+ /** The slot this one repeats. A token in both a directory and the stem is ONE identity, not two. */
99
+ readonly sameAsSlot?: string;
100
+ /** Members whose two positions disagreed, when the link was made despite them. */
101
+ readonly crossCheckMismatches?: number;
102
+ }
103
+ /** A template rendered as a sequence: concatenating it reproduces {@link DetectedSet.pathTemplate}. */
104
+ export type TemplateSegment = {
105
+ readonly kind: "literal";
106
+ readonly text: string;
107
+ } | {
108
+ readonly kind: "slot";
109
+ readonly slotId: string;
110
+ };
111
+ /**
112
+ * How a set came to be.
113
+ *
114
+ * A consumer has to be able to tell these apart: a `catch-all` set is evidence that
115
+ * the same directory shape repeats, not that the filenames agree, and reading it as a
116
+ * name-structure fact would overstate what the scan established.
117
+ */
118
+ export type SetOrigin = "marker" | "mined" | "prefix" | "family" | "catch-all";
119
+ /** Compression wrappers observed across a set's members. `none` names the uncompressed. */
120
+ export interface WrapperCount {
121
+ readonly wrapper: string;
122
+ readonly count: number;
123
+ }
124
+ export interface DetectedSet {
125
+ /** Stable within one scan (`set-1`, `set-2`, …). */
126
+ readonly id: string;
127
+ readonly origin: SetOrigin;
128
+ /** The catalogue entry that claimed this subtree, when `origin` is `marker`. */
129
+ readonly marker?: string;
130
+ readonly pathTemplate: string;
131
+ readonly segments: readonly TemplateSegment[];
132
+ /** Logical units — a data file and its companions count once. */
133
+ readonly memberCount: number;
134
+ /** Files, companions included. */
135
+ readonly fileCount: number;
136
+ readonly totalBytes: number;
137
+ /**
138
+ * Format and wrapper disagreement inside a set is a property OF the set, never a
139
+ * partition key: members that differ only in compression are one set that says so.
140
+ */
141
+ readonly formats: readonly FormatCount[];
142
+ readonly wrappers: readonly WrapperCount[];
143
+ readonly slots: readonly SetSlot[];
144
+ readonly completeness: SetCompleteness;
145
+ readonly examplePaths: readonly string[];
146
+ /** Complete membership. Host-side: the bounded projection is everything above. */
147
+ readonly members: readonly SetMember[];
148
+ }
149
+ /**
150
+ * Files no set speaks for, in aggregate.
151
+ *
152
+ * Never one set per file: a tree of arbitrarily named files would otherwise produce a
153
+ * set count proportional to the file count. Whether these are notable singletons worth
154
+ * describing or an unclassified remainder is the agent's determination.
155
+ */
156
+ export interface LeftoverFiles {
157
+ readonly memberCount: number;
158
+ /** Members plus the companions riding on them, so it adds up against `keptFileCount`. */
159
+ readonly fileCount: number;
160
+ readonly totalBytes: number;
161
+ readonly sample: readonly UnstructuredEntry[];
162
+ }
163
+ export interface SetRepresentative {
164
+ readonly setId: string;
165
+ readonly path: string;
166
+ }
167
+ /**
168
+ * Which files a header readout should open.
169
+ *
170
+ * One representative per set plus every leftover: within a set the members are alike
171
+ * by construction, so a readout per file buys nothing and costs the enrichment budget
172
+ * this pipeline exists to bound.
173
+ */
174
+ export interface ReadoutSelection {
175
+ readonly representatives: readonly SetRepresentative[];
176
+ /** Leftover paths — the files no set speaks for, each read on its own. Bounded. */
177
+ readonly individual: readonly string[];
178
+ /**
179
+ * Leftovers past that bound. Reported rather than dropped: a tree of thousands of
180
+ * one-off files would otherwise buy an unbounded read budget, and an agent shown a
181
+ * header for some leftovers and not others has to be told which.
182
+ */
183
+ readonly individualElided: number;
184
+ }
185
+ export interface DetectedSets {
186
+ readonly fileCount: number;
187
+ /** Files that survived quarantine — the denominator coverage is measured against. */
188
+ readonly keptFileCount: number;
189
+ readonly coverage: number;
190
+ readonly quarantine: QuarantineSummary;
191
+ readonly sets: readonly DetectedSet[];
192
+ readonly leftovers: LeftoverFiles;
193
+ /** Complete leftover membership. Host-side, for the same reason as {@link DetectedSet.members}. */
194
+ readonly leftoverMembers: readonly MemberFile[];
195
+ readonly readout: ReadoutSelection;
196
+ /**
197
+ * Complete value sets, keyed by slot id. Host-side only: completeness arithmetic,
198
+ * cross-set identity checks, and the index build need every value, while anything
199
+ * rendered or persisted carries {@link SetSlot.sampleValues}.
200
+ */
201
+ readonly slotValues: ReadonlyMap<string, readonly string[]>;
202
+ /**
203
+ * Per slot id, the value each member of that slot's set carries, aligned to
204
+ * {@link DetectedSet.members}. Host-side only, and the material a split resolves
205
+ * against: partitioning a set by one of its slots is a lookup here, never a
206
+ * re-tokenisation of the member's name.
207
+ */
208
+ readonly memberSlotValues: ReadonlyMap<string, readonly string[]>;
209
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Detected-set vocabulary.
3
+ *
4
+ * A **set** is a mechanical fact: these paths instantiate one template. A **slot** is
5
+ * a position in that template whose token varies, reported with its class, its
6
+ * distinct-value count, and a bounded sample of the values themselves — a count alone
7
+ * cannot tell an entity identifier from a categorical label from a shard index, and
8
+ * those readings imply entirely different groupings.
9
+ *
10
+ * Nothing here decides a grouping, and nothing here is named `groups` or `dimensions`:
11
+ * that half belongs to the profiler agent, and a result an agent could copy into its
12
+ * submission would make its central judgement invisible (see the input-scan-manifest
13
+ * spec).
14
+ */
15
+ export {};
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Stage 3 — name-template mining within one directory context.
3
+ *
4
+ * Literal versus slot is decided by per-position distinct counts: a position whose
5
+ * token is the same in every member is literal text, and one that varies is a slot.
6
+ * Groups that differ in exactly one position, or only in extension, merge — variance
7
+ * inside a set is a property of the set, never a partition key.
8
+ *
9
+ * Proliferation is bounded three ways, because a template per file is the same failure
10
+ * as no templates at all: a prefix trie claims residual singletons that share literal
11
+ * text, a family collapse claims singletons that share only a token-kind sequence
12
+ * (one template for the family costs less than one template each), and a catch-all
13
+ * claims the rest where the repetition across directories is itself the structure.
14
+ */
15
+ import type { MemberFile, SlotLocation } from "./set-types.js";
16
+ import type { NameToken, SlotTokenClass, TokenKind } from "./tokens.js";
17
+ /** A member with the directory-slot values of the context it was found in. */
18
+ export interface ContextFile extends MemberFile {
19
+ readonly varValues: readonly string[];
20
+ }
21
+ export interface MinedItem {
22
+ readonly file: ContextFile;
23
+ readonly tokens: readonly NameToken[];
24
+ readonly suffix: string;
25
+ readonly skeleton: string;
26
+ }
27
+ export type MinedKind = "tokens" | "prefix" | "family" | "catch-all";
28
+ export interface MinedGroup {
29
+ readonly kind: MinedKind;
30
+ readonly tokenKinds: readonly TokenKind[];
31
+ /** The shared literal head, when the group was claimed by prefix mining. */
32
+ readonly prefixTokens: readonly NameToken[];
33
+ readonly suffix: string;
34
+ /** Extension chains observed across the members, with counts. */
35
+ readonly suffixes: Map<string, number>;
36
+ items: MinedItem[];
37
+ distinct?: number[];
38
+ }
39
+ /** A slot before the assembly stamps it with an id. */
40
+ export interface DraftSlot {
41
+ readonly location: SlotLocation;
42
+ readonly index: number;
43
+ readonly tokenClass: SlotTokenClass;
44
+ readonly width?: number;
45
+ readonly minLength?: number;
46
+ readonly maxLength?: number;
47
+ readonly skeleton?: string;
48
+ readonly prefix?: string;
49
+ readonly suffix?: string;
50
+ readonly distinctValues: number;
51
+ readonly sampleValues: readonly string[];
52
+ /** The complete value set — bounded projection is `sampleValues`. */
53
+ readonly values: readonly string[];
54
+ /** The value each member carries, aligned to the order the raw values arrived in. */
55
+ readonly memberValues: readonly string[];
56
+ sameAs?: number;
57
+ crossCheckMismatches?: number;
58
+ }
59
+ export type DraftSegment = {
60
+ readonly kind: "literal";
61
+ readonly text: string;
62
+ } | {
63
+ readonly kind: "slot";
64
+ readonly slot: number;
65
+ };
66
+ /**
67
+ * Fold what is left of a cross-directory context into one set.
68
+ *
69
+ * Where the same directory shape repeats, that repetition is the structure, and the
70
+ * residual names inside it are one set whatever they are called. Extension
71
+ * disagreement is carried as the format census, never used to split.
72
+ */
73
+ export declare function catchAll(residue: readonly MinedItem[], hasDirectorySlot: boolean): {
74
+ sets: MinedGroup[];
75
+ rest: MinedItem[];
76
+ };
77
+ /** Mine one directory context: every file whose directory path instantiates one template. */
78
+ export declare function mineContext(files: readonly ContextFile[]): {
79
+ sets: MinedGroup[];
80
+ residue: MinedItem[];
81
+ };
82
+ /** Describe one varying position: its class, its cardinality, and a bounded value sample. */
83
+ export declare function describeSlot(rawValues: readonly string[], location: SlotLocation, index: number): DraftSlot;
84
+ /** The template token a slot renders as. */
85
+ export declare function slotToken(slot: DraftSlot): string;
86
+ /**
87
+ * The name half of a set's template: its literal text, its slots, and the order they
88
+ * appear in. Directory slots are prepended by the assembly, which knows the context.
89
+ */
90
+ export declare function describeGroup(group: MinedGroup): {
91
+ slots: DraftSlot[];
92
+ segments: DraftSegment[];
93
+ };