@companion-ai/feynman 0.5.1 → 0.5.3

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.
@@ -2,74 +2,40 @@ You are Feynman, a research-first AI agent.
2
2
 
3
3
  Your job is to investigate questions, read primary sources, compare evidence, design experiments when useful, and produce reproducible written artifacts.
4
4
 
5
- Operating rules:
6
- - Evidence over fluency.
7
- - Prefer papers, official documentation, datasets, code, and direct experimental results over commentary.
8
- - Separate observations from inferences.
9
- - State uncertainty explicitly.
5
+ Evidence:
6
+ - Evidence over fluency. Prefer papers, official documentation, datasets, code, and direct experimental results over commentary.
7
+ - Separate observations from inferences, and state uncertainty explicitly.
10
8
  - When a claim depends on recent literature or unstable facts, use tools before answering.
11
- - When discussing papers, cite title, year, and identifier or URL when possible.
12
- - Use visible Feynman alpha tools such as `alpha_search`, `alpha_get_paper`, `alpha_ask_paper`, and `alpha_read_code` for academic paper search, paper reading, paper Q&A, repository inspection, and persistent annotations.
13
- - Use `web_search`, `fetch_content`, and `get_search_content` first for current topics: products, companies, markets, regulations, software releases, model availability, model pricing, benchmarks, docs, or anything phrased as latest/current/recent/today.
14
- - Tool names are literal. For web search, call `web_search`; do not call non-existent aliases such as `search_web`, `google:search`, `google_search`, or `search_google`. For URL reading, call `fetch_content`; do not call bare `fetch`, `WebFetch`, or `read_url_content`.
15
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call non-existent question tools such as `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
16
- - For shell-based alphaXiv access, call `feynman alpha ...` through `bash`. Do not call the user's bare global `alpha` binary; it may be stale or unpatched.
17
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to the canonical visible tool name and argument shape, or stop and report the specific blocked capability.
18
- - For mixed topics, combine both: use web sources for current reality and paper sources for background literature.
19
- - Never answer a latest/current question from arXiv or alpha-backed paper search alone.
20
- - For AI model or product claims, prefer official docs/vendor pages plus recent web sources over old papers.
21
- - Use visible installed Pi research packages for broader web/PDF access, document parsing, citation/source retrieval, memory, session recall, and delegated research subtasks when they reduce friction. If a package tool is not visible, do not claim that capability exists; write the durable artifact and mark that specific capability blocked.
22
- - You are running inside the Feynman/Pi runtime with filesystem tools, package tools, and configured extensions. Do not claim you are only a static model, that you cannot write files, or that you cannot use tools unless you attempted the relevant tool and it failed.
23
- - If a tool, package, source, or network route is unavailable, record the specific failed capability and still write the requested durable artifact with a clear `Blocked / Unverified` status instead of stopping with chat-only prose.
24
- - Feynman ships project subagents for research work. Prefer the `researcher`, `writer`, `verifier`, and `reviewer` subagents for larger research tasks when decomposition clearly helps.
25
- - Use subagents when decomposition meaningfully reduces context pressure or lets you parallelize evidence gathering. For detached long-running work, prefer background subagent execution with `async: true`.
26
- - For deep research, act like a lead researcher by default: plan first, use hidden worker batches only when breadth justifies them, synthesize batch results, and finish with a verification pass.
27
- - For long workflows, externalize state to disk early. Treat the plan artifact as working memory and keep a task ledger plus verification log there as the run evolves.
28
- - For long-running or resumable work, use `CHANGELOG.md` in the workspace root as a lab notebook when it exists. Read it before resuming substantial work and append concise entries after meaningful progress, failed approaches, major verification results, or new blockers.
29
- - Do not create or update `CHANGELOG.md` for trivial one-shot tasks.
30
- - Do not force chain-shaped orchestration onto the user. Multi-agent decomposition is an internal tactic, not the primary UX.
31
- - For AI research artifacts, default to pressure-testing the work before polishing it. Use review-style workflows to check novelty positioning, evaluation design, baseline fairness, ablations, reproducibility, and likely reviewer objections.
32
- - Do not say `verified`, `confirmed`, `checked`, or `reproduced` unless you actually performed the check and can point to the supporting source, artifact, or command output.
33
- - Do not say a file edit, patch, correction, or reviewer fix was applied unless the relevant write/edit tool succeeded and you then verified the changed file on disk. If an edit fails, record the failure, retry with a smaller edit or full-file rewrite, and only mark the issue fixed after an explicit read, `rg`, `grep`, `diff`, `stat`, or equivalent check shows the old unsupported content is gone and the corrected content exists.
34
- - Never invent or fabricate experimental results, scores, datasets, sample sizes, ablations, benchmark tables, figures, images, charts, or quantitative comparisons. If the user asks for a paper, report, draft, figure, or result and the underlying data is missing, write a clearly labeled placeholder such as `No experimental results are available yet` or `TODO: run experiment`.
35
- - Every quantitative result, figure, table, chart, image, or benchmark claim must trace to at least one explicit source URL, research note, raw artifact path, or script/command output. If provenance is missing, omit the claim or mark it as a planned measurement instead of presenting it as fact.
36
- - When a task involves calculations, code, or quantitative outputs, define the minimal test or oracle set before implementation and record the results of those checks before delivery.
37
- - If a plot, number, or conclusion looks cleaner than expected, assume it may be wrong until it survives explicit checks. Never smooth curves, drop inconvenient variations, or tune presentation-only outputs without stating that choice.
38
- - When a verification pass finds one issue, continue searching for others. Do not stop after the first error unless the whole branch is blocked.
39
- - Use visualization tools only when they are visible in the current tool set and materially improve understanding. Prefer charts for quantitative comparisons, Mermaid for simple process/architecture diagrams, and interactive HTML widgets for exploratory visual explanations. If no chart/rendering tool is visible, write the chart specification or data table as a durable artifact instead of claiming a chart was generated.
40
- - Persistent memory is package-backed. Use `memory_search` to recall prior preferences and lessons, `memory_remember` to store explicit durable facts, and `memory_lessons` when prior corrections matter.
41
- - If the user says "remember", states a stable preference, or asks for something to be the default in future sessions, call `memory_remember`. Do not just say you will remember it.
42
- - For long-running local research work such as experiments, crawls, benchmark runs, or log-following, use the process package when it is visible. If it is not visible, run bounded foreground commands or record the exact blocked research-run status capability instead of claiming detached/background execution.
43
- - Prefer the smallest investigation or experiment that can materially reduce uncertainty before escalating to broader work.
44
- - When an experiment is warranted, write the code or scripts, run them, capture outputs, and save artifacts to disk.
45
- - Before pausing long-running work, update the durable state on disk first: plan artifact, `CHANGELOG.md`, and any verification notes needed for the next session to resume cleanly.
46
- - Treat polished scientific communication as part of the job: structure reports cleanly, use Markdown deliberately, and use LaTeX math when equations clarify the argument.
47
- - For any source-based answer, include an explicit Sources section with direct URLs, not just paper titles.
48
- - When citing papers from alpha-backed tools, prefer direct arXiv or alphaXiv links and include the arXiv ID.
49
- - Default toward delivering a concrete artifact when the task naturally calls for one: reading list, memo, audit, experiment log, or draft.
50
- - For user-facing workflows, produce exactly one canonical durable Markdown artifact unless the user explicitly asks for multiple deliverables.
51
- - If a workflow requests a durable artifact, verify the file exists on disk before the final response. If complete evidence is unavailable, save a partial artifact that explicitly marks missing checks as `blocked`, `unverified`, or `not run`.
52
- - Do not create extra user-facing intermediate markdown files just because the workflow has multiple reasoning stages.
53
- - Treat HTML/PDF preview outputs as temporary render artifacts, not as the canonical saved result.
54
- - Intermediate task files, raw logs, and verification notes are allowed when they materially reduce context pressure or improve auditability.
55
- - Strong default AI-research artifacts include: literature review, internal research review, reproducibility audit, source comparison, and paper-style draft.
56
- - Default artifact locations:
57
- - outputs/ for reviews, reading lists, and summaries
58
- - experiments/ for runnable experiment code and result logs
59
- - notes/ for scratch notes and intermediate synthesis
60
- - papers/ for polished paper-style drafts and writeups
61
- - Default deliverables should include: summary, strongest evidence, disagreements or gaps, open questions, recommended next steps, and links to the source material.
9
+ - For papers, use the alpha tools (`alpha_search`, `alpha_get_paper`, `alpha_ask_paper`, `alpha_read_code`) and `feynman_science_database_search`. In a shell, call `feynman alpha ...`, not a bare global `alpha`.
10
+ - For current topics (products, releases, pricing, benchmarks, docs, regulations, anything latest/current/recent), use `web_search` and `fetch_content` first. Never answer a current question from paper search alone. For mixed topics, use both.
11
+ - Cite title, year, and a direct URL or identifier; prefer arXiv or alphaXiv links with the arXiv ID. Source-based answers end with a Sources section of direct URLs.
62
12
 
63
- Default workflow:
64
- 1. Clarify the research objective if needed.
65
- 2. Search for relevant primary sources.
66
- 3. Inspect the most relevant papers or materials directly.
67
- 4. Synthesize consensus, disagreements, and missing evidence.
68
- 5. Design and run experiments when they would resolve uncertainty.
69
- 6. Write the requested output artifact.
13
+ Tools:
14
+ - Call only tools in your tool list. If a call returns `Tool not found` or `Invalid URL`, do not repeat it; use a listed tool or record the capability as blocked.
15
+ - To ask the user something, write plain chat text and wait for their reply.
16
+ - If a tool, source, or network route fails, record the failure and still write the requested artifact with a clear `Blocked` or `Unverified` status instead of stopping with chat-only prose.
17
+
18
+ Delegation:
19
+ - Use the `researcher`, `writer`, `verifier`, and `reviewer` subagents when decomposition reduces context pressure or parallelizes evidence gathering. Keep delegation internal; do not make the user manage it.
20
+ - A workflow is finished only when its final artifact is on disk. Before your final response, wait with `bg_wait` for every subagent whose result the artifact still needs; a launch receipt is not a result.
21
+ - For long workflows, write the plan to disk early and keep its task ledger and verification log current. If `CHANGELOG.md` exists in the workspace, read it before resuming substantial work and append concise entries after meaningful progress, failures, verification results, or blockers. Do not create it for one-shot tasks.
22
+ - Prefer the smallest investigation or experiment that can reduce uncertainty. When an experiment is warranted, write the code, run it, and save outputs to disk.
23
+
24
+ Integrity:
25
+ - Never invent results, scores, datasets, sample sizes, ablations, tables, figures, or quantitative comparisons. If data is missing, write a labeled placeholder such as `TODO: run experiment`.
26
+ - Every quantitative claim, figure, or table must trace to a source URL, research note, raw artifact path, or command output. Otherwise omit it or mark it as a planned measurement.
27
+ - For calculations or code, define the minimal checks before implementing and record their results before delivery. Treat results that look cleaner than expected as suspect until checked.
28
+ - Say `verified`, `confirmed`, `checked`, or `reproduced` only when you performed the check and can point to its evidence.
29
+ - Say an edit or fix was applied only after the write succeeded and a read, `grep`, or `diff` of the file shows it. If an edit fails, retry with a smaller edit or a full-file rewrite.
30
+ - When a verification pass finds one issue, keep looking for others.
31
+
32
+ Artifacts:
33
+ - Deliver one canonical Markdown artifact per workflow unless the user asks for more. Intermediate notes and logs are fine when they reduce context pressure or improve auditability.
34
+ - Locations: `outputs/` for reviews, reading lists, and summaries; `papers/` for paper-style drafts; `experiments/` for experiment code and logs; `notes/` for scratch notes.
35
+ - Verify the artifact exists on disk before the final response. If evidence is incomplete, save a partial artifact that marks missing checks `blocked`, `unverified`, or `not run`.
36
+ - Use Markdown tables for quantitative comparisons, Mermaid for processes and architectures, and LaTeX when equations clarify the argument.
37
+ - A default deliverable covers: summary, strongest evidence, disagreements or gaps, open questions, next steps, and sources.
70
38
 
71
39
  Style:
72
- - Concise, skeptical, and explicit.
73
- - Avoid fake certainty.
74
- - Do not present unverified claims as facts.
75
- - When greeting, introducing yourself, or answering "who are you", identify yourself explicitly as Feynman.
40
+ - Concise, skeptical, and explicit. No fake certainty.
41
+ - When greeting or asked who you are, identify yourself as Feynman.
@@ -5,6 +5,7 @@ thinking: high
5
5
  tools: read, write, edit, bash, grep, find, ls, web_search, fetch_content, get_search_content, feynman_science_database_search, hf_dataset_info, hf_repo_files, hf_repo_read_file
6
6
  output: research.md
7
7
  defaultProgress: true
8
+ async: true
8
9
  ---
9
10
 
10
11
  You are Feynman's evidence-gathering subagent.
@@ -5,6 +5,7 @@ thinking: medium
5
5
  tools: read, bash, grep, find, ls, write, edit, web_search, fetch_content, get_search_content, feynman_science_database_search
6
6
  output: cited.md
7
7
  defaultProgress: true
8
+ async: true
8
9
  ---
9
10
 
10
11
  You are Feynman's verifier agent.
@@ -36,10 +36,9 @@ Unresolved issues, disagreements between sources, gaps in evidence.
36
36
  ```
37
37
 
38
38
  ## Visuals
39
- - When the research contains quantitative data (benchmarks, comparisons, trends over time), generate charts only when a chart tool is visible; otherwise write a chart specification or source-backed table.
39
+ - Use Markdown tables for quantitative data (benchmarks, comparisons, trends). Plot only source-backed data, and save the plotting script next to the draft.
40
40
  - Do not create charts from invented or example data. If values are missing, describe the planned measurement instead.
41
41
  - When explaining architectures, pipelines, or multi-step processes, use Mermaid diagrams only when the structure is supported by the supplied evidence.
42
- - When a comparison across multiple dimensions would benefit from an interactive view, use an interactive UI tool only when one is visible and the data is source-backed.
43
42
  - Every visual must have a descriptive caption and reference the data, source URL, research file, raw artifact, or script it is based on.
44
43
  - Do not add visuals for decoration — only when they materially improve understanding of the evidence.
45
44
 
package/RELEASES.md CHANGED
@@ -6,6 +6,30 @@ GitHub release notes are generated from the matching `## vX.Y.Z` section in this
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## v0.5.3 - 2026-09-24
10
+
11
+ ### Leaner prompts, same research quality
12
+
13
+ - The system prompt and the 11 workflow prompts lost about 200 lines. A block of tool-name rules was copied into every workflow and repeated in the system prompt, and the prompts referred to memory, process, chart, and experiment tools Feynman does not ship, `FEYNMAN_SUMMARIZE_*` environment variables that nothing reads, and a PDF crash that no longer exists.
14
+ - Workflows now wait for their background subagents before the final answer. In one-shot `feynman --prompt` runs, a `/lit` run could end while its reviewer was still working and never write the provenance file.
15
+ - On the `/lit` eval with GPT-5.6 Terra, 4 of 4 questions finished, all 44 citations resolved with matching titles, and each question ran the researcher, verifier, and reviewer in under 11 minutes (0.5.2: 9-14 minutes, 43 of 43 citations).
16
+
17
+ ### Smaller install
18
+
19
+ - CLI telemetry sends its command events through posthog-node, like the rest of Feynman. It no longer also sends each command as an OpenTelemetry span and two log records, which removes nine `@opentelemetry` packages (about 28 MB). The events and what they contain are unchanged.
20
+
21
+ ### Known issue
22
+
23
+ - Claude Opus 5.5 refuses some biology literature reviews (for example `/lit CRISPR base editing`) with "The model refused to complete the request". The same topics run on GPT-5.6 Terra.
24
+
25
+ ## v0.5.2 - 2026-09-23
26
+
27
+ ### Faster, cheaper research runs
28
+
29
+ - OpenAlex exact searches (`openalex_search_works`, citations, references, authors, venues) now return at most the tool's `limit` (default 5, max 20) instead of 50-100 full records; an explicit `max_records` is capped at 50. In live `/lit` runs these results were 100-240 KB per call and drove most of the multi-million-token usage.
30
+ - The `researcher` and `verifier` subagents run in the background by default, where they get Feynman's web and literature tools. Foreground launches of these agents failed and had to be retried.
31
+ - `alpha_ask_paper` now states it takes arXiv and alphaXiv papers only, and points DOI-only papers to `fetch_content` or Europe PMC full text.
32
+
9
33
  ## v0.5.1 - 2026-09-23
10
34
 
11
35
  ### Telemetry
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import { fetchLatestFeynmanVersion, getFeynmanUpgradeLines, isNewerVersion } fro
29
29
  import { runDoctor, runStatus } from "./setup/doctor.js";
30
30
  import { setupPreviewDependencies } from "./setup/preview.js";
31
31
  import { runSetup } from "./setup/setup.js";
32
- import { captureTelemetryEvent, emitTelemetryLog, getCliTelemetryMetadata, initializePostHogTelemetry, shutdownPostHogTelemetry, startTelemetrySpan, telemetryErrorProperties, telemetryFirstRunNotice, } from "./telemetry/posthog.js";
32
+ import { captureTelemetryEvent, getCliTelemetryMetadata, initializePostHogTelemetry, shutdownPostHogTelemetry, telemetryErrorProperties, telemetryFirstRunNotice, } from "./telemetry/posthog.js";
33
33
  import { ASH, printAsciiHeader, printInfo, printPanel, printSection, RESET, SAGE } from "./ui/terminal.js";
34
34
  import { createModelRuntime } from "./model/registry.js";
35
35
  import { cliCommandSections, formatCliWorkflowUsage, legacyFlags, readPromptSpecs, topLevelCommandNames, } from "../metadata/commands.mjs";
@@ -385,15 +385,13 @@ export async function main() {
385
385
  const here = dirname(fileURLToPath(import.meta.url));
386
386
  const appRoot = resolve(here, "..");
387
387
  const feynmanVersion = loadPackageVersion(appRoot).version;
388
- initializePostHogTelemetry({ appVersion: feynmanVersion, serviceName: "feynman-cli" });
388
+ initializePostHogTelemetry({ appVersion: feynmanVersion });
389
389
  const telemetryNotice = telemetryFirstRunNotice();
390
390
  if (telemetryNotice)
391
391
  process.stderr.write(`${telemetryNotice}\n`);
392
392
  const commandTelemetry = getCliTelemetryMetadata(process.argv.slice(2), { knownCommands: getTelemetryCommandNames(appRoot) });
393
393
  const commandStartedAt = Date.now();
394
- const commandSpan = startTelemetrySpan("feynman.cli.command", commandTelemetry);
395
394
  captureTelemetryEvent("feynman_command_started", commandTelemetry);
396
- emitTelemetryLog("info", "feynman command started", commandTelemetry);
397
395
  try {
398
396
  await runMain({ here, appRoot, feynmanVersion });
399
397
  const durationMs = Date.now() - commandStartedAt;
@@ -403,9 +401,7 @@ export async function main() {
403
401
  duration_ms: durationMs,
404
402
  exit_code: exitCode,
405
403
  };
406
- commandSpan.end(exitCode === 0 ? "ok" : "error", completeProperties);
407
404
  captureTelemetryEvent(exitCode === 0 ? "feynman_command_completed" : "feynman_command_failed", completeProperties);
408
- emitTelemetryLog(exitCode === 0 ? "info" : "error", exitCode === 0 ? "feynman command completed" : "feynman command failed", completeProperties);
409
405
  }
410
406
  catch (error) {
411
407
  const durationMs = Date.now() - commandStartedAt;
@@ -414,10 +410,7 @@ export async function main() {
414
410
  duration_ms: durationMs,
415
411
  ...telemetryErrorProperties(error),
416
412
  };
417
- commandSpan.recordException(error);
418
- commandSpan.end("error", failureProperties);
419
413
  captureTelemetryEvent("feynman_command_failed", failureProperties);
420
- emitTelemetryLog("error", "feynman command failed", failureProperties);
421
414
  throw error;
422
415
  }
423
416
  finally {
@@ -1,16 +1,6 @@
1
1
  import { randomUUID, createHash } from "node:crypto";
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
- import { trace, SpanStatusCode } from "@opentelemetry/api";
5
- import { logs, SeverityNumber } from "@opentelemetry/api-logs";
6
- import { OTLPExporterBase, createOtlpNetworkExportDelegate, } from "@opentelemetry/otlp-exporter-base";
7
- import { createOtlpHttpExporterMetrics } from "@opentelemetry/otlp-exporter-base/node-http";
8
- import { JsonLogsSerializer, LogsExporterMetricsHelper, ProtobufTraceSerializer, TraceExporterMetricsHelper, } from "@opentelemetry/otlp-transformer";
9
- import { resourceFromAttributes } from "@opentelemetry/resources";
10
- import { BatchLogRecordProcessor, LoggerProvider, } from "@opentelemetry/sdk-logs";
11
- import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
12
- import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
13
- import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
14
4
  import { PostHog } from "posthog-node";
15
5
  import { getFeynmanHome, getFeynmanStateDir } from "../config/paths.js";
16
6
  export const DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
@@ -25,102 +15,30 @@ export const TELEMETRY_NOTICE = [
25
15
  "To opt out, set FEYNMAN_TELEMETRY=off. Learn more: https://www.feynman.is/docs/getting-started/configuration#telemetry",
26
16
  ].join("\n");
27
17
  let posthogClient;
28
- let tracerProvider;
29
- let loggerProvider;
30
18
  let activeConfig;
31
19
  let telemetryInitialized = false;
32
20
  let telemetryStartWarningPrinted = false;
33
21
  let telemetryTransportFailed = false;
34
22
  let telemetryNoticeThisProcess;
35
- export function createTelemetryTransportCircuitBreaker(onTransportFailure) {
36
- let circuitOpen = false;
37
- return {
38
- tryStart() {
39
- return !circuitOpen;
40
- },
41
- completeSuccess() { },
42
- completeFailure(error) {
43
- if (circuitOpen)
44
- return;
45
- circuitOpen = true;
46
- onTransportFailure(error);
47
- },
48
- isOpen() {
49
- return circuitOpen;
50
- },
51
- };
52
- }
53
- function successfulTelemetryDropResponse() {
54
- return new Response(null, { status: 204 });
55
- }
56
- export function createTelemetryCircuitBreakerFetch(fetchImpl, onTransportFailure, circuit = createTelemetryTransportCircuitBreaker(onTransportFailure)) {
23
+ /** One silent attempt per session: after the first failure, later requests are dropped. */
24
+ export function createTelemetryCircuitBreakerFetch(fetchImpl, onTransportFailure) {
25
+ let open = false;
57
26
  return async (url, options) => {
58
- if (!circuit.tryStart()) {
59
- return successfulTelemetryDropResponse();
60
- }
61
- try {
62
- const response = await fetchImpl(url, options);
63
- if (response.status >= 200 && response.status < 400) {
64
- circuit.completeSuccess();
65
- return response;
66
- }
67
- circuit.completeFailure(new Error(`PostHog transport returned HTTP ${response.status}`));
68
- return successfulTelemetryDropResponse();
69
- }
70
- catch (error) {
71
- circuit.completeFailure(error);
72
- return successfulTelemetryDropResponse();
73
- }
74
- };
75
- }
76
- export function createOneShotOtlpTransport(options) {
77
- return {
78
- async send(data, timeoutMillis) {
79
- if (!options.circuit.tryStart()) {
80
- return { status: "success" };
81
- }
82
- const controller = new AbortController();
83
- const timeout = setTimeout(() => controller.abort(), timeoutMillis);
84
- timeout.unref?.();
27
+ if (!open) {
85
28
  try {
86
- const response = await options.fetchImpl(options.url, {
87
- method: "POST",
88
- headers: {
89
- ...options.headers,
90
- "Content-Type": options.contentType,
91
- },
92
- body: Buffer.from(data),
93
- signal: controller.signal,
94
- });
95
- if (response.status < 200 || response.status >= 400) {
96
- throw new Error(`OTLP transport returned HTTP ${response.status}`);
97
- }
98
- options.circuit.completeSuccess();
99
- return { status: "success" };
29
+ const response = await fetchImpl(url, options);
30
+ if (response.status >= 200 && response.status < 400)
31
+ return response;
32
+ throw new Error(`PostHog transport returned HTTP ${response.status}`);
100
33
  }
101
34
  catch (error) {
102
- // The exporter reports success after opening the shared circuit so
103
- // OpenTelemetry processors do not relay optional telemetry failures
104
- // through their global error handler.
105
- options.circuit.completeFailure(error);
106
- return { status: "success" };
35
+ open = true;
36
+ onTransportFailure(error);
107
37
  }
108
- finally {
109
- clearTimeout(timeout);
110
- }
111
- },
112
- shutdown() { },
38
+ }
39
+ return new Response(null, { status: 204 });
113
40
  };
114
41
  }
115
- function createOneShotOtlpExporter(options) {
116
- const metrics = createOtlpHttpExporterMetrics(options.componentType, options.metricsHelper, options.url, undefined);
117
- const transport = createOneShotOtlpTransport(options);
118
- return new OTLPExporterBase(createOtlpNetworkExportDelegate({
119
- timeoutMillis: options.timeoutMillis,
120
- concurrencyLimit: 1,
121
- compression: "none",
122
- }, options.serializer, metrics, transport));
123
- }
124
42
  function disableTelemetryAfterTransportFailure(error) {
125
43
  if (telemetryTransportFailed)
126
44
  return;
@@ -213,7 +131,6 @@ export function resolvePostHogTelemetryConfig(options = {}) {
213
131
  projectToken,
214
132
  distinctId: env.FEYNMAN_TELEMETRY_DISTINCT_ID?.trim() || getAnonymousDistinctId(options.home),
215
133
  appVersion: options.appVersion,
216
- serviceName: options.serviceName ?? "feynman-cli",
217
134
  };
218
135
  }
219
136
  function normalizeTelemetryKey(key) {
@@ -262,16 +179,6 @@ function baseTelemetryProperties(config) {
262
179
  $process_person_profile: false,
263
180
  });
264
181
  }
265
- function toOtelAttributes(properties = {}) {
266
- const normalized = normalizeTelemetryProperties(properties);
267
- const attributes = {};
268
- for (const [key, value] of Object.entries(normalized)) {
269
- if (value === null)
270
- continue;
271
- attributes[key] = value;
272
- }
273
- return attributes;
274
- }
275
182
  export function stableTelemetryHash(value) {
276
183
  if (!value)
277
184
  return undefined;
@@ -289,13 +196,6 @@ export function telemetryErrorProperties(error) {
289
196
  error_message_hash: stableTelemetryHash(message),
290
197
  };
291
198
  }
292
- export function sanitizeTelemetryException(error) {
293
- const properties = telemetryErrorProperties(error);
294
- return {
295
- name: String(properties.error_name ?? "unknown"),
296
- message: `error_message_hash:${properties.error_message_hash ?? "unknown"}`,
297
- };
298
- }
299
199
  export function initializePostHogTelemetry(options = {}) {
300
200
  if (telemetryInitialized)
301
201
  return activeConfig;
@@ -305,81 +205,22 @@ export function initializePostHogTelemetry(options = {}) {
305
205
  activeConfig = config;
306
206
  if (!config)
307
207
  return undefined;
308
- try {
309
- const resource = resourceFromAttributes({
310
- [ATTR_SERVICE_NAME]: config.serviceName,
311
- ...(config.appVersion ? { [ATTR_SERVICE_VERSION]: config.appVersion } : {}),
312
- });
313
- const circuit = createTelemetryTransportCircuitBreaker(disableTelemetryAfterTransportFailure);
314
- const defaultTelemetryFetch = (url, fetchOptions) => fetch(url, fetchOptions);
315
- const otlpFetch = options.otlpFetch ?? defaultTelemetryFetch;
316
- tracerProvider = new NodeTracerProvider({
317
- resource,
318
- spanProcessors: [
319
- new BatchSpanProcessor(createOneShotOtlpExporter({
320
- url: `${config.host}/i/v1/traces`,
321
- headers: { Authorization: `Bearer ${config.projectToken}` },
322
- contentType: "application/x-protobuf",
323
- fetchImpl: otlpFetch,
324
- circuit,
325
- timeoutMillis: 750,
326
- componentType: "otlp_http_span_exporter",
327
- serializer: ProtobufTraceSerializer,
328
- metricsHelper: TraceExporterMetricsHelper,
329
- }), { scheduledDelayMillis: 250, exportTimeoutMillis: 3000 }),
330
- ],
331
- });
332
- tracerProvider.register();
333
- loggerProvider = new LoggerProvider({
334
- resource,
335
- processors: [
336
- new BatchLogRecordProcessor({
337
- exporter: createOneShotOtlpExporter({
338
- url: `${config.host}/i/v1/logs`,
339
- headers: { Authorization: `Bearer ${config.projectToken}` },
340
- contentType: "application/json",
341
- fetchImpl: otlpFetch,
342
- circuit,
343
- timeoutMillis: 750,
344
- componentType: "otlp_http_log_exporter",
345
- serializer: JsonLogsSerializer,
346
- metricsHelper: LogsExporterMetricsHelper,
347
- }),
348
- scheduledDelayMillis: 250,
349
- exportTimeoutMillis: 3000,
350
- }),
351
- ],
352
- });
353
- logs.setGlobalLoggerProvider(loggerProvider);
354
- const defaultPostHogFetch = (url, fetchOptions) => fetch(url, fetchOptions);
355
- posthogClient = new PostHog(config.projectToken, {
356
- host: config.host,
357
- flushAt: 1,
358
- flushInterval: 0,
359
- isServer: false,
360
- disableGeoip: true,
361
- fetchRetryCount: 0,
362
- fetch: createTelemetryCircuitBreakerFetch(options.posthogFetch ?? defaultPostHogFetch, disableTelemetryAfterTransportFailure, circuit),
363
- });
364
- posthogClient.on("error", () => {
365
- if (process.env.FEYNMAN_DEBUG === "1" && !telemetryStartWarningPrinted) {
366
- telemetryStartWarningPrinted = true;
367
- process.stderr.write("[feynman] PostHog telemetry transport reported an error.\n");
368
- }
369
- });
370
- return config;
371
- }
372
- catch (error) {
208
+ posthogClient = new PostHog(config.projectToken, {
209
+ host: config.host,
210
+ flushAt: 1,
211
+ flushInterval: 0,
212
+ isServer: false,
213
+ disableGeoip: true,
214
+ fetchRetryCount: 0,
215
+ fetch: createTelemetryCircuitBreakerFetch(options.posthogFetch ?? ((url, fetchOptions) => fetch(url, fetchOptions)), disableTelemetryAfterTransportFailure),
216
+ });
217
+ posthogClient.on("error", () => {
373
218
  if (process.env.FEYNMAN_DEBUG === "1" && !telemetryStartWarningPrinted) {
374
219
  telemetryStartWarningPrinted = true;
375
- process.stderr.write(`[feynman] PostHog telemetry disabled after initialization failed (${error instanceof Error ? error.message : "unknown error"}).\n`);
220
+ process.stderr.write("[feynman] PostHog telemetry transport reported an error.\n");
376
221
  }
377
- activeConfig = undefined;
378
- posthogClient = undefined;
379
- tracerProvider = undefined;
380
- loggerProvider = undefined;
381
- return undefined;
382
- }
222
+ });
223
+ return config;
383
224
  }
384
225
  export function captureTelemetryEvent(event, properties = {}) {
385
226
  if (!activeConfig || !posthogClient)
@@ -405,90 +246,17 @@ export async function captureTelemetryEventImmediate(event, properties = {}) {
405
246
  },
406
247
  });
407
248
  }
408
- export function emitTelemetryLog(severityText, body, properties = {}) {
409
- if (!activeConfig || !loggerProvider)
410
- return;
411
- const severityNumber = severityText === "error"
412
- ? SeverityNumber.ERROR
413
- : severityText === "warn"
414
- ? SeverityNumber.WARN
415
- : severityText === "debug"
416
- ? SeverityNumber.DEBUG
417
- : severityText === "trace"
418
- ? SeverityNumber.TRACE
419
- : SeverityNumber.INFO;
420
- logs.getLogger("feynman").emit({
421
- severityText,
422
- severityNumber,
423
- body,
424
- attributes: {
425
- ...toOtelAttributes(baseTelemetryProperties(activeConfig)),
426
- ...toOtelAttributes(properties),
427
- },
428
- });
429
- }
430
- function createNoopSpan() {
431
- return {
432
- setAttributes() { },
433
- recordException() { },
434
- end() { },
435
- };
436
- }
437
- export function startTelemetrySpan(name, properties = {}) {
438
- if (!activeConfig || !tracerProvider)
439
- return createNoopSpan();
440
- const span = trace.getTracer("feynman").startSpan(name, {
441
- attributes: {
442
- ...toOtelAttributes(baseTelemetryProperties(activeConfig)),
443
- ...toOtelAttributes(properties),
444
- },
445
- });
446
- let ended = false;
447
- return {
448
- setAttributes(nextProperties) {
449
- if (ended)
450
- return;
451
- span.setAttributes(toOtelAttributes(nextProperties));
452
- },
453
- recordException(error) {
454
- if (ended)
455
- return;
456
- span.recordException(sanitizeTelemetryException(error));
457
- span.setAttributes(toOtelAttributes(telemetryErrorProperties(error)));
458
- },
459
- end(status = "ok", nextProperties = {}) {
460
- if (ended)
461
- return;
462
- ended = true;
463
- if (Object.keys(nextProperties).length > 0) {
464
- span.setAttributes(toOtelAttributes(nextProperties));
465
- }
466
- if (status === "error") {
467
- span.setStatus({ code: SpanStatusCode.ERROR });
468
- }
469
- else {
470
- span.setStatus({ code: SpanStatusCode.OK });
471
- }
472
- span.end();
473
- },
474
- };
475
- }
476
249
  export async function shutdownPostHogTelemetry() {
477
250
  const client = posthogClient;
478
- const traces = tracerProvider;
479
- const loggers = loggerProvider;
480
251
  posthogClient = undefined;
481
- tracerProvider = undefined;
482
- loggerProvider = undefined;
483
252
  activeConfig = undefined;
484
253
  telemetryInitialized = false;
485
254
  telemetryTransportFailed = false;
486
255
  telemetryNoticeThisProcess = undefined;
487
- await Promise.allSettled([
488
- client?.shutdown(3000),
489
- traces?.shutdown(),
490
- loggers?.shutdown(),
491
- ]);
256
+ try {
257
+ await client?.shutdown(3000);
258
+ }
259
+ catch { }
492
260
  }
493
261
  function flagValue(args, flag) {
494
262
  const prefix = `${flag}=`;
@@ -86,7 +86,7 @@ export function registerAlphaTools(pi: ExtensionAPI): void {
86
86
  pi.registerTool({
87
87
  name: "alpha_ask_paper",
88
88
  label: "Alpha Ask Paper",
89
- description: "Ask a targeted question about a paper. Uses AI to analyze the PDF and answer.",
89
+ description: "Ask a targeted question about an arXiv or alphaXiv paper. Uses AI to analyze the PDF and answer. DOI-only papers are not supported; read those with fetch_content on the open-access PDF or Europe PMC full text.",
90
90
  parameters: Type.Object({
91
91
  paper: Type.String({ description: "arXiv ID, arXiv URL, or alphaXiv URL." }),
92
92
  question: Type.String({ description: "Question about the paper." }),
@@ -1,4 +1,4 @@
1
- const MAX_EXACT_RECORDS = 500;
1
+ const MAX_EXACT_RECORDS = 50;
2
2
  const REQUEST_TIMEOUT_MS = 25_000;
3
3
  const OPENALEX_BASE = "https://api.openalex.org";
4
4
  const OPEN_ABSTRACT_LICENSES = new Set(["cc-by", "cc-by-sa", "cc0", "public-domain"]);
@@ -461,9 +461,9 @@ async function fetchWorkById(workId: string): Promise<{
461
461
  };
462
462
  }
463
463
 
464
- async function exactWorkSearch(query: string, commandQuery: string): Promise<Record<string, unknown>> {
464
+ async function exactWorkSearch(query: string, commandQuery: string, defaultLimit?: number): Promise<Record<string, unknown>> {
465
465
  const parsed = parseKeyValueQuery(commandQuery);
466
- const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), 50);
466
+ const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), defaultLimit ?? 50);
467
467
  const url = endpointPath("/works");
468
468
  if (parsed.text) url.searchParams.set("search", parsed.text);
469
469
  const filters: string[] = [];
@@ -518,12 +518,12 @@ async function exactGetWork(query: string, workId: string): Promise<Record<strin
518
518
  }, "openalex_get_work", query, resolved.endpoints, resolved.credentialStatus);
519
519
  }
520
520
 
521
- async function exactCitations(query: string, commandQuery: string): Promise<Record<string, unknown>> {
521
+ async function exactCitations(query: string, commandQuery: string, defaultLimit?: number): Promise<Record<string, unknown>> {
522
522
  const parsed = parseKeyValueQuery(commandQuery);
523
523
  const workInput = parsed.text;
524
524
  if (!workInput) throw new Error("openalex_citations requires an OpenAlex work id or DOI.");
525
525
  const resolved = await fetchWorkById(workInput);
526
- const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), 50);
526
+ const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), defaultLimit ?? 50);
527
527
  const url = endpointPath("/works");
528
528
  url.searchParams.set("filter", `cites:${resolved.workId}`);
529
529
  const sort = exactSearchSort(parsed.flags.sort ?? "cited_by_count", false);
@@ -545,11 +545,11 @@ async function exactCitations(query: string, commandQuery: string): Promise<Reco
545
545
  }, "openalex_citations", query, [...resolved.endpoints, result.endpoint], result.credentialStatus);
546
546
  }
547
547
 
548
- async function exactReferences(query: string, commandQuery: string): Promise<Record<string, unknown>> {
548
+ async function exactReferences(query: string, commandQuery: string, defaultLimit?: number): Promise<Record<string, unknown>> {
549
549
  const parsed = parseKeyValueQuery(commandQuery);
550
550
  if (!parsed.text) throw new Error("openalex_references requires an OpenAlex work id or DOI.");
551
551
  const resolved = await fetchWorkById(parsed.text);
552
- const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), 100);
552
+ const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), defaultLimit ?? 100);
553
553
  const referenceIds = arrayValue(resolved.payload.referenced_works).map(shortOpenAlexId).filter((id): id is string => Boolean(id));
554
554
  const selected = referenceIds.slice(0, maxRecords);
555
555
  const endpoints = [...resolved.endpoints];
@@ -581,10 +581,10 @@ async function exactReferences(query: string, commandQuery: string): Promise<Rec
581
581
  }, "openalex_references", query, endpoints, credentialStatus);
582
582
  }
583
583
 
584
- async function exactSearchAuthors(query: string, commandQuery: string): Promise<Record<string, unknown>> {
584
+ async function exactSearchAuthors(query: string, commandQuery: string, defaultLimit?: number): Promise<Record<string, unknown>> {
585
585
  const parsed = parseKeyValueQuery(commandQuery);
586
586
  if (!parsed.text) throw new Error("openalex_search_authors requires a name query.");
587
- const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), 25);
587
+ const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), defaultLimit ?? 25);
588
588
  const url = endpointPath("/authors");
589
589
  url.searchParams.set("search", parsed.text);
590
590
  url.searchParams.set("per-page", String(Math.min(maxRecords, 200)));
@@ -625,7 +625,7 @@ async function exactGetAuthor(query: string, commandQuery: string): Promise<Reco
625
625
  }, "openalex_get_author", query, [result.endpoint, works.endpoint], works.credentialStatus);
626
626
  }
627
627
 
628
- async function exactVenueInfo(query: string, commandQuery: string): Promise<Record<string, unknown>> {
628
+ async function exactVenueInfo(query: string, commandQuery: string, defaultLimit?: number): Promise<Record<string, unknown>> {
629
629
  const parsed = parseKeyValueQuery(commandQuery);
630
630
  const venue = parsed.text;
631
631
  if (!venue) throw new Error("openalex_venue_info requires a source id, ISSN, or venue name.");
@@ -640,7 +640,7 @@ async function exactVenueInfo(query: string, commandQuery: string): Promise<Reco
640
640
  records: [row],
641
641
  }, "openalex_venue_info", query, [result.endpoint], result.credentialStatus);
642
642
  }
643
- const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), 10);
643
+ const maxRecords = safeExactLimit(numberValue(parsed.flags.max_records), defaultLimit ?? 10);
644
644
  const url = endpointPath("/sources");
645
645
  url.searchParams.set("search", venue);
646
646
  url.searchParams.set("per-page", String(Math.min(maxRecords, 200)));
@@ -657,15 +657,15 @@ async function exactVenueInfo(query: string, commandQuery: string): Promise<Reco
657
657
  }, "openalex_venue_info", query, [result.endpoint], result.credentialStatus);
658
658
  }
659
659
 
660
- export async function searchExactOpenAlex(query: string): Promise<Record<string, unknown> | undefined> {
660
+ export async function searchExactOpenAlex(query: string, defaultLimit?: number): Promise<Record<string, unknown> | undefined> {
661
661
  const command = exactCommand(query);
662
662
  if (!command) return undefined;
663
- if (command.name === "openalex_search_works") return exactWorkSearch(query, command.rest);
663
+ if (command.name === "openalex_search_works") return exactWorkSearch(query, command.rest, defaultLimit);
664
664
  if (command.name === "openalex_get_work") return exactGetWork(query, command.rest);
665
- if (command.name === "openalex_citations") return exactCitations(query, command.rest);
666
- if (command.name === "openalex_references") return exactReferences(query, command.rest);
667
- if (command.name === "openalex_search_authors") return exactSearchAuthors(query, command.rest);
665
+ if (command.name === "openalex_citations") return exactCitations(query, command.rest, defaultLimit);
666
+ if (command.name === "openalex_references") return exactReferences(query, command.rest, defaultLimit);
667
+ if (command.name === "openalex_search_authors") return exactSearchAuthors(query, command.rest, defaultLimit);
668
668
  if (command.name === "openalex_get_author") return exactGetAuthor(query, command.rest);
669
- if (command.name === "openalex_venue_info") return exactVenueInfo(query, command.rest);
669
+ if (command.name === "openalex_venue_info") return exactVenueInfo(query, command.rest, defaultLimit);
670
670
  return undefined;
671
671
  }
@@ -354,7 +354,7 @@ async function resolveDoiWork(doiWorkId: string): Promise<{
354
354
  export async function searchOpenAlex(params: SearchParams): Promise<Record<string, unknown>> {
355
355
  const query = cleanQuery(params.query);
356
356
  const limit = safeLimit(params.limit);
357
- const exact = await searchExactOpenAlex(query);
357
+ const exact = await searchExactOpenAlex(query, limit);
358
358
  if (exact) return exact;
359
359
  if (/^rate-limit$/i.test(query)) {
360
360
  if (!openAlexApiKey()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@companion-ai/feynman",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Research-first CLI agent built on Pi and alphaXiv",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -42,7 +42,7 @@
42
42
  "prepack": "node ./scripts/clean-publish-artifacts.mjs && npm run build",
43
43
  "start": "tsx src/index.ts",
44
44
  "start:dist": "node ./bin/feynman.js",
45
- "test": "node --import tsx --test --test-concurrency=1 tests/*.test.ts",
45
+ "test": "node --import tsx --import ./tests/isolate-tmpdir.ts --test --test-concurrency=1 tests/*.test.ts",
46
46
  "typecheck": "tsc --noEmit",
47
47
  "architecture:check": "node ./scripts/check-architecture.mjs"
48
48
  },
@@ -79,17 +79,8 @@
79
79
  "dependencies": {
80
80
  "@clack/prompts": "^1.7.0",
81
81
  "@companion-ai/alpha-hub": "0.1.6",
82
- "@earendil-works/pi-ai": "0.87.1",
83
- "@earendil-works/pi-coding-agent": "0.87.1",
84
- "@opentelemetry/api": "^1.9.1",
85
- "@opentelemetry/api-logs": "^0.222.0",
86
- "@opentelemetry/otlp-exporter-base": "^0.222.0",
87
- "@opentelemetry/otlp-transformer": "^0.222.0",
88
- "@opentelemetry/resources": "^2.11.0",
89
- "@opentelemetry/sdk-logs": "^0.222.0",
90
- "@opentelemetry/sdk-trace-base": "^2.11.0",
91
- "@opentelemetry/sdk-trace-node": "^2.11.0",
92
- "@opentelemetry/semantic-conventions": "^1.43.0",
82
+ "@earendil-works/pi-ai": "*",
83
+ "@earendil-works/pi-coding-agent": "*",
93
84
  "fast-xml-parser": "5.11.1",
94
85
  "pi-btw": "0.6.0",
95
86
  "pi-docparser": "4.0.0",
package/prompts/audit.md CHANGED
@@ -4,17 +4,6 @@ args: <item>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Audit the paper and codebase for: $@
19
8
 
20
9
  Derive a short slug from the audit target (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
@@ -4,17 +4,6 @@ args: <idea>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Start an autoresearch optimization loop for: $@
19
8
 
20
9
  This command runs a bounded foreground research experiment loop using the visible tools in this session.
@@ -66,14 +55,6 @@ After the baseline and after meaningful iteration milestones, append a concise e
66
55
 
67
56
  When reporting results, include every configuration tried from `autoresearch.jsonl` (kept, reverted, and failed) with its metric. Do not claim an effect from the single most favorable setting; state how the result varies across all tried settings and seeds.
68
57
 
69
- ## Optional tools
70
-
71
- Use these only when they are visible in the current tool set:
72
-
73
- - `init_experiment` - one-time session config (name, metric, unit, direction)
74
- - `run_experiment` - run the benchmark command, capture output and wall-clock time
75
- - `log_experiment` - record the benchmark result, evidence, and decision in the autoresearch log
76
-
77
58
  ## Subcommands
78
59
 
79
60
  - `/autoresearch <text>` — start or resume the loop
@@ -4,17 +4,6 @@ args: <topic>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Compare sources for: $@
19
8
 
20
9
  Derive a short slug from the comparison topic (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
@@ -23,7 +12,7 @@ Requirements:
23
12
  - Before starting, outline the comparison plan: which sources to compare, which dimensions to evaluate, expected output structure. Write the plan to `outputs/.plans/<slug>.md`. Briefly summarize the plan to the user and continue immediately. Do not ask for confirmation or wait for a proceed response unless the user explicitly requested plan review.
24
13
  - Use the `researcher` subagent to gather source material when the comparison set is broad, and the `verifier` subagent to verify sources and add inline citations to the final matrix.
25
14
  - Build a comparison matrix covering: source, key claim, evidence type, caveats, confidence.
26
- - Generate charts only when a chart tool is visible and the comparison involves quantitative metrics; otherwise include a source-backed table or chart specification. Use Mermaid for method or architecture comparisons when the structure is source-supported.
15
+ - Use a Markdown table for quantitative metrics and Mermaid for method or architecture comparisons when the structure is source-supported.
27
16
  - Distinguish agreement, disagreement, and uncertainty clearly.
28
17
  - Save exactly one comparison to `outputs/<slug>-comparison.md`.
29
18
  - End with a `Sources` section containing direct URLs for every source used.
@@ -4,22 +4,8 @@ args: <topic>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Run deep research for: $@
19
8
 
20
- This is an execution request, not a request to explain or implement the workflow instructions.
21
- Execute the workflow. Do not answer by describing the protocol, do not explain these instructions, and do not restate the protocol. Your first actions should be tool calls that create directories and write the plan artifact.
22
-
23
9
  ## Required Artifacts
24
10
 
25
11
  Derive a short slug from the topic: lowercase, hyphenated, no filler words, at most 5 words.
@@ -45,8 +31,6 @@ Create `outputs/.plans/<slug>.md` immediately. The plan must include:
45
31
 
46
32
  Make the scale decision before assigning owners in the plan. If the topic is a narrow "what is X" explainer, the plan must use lead-owned direct search tasks only; do not allocate researcher subagents in the task ledger.
47
33
 
48
- Also save the plan with `memory_remember` using key `deepresearch.<slug>.plan` if that tool is available. If it is not available, continue without it.
49
-
50
34
  After writing the plan, stop and ask for explicit confirmation before gathering evidence. Summarize the plan briefly and ask:
51
35
 
52
36
  `Proceed with this deep research plan? Reply "yes" to continue, or tell me what to change.`
@@ -69,9 +53,7 @@ Use subagents only when decomposition clearly helps:
69
53
 
70
54
  ## Step 3: Gather Evidence
71
55
 
72
- Use only tool names visible in the current tool set. For web search, call `web_search`; never call `google:search`, `google_search`, or `search_google`.
73
-
74
- Avoid crash-prone PDF parsing in this workflow. Do not call `alpha_get_paper` and do not fetch `.pdf` URLs unless the user explicitly asks for PDF extraction. Prefer paper metadata, abstracts, HTML pages, official docs, and web snippets. If only a PDF exists, cite the PDF URL from search metadata and mark full-text PDF parsing as blocked instead of fetching it.
56
+ Prefer abstracts, HTML pages, official docs, and paper metadata. Read full text only for the few papers the conclusions depend on.
75
57
 
76
58
  If direct search was chosen:
77
59
  - Skip researcher spawning entirely.
@@ -88,7 +70,6 @@ If subagents were chosen:
88
70
  - Use only supported `subagent` keys. Do not add extra keys such as `artifacts` unless the tool schema explicitly exposes them.
89
71
  - Use one async `workflowScript` with `await runs.all(...)` for parallel evidence gathering. Each item needs a unique stable `key`, plus its agent, short task, and output path. Set `globalConcurrencyLimit: 4` on the outer call.
90
72
  - Read the ordered result array and record each child's `ok`, error, and returned output/artifact paths. Ordinary child failures are collected by `runs.all`; validation or infrastructure failure can still fail the workflow. Do not assume every output exists.
91
- - Do not name exact tool commands in subagent tasks unless those tool names are visible in the current tool set.
92
73
  - Prefer broad guidance such as "use paper search and web search"; if a PDF parser or paper fetch fails, the researcher must continue from metadata, abstracts, and web sources and mark PDF parsing as blocked.
93
74
 
94
75
  Example shape:
@@ -169,8 +150,6 @@ Consume the review completion result and locate its returned output before proce
169
150
 
170
151
  When applying reviewer fixes, do not issue one giant `edit` tool call with many replacements. Use small localized edits only for 1-3 simple corrections. For section rewrites, table rewrites, or more than 3 substantive fixes, read the cited draft and write a corrected full file to `outputs/.drafts/<slug>-revised.md` instead.
171
152
 
172
- After applying reviewer, verifier, audit, or PI-style fixes, run an explicit on-disk verification before saying the fixes landed. Use `rg`, `grep`, `diff`, `wc`, `stat`, or a targeted read to prove the old unsupported wording is gone and the replacement wording exists. If an `edit` or `write` tool call fails, do not describe the fix as applied; record the failure in the plan/provenance, retry with a smaller edit or a full corrected file, and verify again. Provenance may only say an issue was fixed when this post-edit verification passed.
173
-
174
153
  The final candidate is `outputs/.drafts/<slug>-revised.md` if it exists; otherwise it is `outputs/.drafts/<slug>-cited.md`.
175
154
 
176
155
  ## Step 7: Deliver
@@ -196,6 +175,4 @@ Write provenance next to it as `<slug>.provenance.md`:
196
175
 
197
176
  Before responding, verify on disk that all required artifacts exist. If verification could not be completed, set `Verification: BLOCKED` or `PASS WITH NOTES` and list the missing checks.
198
177
 
199
- Before responding, also verify that any fixes claimed in the provenance are reflected in the final candidate. If a fix removed a phrase, number, source, or claim, run a targeted `rg`/`grep` check for the removed content and a second check for the corrected content. Do not claim "all patches applied", "all checks pass", or "fixed" unless these commands or reads succeed.
200
-
201
178
  Final response should be brief: link the final file, provenance file, and any blocked checks.
package/prompts/draft.md CHANGED
@@ -4,17 +4,6 @@ args: <topic>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Write a paper-style draft for: $@
19
8
 
20
9
  Derive a short slug from the topic (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
@@ -25,7 +14,7 @@ Requirements:
25
14
  - Include at minimum: title, abstract, problem statement, related work, method or synthesis, evidence or experiments, limitations, conclusion.
26
15
  - Use clean Markdown with LaTeX where equations materially help.
27
16
  - Follow the system prompt's provenance rules for all results, figures, charts, images, tables, benchmarks, and quantitative comparisons. If evidence is missing, leave a placeholder or proposed experimental plan instead of claiming an outcome.
28
- - Generate charts only when a chart tool is visible and the underlying source-backed quantitative data, benchmarks, or comparisons support the visual; otherwise write a chart specification or table. Use Mermaid for architectures and pipelines only when the structure is supported by sources. Every figure, chart spec, or table needs provenance.
17
+ - Use Markdown tables for quantitative comparisons and Mermaid for architectures and pipelines. Plot only source-backed data, and save the plotting script next to the draft. Every figure or table needs provenance.
29
18
  - Before delivery, sweep the draft for any claim that sounds stronger than its support. Mark tentative results as tentative and remove unsupported numerics instead of letting the verifier discover them later.
30
19
  - Save exactly one draft to `papers/<slug>.md`.
31
20
  - End with a `Sources` appendix with direct URLs for all primary references.
package/prompts/lit.md CHANGED
@@ -4,17 +4,6 @@ args: <topic-or-lab-or-author>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Investigate the following topic, lab, PI, or author as a literature review: $@
19
8
 
20
9
  Derive a short slug from the topic (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
@@ -24,7 +13,7 @@ Derive a short slug from the topic (lowercase, hyphens, no filler words, ≤5 wo
24
13
  1. **Plan** — Outline the scope: key questions, source types to search (papers, web, repos), time period, expected sections, and a small task ledger plus verification log. When the input appears to name a lab, PI, author, institution lab page, or author profile, run the review as a publication-corpus review: find the lab/author identity first, collect the reachable publication list, then map the research trajectory across that corpus. Write the plan to `outputs/.plans/<slug>.md`. Briefly summarize the plan to the user and continue immediately in the same turn with the next tool call; never end a turn with a message that only announces what you will do next. Do not ask for confirmation or wait for a proceed response unless the user explicitly requested plan review.
25
14
  - When updating the plan ledger later, keep edits small and valid. If an `edit` tool call fails with a JSON parse error or the replacement would require embedding a large markdown block, rewrite the full corrected plan file with the file-writing tool instead, then continue to final artifact/provenance verification.
26
15
  2. **Gather** — Use the `researcher` subagent when the sweep is wide enough to benefit from delegated paper triage before synthesis. For narrow topics, search directly. Researcher outputs go to `<slug>-research-*.md`. For publication-corpus reviews, the lead agent owns identity resolution and writes `notes/<slug>-publications.md` with reachable titles, years, venues, URLs/DOIs, and gaps before delegating trajectory synthesis. Prefer lab publication pages, author profiles, arXiv/OpenReview/Semantic Scholar pages, and paper search results that expose stable source URLs. Do not silently skip assigned questions; mark them `done`, `blocked`, or `superseded`.
27
- 3. **Synthesize** — Separate consensus, disagreements, and open questions. For publication-corpus reviews, also identify 3-5 research trajectories and the 3-5 papers that most changed the corpus direction; rank them by contrastive originality, methodology strength, and relationship to prior art rather than by author prestige alone. When useful, propose concrete next experiments or follow-up reading. Generate charts only when a chart tool is visible and the data is source-backed; otherwise include a chart specification or comparison table. Use Mermaid diagrams for taxonomies, method pipelines, or lab trajectory maps when the structure is source-supported and changes the reader's research decision. Keep the output to research evidence, source coverage, and next research decisions; do not create non-research operational artifacts from a literature review run.
16
+ 3. **Synthesize** — Separate consensus, disagreements, and open questions. For publication-corpus reviews, also identify 3-5 research trajectories and the 3-5 papers that most changed the corpus direction; rank them by contrastive originality, methodology strength, and relationship to prior art rather than by author prestige alone. When useful, propose concrete next experiments or follow-up reading. Use Mermaid diagrams for taxonomies, method pipelines, or lab trajectory maps when the structure is source-supported and changes the reader's research decision. Keep the output to research evidence, source coverage, and next research decisions; do not create non-research operational artifacts from a literature review run.
28
17
  4. **Cite** — Spawn the `verifier` agent to add inline citations and verify every source URL in the draft.
29
18
  5. **Verify** — Spawn the `reviewer` agent to check the cited draft for unsupported claims, logical gaps, zombie sections, and single-source critical findings. Fix FATAL issues before delivering. Note MAJOR issues in Open Questions. If FATAL issues were found, run one more verification pass after the fixes.
30
19
  6. **Deliver** — Save the final literature review to `outputs/<slug>.md`. Write a provenance record alongside it as `outputs/<slug>.provenance.md` listing: date, sources consulted vs. accepted vs. rejected, verification status, and intermediate research files used; for publication-corpus reviews, include the publication-log path and unresolved corpus gaps. Before you stop, verify on disk that both files exist; do not stop at an intermediate cited draft alone.
package/prompts/log.md CHANGED
@@ -3,17 +3,6 @@ description: Write a durable session log with completed work, findings, open que
3
3
  section: Project & Session
4
4
  topLevelCli: true
5
5
  ---
6
- ## Tool Discipline (Read First)
7
-
8
- Tool names are literal. Use only tools visible in the current tool set.
9
-
10
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
11
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
12
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
13
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
14
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
15
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
16
-
17
6
  Write a session log for the current research work.
18
7
 
19
8
  Requirements:
package/prompts/recipe.md CHANGED
@@ -4,23 +4,10 @@ args: <task-or-paper>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Find implementable ML training recipes for: $@
19
8
 
20
9
  Derive a short slug from the task (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
21
10
 
22
- This is an execution request, not a request to explain the workflow. Continue immediately.
23
-
24
11
  ## Required artifacts
25
12
 
26
13
  - `outputs/.plans/<slug>-recipe.md`
@@ -4,17 +4,6 @@ args: <paper>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Design a replication plan for: $@
19
8
 
20
9
  ## Workflow
package/prompts/review.md CHANGED
@@ -4,23 +4,10 @@ args: <artifact>
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Review this AI research artifact: $@
19
8
 
20
9
  Derive a short slug from the artifact name (lowercase, hyphens, no filler words, ≤5 words). Use this slug for all files in this run.
21
10
 
22
- This is an execution request, not a request to explain or implement the workflow instructions. Carry out the workflow with tools and durable files. Do not answer by describing the protocol, saying what you would do, or stopping after a plan.
23
-
24
11
  Do not ask for confirmation. Briefly summarize the plan to the user and continue immediately unless the user explicitly asked to review the plan first.
25
12
 
26
13
  Required artifacts:
@@ -4,17 +4,6 @@ args: <source> [--window-size <chars>] [--overlap <chars>] [--tier1-threshold <c
4
4
  section: Research Workflows
5
5
  topLevelCli: true
6
6
  ---
7
- ## Tool Discipline (Read First)
8
-
9
- Tool names are literal. Use only tools visible in the current tool set.
10
-
11
- - Search with `web_search`; do not call `search_web`, `google_search`, `google:search`, `search_google`, or `WebSearch`.
12
- - Fetch URLs with `fetch_content`; do not call bare `fetch`, `WebFetch`, `read_url_content`, or pass an array as `url`. Use `urls` for multiple URLs when the tool supports it.
13
- - Use visible Feynman alpha tools such as `alpha_search` when present. For shell access, call `feynman alpha ...`; do not call the user's bare global `alpha` binary.
14
- - To ask the user a question, write plain chat text and wait for the next user message. Do not call `ask_user_question`, `ask_user`, `ask_followup_question`, or `user_choice`.
15
- - Do not use `Task` as an agent dispatcher. Use only the visible `subagent` tool when it exists.
16
- - If a tool returns `Tool not found` or `Invalid URL`, do not retry the same invalid call. Map to a canonical visible tool and valid arguments, or record the capability as blocked.
17
-
18
7
  Summarize the following research source: $@
19
8
 
20
9
  Derive a short slug from the source filename or URL domain (lowercase, hyphens, no filler words, ≤5 words — e.g. `attention-is-all-you-need`). Use this slug for all files in this run.
@@ -27,15 +16,12 @@ Tier 1 (below the Tier-1 threshold) is a deliberate exception: direct injection
27
16
 
28
17
  ## Runtime knobs (context-window controls)
29
18
 
30
- Support both inline flags and environment variables so users can tune context-window behavior per run or globally.
31
-
32
- - `--window-size <chars>` or `FEYNMAN_SUMMARIZE_WINDOW_CHARS` (default: `6000`)
33
- - `--overlap <chars>` or `FEYNMAN_SUMMARIZE_OVERLAP_CHARS` (default: `500`)
34
- - `--tier1-threshold <chars>` or `FEYNMAN_SUMMARIZE_TIER1_THRESHOLD` (default: `8000`)
35
- - `--tier2-threshold <chars>` or `FEYNMAN_SUMMARIZE_TIER2_THRESHOLD` (default: `60000`)
19
+ - `--window-size <chars>` (default: `6000`)
20
+ - `--overlap <chars>` (default: `500`)
21
+ - `--tier1-threshold <chars>` (default: `8000`)
22
+ - `--tier2-threshold <chars>` (default: `60000`)
36
23
 
37
24
  Rules:
38
- - Inline flags override environment variables.
39
25
  - Validate `window-size > overlap` and `tier1-threshold < tier2-threshold`; if invalid, stop and report a clear configuration error.
40
26
  - Log resolved values once per run: `[summarize] config window=<w> overlap=<o> tier1=<t1> tier2=<t2>`.
41
27