@wrenautomation/raven 0.10.0 → 0.12.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.
package/README.md CHANGED
@@ -15,7 +15,9 @@ Three calls, one record each:
15
15
  | `review` | what a round came to (counts, found lines with their dates, the extractor's verdict and gap per read, the steps' gaps, the sample check, notes) | the edge: `stop`, `again` (a new round from plan) or `back` (rerun one step), with why. The budget is shown, never enforced here: the runner parks past it |
16
16
 
17
17
  Ask kinds: `web`, `video`, `channel`, `person`, `site`. Each has a default plan file
18
- (prompts, sources, budget, and `age`: one sentence on how much a source's age counts). Copy one,
18
+ (prompts, sources, budget, `age`: one sentence on how much a source's age counts, and `tree`: the
19
+ facets a round's query tree covers and `thin`, the new hits under which a try falls through to the
20
+ next). Copy one,
19
21
  tune it, keep it beside your ledger (`weaver learn`): that is where a run learns. Raven never
20
22
  loops; the runner takes the edge.
21
23
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { fill } from "./model.js";
2
2
  export { mergeProposals, type PlanInput, plan, propose, proposePrompt } from "./plan.js";
3
- export { defaultPlanFile, PLAN_KINDS } from "./plans/index.js";
3
+ export { ageOf, defaultPlanFile, PLAN_KINDS, TREE, treeOf } from "./plans/index.js";
4
4
  export { renderHits, renderYield } from "./render.js";
5
5
  export { review, reviewPrompt } from "./review.js";
6
6
  export { dedupeHits, triage, triagePrompt } from "./triage.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { fill } from "./model.js";
2
2
  export { mergeProposals, plan, propose, proposePrompt } from "./plan.js";
3
- export { defaultPlanFile, PLAN_KINDS } from "./plans/index.js";
3
+ export { ageOf, defaultPlanFile, PLAN_KINDS, TREE, treeOf } from "./plans/index.js";
4
4
  export { renderHits, renderYield } from "./render.js";
5
5
  export { review, reviewPrompt } from "./review.js";
6
6
  export { dedupeHits, triage, triagePrompt } from "./triage.js";
@@ -2,9 +2,16 @@
2
2
  * The default plan file per ask kind. A copy of one, tuned and stored beside a ledger, is how
3
3
  * a run learns: the recipe changes, raven does not. `raven plans <kind>` prints one to start from.
4
4
  */
5
- import { type AskKind, type PlanFile } from "../types.js";
5
+ import { type AskKind, type PlanFile, type TreeGuide } from "../types.js";
6
+ /**
7
+ * The five sides a researcher covers before the reads start. One tree per round; the agent
8
+ * fills each facet with tries, in order of what it expects to work.
9
+ */
10
+ export declare const TREE: TreeGuide;
6
11
  /** The default plan file for a kind, validated, as a fresh copy. */
7
12
  export declare function defaultPlanFile(kind: AskKind): PlanFile;
8
- /** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". */
13
+ /** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". Version 6: `tree`, the query tree's guide. */
9
14
  export declare const ageOf: (planFile: PlanFile) => string | undefined;
15
+ /** The plan file's guide for a query tree; a stored file from before version 6 takes its kind's default. */
16
+ export declare const treeOf: (planFile: PlanFile) => TreeGuide;
10
17
  export declare const PLAN_KINDS: AskKind[];
@@ -2,7 +2,7 @@
2
2
  * The default plan file per ask kind. A copy of one, tuned and stored beside a ledger, is how
3
3
  * a run learns: the recipe changes, raven does not. `raven plans <kind>` prints one to start from.
4
4
  */
5
- import { PlanFile as PlanFileShape } from "../types.js";
5
+ import { PlanFile as PlanFileShape, } from "../types.js";
6
6
  const SHAPE_QUERIES = `Return ONLY a JSON object, no prose, exactly this shape:
7
7
  {"queries": [{"terms": "...", "why": "..."}]}`;
8
8
  const SHAPE_HITS = `Return ONLY a JSON object, no prose, exactly this shape:
@@ -44,10 +44,27 @@ Checked (a sample of the kept findings, each against its document):
44
44
  {checks}
45
45
  Notes:
46
46
  {notes}`;
47
+ /**
48
+ * The five sides a researcher covers before the reads start. One tree per round; the agent
49
+ * fills each facet with tries, in order of what it expects to work.
50
+ */
51
+ export const TREE = {
52
+ facets: [
53
+ { name: "number", why: "a figure: a rate, a price, a count, a date" },
54
+ { name: "how", why: "how it is done: a method, a step list, a tool" },
55
+ { name: "who", why: "who does it or buys it, in their own words" },
56
+ { name: "counter", why: "the case against: what fails, who says no" },
57
+ {
58
+ name: "primary",
59
+ why: "the source itself: a study, a filing, a transcript, the maker's own page",
60
+ },
61
+ ],
62
+ thin: 3,
63
+ };
47
64
  const web = {
48
65
  id: "raven/web",
49
66
  kind: "web",
50
- version: 5,
67
+ version: 6,
51
68
  propose: `You plan web searches for one research ask.
52
69
 
53
70
  ${SHAPE_QUERIES}
@@ -74,12 +91,13 @@ Hits:
74
91
  review: REVIEW,
75
92
  sources: ["searxng", "exa", "google"],
76
93
  budget: { queries: 3, reads: 6, rounds: 3, checks: 3 },
94
+ tree: TREE,
77
95
  age: "Prices, tools and numbers that move: prefer the last two years. A principle or a method can be old.",
78
96
  };
79
97
  const video = {
80
98
  id: "raven/video",
81
99
  kind: "video",
82
- version: 5,
100
+ version: 6,
83
101
  propose: `You plan video searches for one research ask: talks, walkthroughs, interviews and reviews on YouTube and podcast feeds.
84
102
 
85
103
  ${SHAPE_QUERIES}
@@ -106,12 +124,13 @@ Hits:
106
124
  review: REVIEW,
107
125
  sources: ["youtube", "podcasts"],
108
126
  budget: { queries: 3, reads: 4, rounds: 2, checks: 3 },
127
+ tree: TREE,
109
128
  age: "Tools and platforms: prefer the last two years. A talk on a principle can be old.",
110
129
  };
111
130
  const channel = {
112
131
  id: "raven/channel",
113
132
  kind: "channel",
114
- version: 5,
133
+ version: 6,
115
134
  propose: `You plan searches that find the people and channels worth following for one research ask: creators, newsletters, podcasts, forums.
116
135
 
117
136
  ${SHAPE_QUERIES}
@@ -136,12 +155,13 @@ Hits:
136
155
  review: REVIEW,
137
156
  sources: ["searxng", "youtube", "exa"],
138
157
  budget: { queries: 3, reads: 6, rounds: 2, checks: 3 },
158
+ tree: TREE,
139
159
  age: "A channel that has not posted in the last year counts for little.",
140
160
  };
141
161
  const person = {
142
162
  id: "raven/person",
143
163
  kind: "person",
144
- version: 5,
164
+ version: 6,
145
165
  propose: `You plan searches about one person or company for one research ask: what they do, what they said, what others say about them.
146
166
 
147
167
  ${SHAPE_QUERIES}
@@ -168,12 +188,13 @@ Hits:
168
188
  review: REVIEW,
169
189
  sources: ["searxng", "exa", "linkedin", "google"],
170
190
  budget: { queries: 4, reads: 6, rounds: 2, checks: 3 },
191
+ tree: TREE,
171
192
  age: "What they do now: prefer the latest pages. Their history can be old.",
172
193
  };
173
194
  const site = {
174
195
  id: "raven/site",
175
196
  kind: "site",
176
- version: 5,
197
+ version: 6,
177
198
  propose: `You plan searches inside one website for one research ask. Every query runs on {site} only.
178
199
 
179
200
  ${SHAPE_QUERIES}
@@ -199,6 +220,7 @@ Hits:
199
220
  review: REVIEW,
200
221
  sources: ["sitemap", "searxng", "fetch"],
201
222
  budget: { queries: 4, reads: 8, rounds: 2, checks: 3 },
223
+ tree: TREE,
202
224
  age: "When two pages of the site disagree, the later one counts.",
203
225
  };
204
226
  const DEFAULTS = { web, video, channel, person, site };
@@ -206,7 +228,9 @@ const DEFAULTS = { web, video, channel, person, site };
206
228
  export function defaultPlanFile(kind) {
207
229
  return PlanFileShape.parse(structuredClone(DEFAULTS[kind]));
208
230
  }
209
- /** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". */
231
+ /** The plan file's word on age; a stored file from before version 4 takes its kind's default. Version 5: the review no longer says "at most". Version 6: `tree`, the query tree's guide. */
210
232
  export const ageOf = (planFile) => planFile.age ?? DEFAULTS[planFile.kind].age;
233
+ /** The plan file's guide for a query tree; a stored file from before version 6 takes its kind's default. */
234
+ export const treeOf = (planFile) => planFile.tree ?? DEFAULTS[planFile.kind].tree;
211
235
  export const PLAN_KINDS = Object.keys(DEFAULTS);
212
236
  //# sourceMappingURL=index.js.map
package/dist/types.d.ts CHANGED
@@ -47,6 +47,8 @@ export declare const Query: z.ZodObject<{
47
47
  terms: z.ZodString;
48
48
  site: z.ZodOptional<z.ZodString>;
49
49
  why: z.ZodString;
50
+ facet: z.ZodOptional<z.ZodString>;
51
+ tier: z.ZodOptional<z.ZodNumber>;
50
52
  from: z.ZodEnum<{
51
53
  ai: "ai";
52
54
  human: "human";
@@ -72,9 +74,55 @@ export declare const Proposal: z.ZodObject<{
72
74
  }>;
73
75
  terms: z.ZodString;
74
76
  why: z.ZodString;
77
+ facet: z.ZodOptional<z.ZodString>;
78
+ tier: z.ZodOptional<z.ZodNumber>;
75
79
  }, z.core.$strip>>;
76
80
  }, z.core.$strip>;
77
81
  export type Proposal = z.infer<typeof Proposal>;
82
+ /** One query as a leaf of the tree: what a person would type, and why. */
83
+ export declare const Leaf: z.ZodObject<{
84
+ terms: z.ZodString;
85
+ why: z.ZodString;
86
+ site: z.ZodOptional<z.ZodString>;
87
+ }, z.core.$strip>;
88
+ export type Leaf = z.infer<typeof Leaf>;
89
+ /**
90
+ * One side of the ask a researcher covers: a number, a how, a who, a counter-view, a primary
91
+ * source. `tries` are its alternatives in order: the first runs; the next runs only when the
92
+ * one before it yielded thin (fewer new hits than the guide's `thin`), or when the agent asks.
93
+ */
94
+ export declare const Facet: z.ZodObject<{
95
+ name: z.ZodString;
96
+ why: z.ZodString;
97
+ tries: z.ZodArray<z.ZodArray<z.ZodObject<{
98
+ terms: z.ZodString;
99
+ why: z.ZodString;
100
+ site: z.ZodOptional<z.ZodString>;
101
+ }, z.core.$strip>>>;
102
+ }, z.core.$strip>;
103
+ export type Facet = z.infer<typeof Facet>;
104
+ /** The fan-out for one round: the facets, each with its tries. The agent writes it; weaver runs it. */
105
+ export declare const QueryTree: z.ZodObject<{
106
+ facets: z.ZodArray<z.ZodObject<{
107
+ name: z.ZodString;
108
+ why: z.ZodString;
109
+ tries: z.ZodArray<z.ZodArray<z.ZodObject<{
110
+ terms: z.ZodString;
111
+ why: z.ZodString;
112
+ site: z.ZodOptional<z.ZodString>;
113
+ }, z.core.$strip>>>;
114
+ }, z.core.$strip>>;
115
+ }, z.core.$strip>;
116
+ export type QueryTree = z.infer<typeof QueryTree>;
117
+ /** The plan file's guide for a tree: the facets a tree of this kind covers, and what thin means. A guide, not a cap: a tree may add facets; one it leaves out is a warning. */
118
+ export declare const TreeGuide: z.ZodObject<{
119
+ facets: z.ZodArray<z.ZodObject<{
120
+ name: z.ZodString;
121
+ why: z.ZodString;
122
+ }, z.core.$strip>>;
123
+ thin: z.ZodNumber;
124
+ }, z.core.$strip>;
125
+ export type TreeGuide = z.infer<typeof TreeGuide>;
78
126
  export declare const Budget: z.ZodObject<{
79
127
  queries: z.ZodNumber;
80
128
  reads: z.ZodNumber;
@@ -109,6 +157,13 @@ export declare const PlanFile: z.ZodObject<{
109
157
  checks: z.ZodDefault<z.ZodNumber>;
110
158
  }, z.core.$strip>;
111
159
  age: z.ZodOptional<z.ZodString>;
160
+ tree: z.ZodOptional<z.ZodObject<{
161
+ facets: z.ZodArray<z.ZodObject<{
162
+ name: z.ZodString;
163
+ why: z.ZodString;
164
+ }, z.core.$strip>>;
165
+ thin: z.ZodNumber;
166
+ }, z.core.$strip>>;
112
167
  }, z.core.$strip>;
113
168
  export type PlanFile = z.infer<typeof PlanFile>;
114
169
  /** What a source, channel or proposer yielded before. Raven reads it; wren or the files ledger writes it. */
@@ -168,6 +223,8 @@ export declare const Plan: z.ZodObject<{
168
223
  terms: z.ZodString;
169
224
  site: z.ZodOptional<z.ZodString>;
170
225
  why: z.ZodString;
226
+ facet: z.ZodOptional<z.ZodString>;
227
+ tier: z.ZodOptional<z.ZodNumber>;
171
228
  from: z.ZodEnum<{
172
229
  ai: "ai";
173
230
  human: "human";
@@ -221,8 +278,8 @@ export type Triage = z.infer<typeof Triage>;
221
278
  export declare const Verdict: z.ZodObject<{
222
279
  url: z.ZodString;
223
280
  quality: z.ZodEnum<{
224
- rich: "rich";
225
281
  thin: "thin";
282
+ rich: "rich";
226
283
  off: "off";
227
284
  empty: "empty";
228
285
  }>;
@@ -261,8 +318,8 @@ export declare const Round: z.ZodObject<{
261
318
  verdicts: z.ZodDefault<z.ZodArray<z.ZodObject<{
262
319
  url: z.ZodString;
263
320
  quality: z.ZodEnum<{
264
- rich: "rich";
265
321
  thin: "thin";
322
+ rich: "rich";
266
323
  off: "off";
267
324
  empty: "empty";
268
325
  }>;
package/dist/types.js CHANGED
@@ -28,6 +28,9 @@ export const Query = z.object({
28
28
  site: z.string().optional(),
29
29
  /** Why this query serves the ask: the line a reviewer reads first. */
30
30
  why: z.string(),
31
+ /** The tree's facet it serves, and which try (1 = the first). Absent on a flat query. */
32
+ facet: z.string().optional(),
33
+ tier: z.number().int().positive().optional(),
31
34
  from: From,
32
35
  /** Model id, plan file id or a person's name. */
33
36
  by: z.string(),
@@ -38,6 +41,31 @@ export const Proposal = z.object({
38
41
  by: z.string(),
39
42
  queries: z.array(Query.omit({ from: true, by: true })),
40
43
  });
44
+ /** One query as a leaf of the tree: what a person would type, and why. */
45
+ export const Leaf = z.object({
46
+ terms: z.string().min(1),
47
+ why: z.string(),
48
+ site: z.string().optional(),
49
+ });
50
+ /**
51
+ * One side of the ask a researcher covers: a number, a how, a who, a counter-view, a primary
52
+ * source. `tries` are its alternatives in order: the first runs; the next runs only when the
53
+ * one before it yielded thin (fewer new hits than the guide's `thin`), or when the agent asks.
54
+ */
55
+ export const Facet = z.object({
56
+ name: z.string().min(1),
57
+ /** What this facet would prove. */
58
+ why: z.string(),
59
+ tries: z.array(z.array(Leaf).min(1)).min(1),
60
+ });
61
+ /** The fan-out for one round: the facets, each with its tries. The agent writes it; weaver runs it. */
62
+ export const QueryTree = z.object({ facets: z.array(Facet).min(1) });
63
+ /** The plan file's guide for a tree: the facets a tree of this kind covers, and what thin means. A guide, not a cap: a tree may add facets; one it leaves out is a warning. */
64
+ export const TreeGuide = z.object({
65
+ facets: z.array(z.object({ name: z.string().min(1), why: z.string() })),
66
+ /** New hits under which a try counts as thin, so the next try runs. */
67
+ thin: z.number().int().nonnegative(),
68
+ });
41
69
  export const Budget = z.object({
42
70
  /** Queries per round after the merge. Human queries never count against it. */
43
71
  queries: z.number().int().positive(),
@@ -69,6 +97,8 @@ export const PlanFile = z.object({
69
97
  budget: Budget,
70
98
  /** How much a source's age counts for this kind, one sentence: filled as `{age}`. Never a cutoff. */
71
99
  age: z.string().optional(),
100
+ /** The facets a query tree of this kind covers. Absent on a file from before version 6: the kind's default. */
101
+ tree: TreeGuide.optional(),
72
102
  });
73
103
  /** What a source, channel or proposer yielded before. Raven reads it; wren or the files ledger writes it. */
74
104
  export const YieldRow = z.object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrenautomation/raven",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Ask in, plan out. The planner of Wren's research engine: typed queries with who proposed them and why, proposals merged into one plan under a plan file per ask kind, read-or-skip on hits, and the edge to take after a round. Pure functions and prompts; the model is injected.",
5
5
  "license": "PolyForm-Strict-1.0.0",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "commander": "15.0.0",
34
34
  "zod": "4.6.5",
35
- "@wrenautomation/models": "0.10.0"
35
+ "@wrenautomation/models": "0.12.0"
36
36
  },
37
37
  "scripts": {
38
38
  "typecheck": "tsc --noEmit",