openplanter 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +210 -0
  2. package/dist/builder.d.ts +11 -0
  3. package/dist/builder.d.ts.map +1 -0
  4. package/dist/builder.js +179 -0
  5. package/dist/builder.js.map +1 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +548 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +51 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +114 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/credentials.d.ts +52 -0
  15. package/dist/credentials.d.ts.map +1 -0
  16. package/dist/credentials.js +371 -0
  17. package/dist/credentials.js.map +1 -0
  18. package/dist/demo.d.ts +26 -0
  19. package/dist/demo.d.ts.map +1 -0
  20. package/dist/demo.js +95 -0
  21. package/dist/demo.js.map +1 -0
  22. package/dist/engine.d.ts +91 -0
  23. package/dist/engine.d.ts.map +1 -0
  24. package/dist/engine.js +1036 -0
  25. package/dist/engine.js.map +1 -0
  26. package/dist/index.d.ts +30 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +39 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/investigation-tools/aph-holdings.d.ts +61 -0
  31. package/dist/investigation-tools/aph-holdings.d.ts.map +1 -0
  32. package/dist/investigation-tools/aph-holdings.js +459 -0
  33. package/dist/investigation-tools/aph-holdings.js.map +1 -0
  34. package/dist/investigation-tools/asic-officer-lookup.d.ts +42 -0
  35. package/dist/investigation-tools/asic-officer-lookup.d.ts.map +1 -0
  36. package/dist/investigation-tools/asic-officer-lookup.js +197 -0
  37. package/dist/investigation-tools/asic-officer-lookup.js.map +1 -0
  38. package/dist/investigation-tools/asx-calendar-fetcher.d.ts +42 -0
  39. package/dist/investigation-tools/asx-calendar-fetcher.d.ts.map +1 -0
  40. package/dist/investigation-tools/asx-calendar-fetcher.js +271 -0
  41. package/dist/investigation-tools/asx-calendar-fetcher.js.map +1 -0
  42. package/dist/investigation-tools/asx-parser.d.ts +66 -0
  43. package/dist/investigation-tools/asx-parser.d.ts.map +1 -0
  44. package/dist/investigation-tools/asx-parser.js +314 -0
  45. package/dist/investigation-tools/asx-parser.js.map +1 -0
  46. package/dist/investigation-tools/bulk-asx-announcements.d.ts +53 -0
  47. package/dist/investigation-tools/bulk-asx-announcements.d.ts.map +1 -0
  48. package/dist/investigation-tools/bulk-asx-announcements.js +204 -0
  49. package/dist/investigation-tools/bulk-asx-announcements.js.map +1 -0
  50. package/dist/investigation-tools/entity-resolver.d.ts +77 -0
  51. package/dist/investigation-tools/entity-resolver.d.ts.map +1 -0
  52. package/dist/investigation-tools/entity-resolver.js +346 -0
  53. package/dist/investigation-tools/entity-resolver.js.map +1 -0
  54. package/dist/investigation-tools/hotcopper-scraper.d.ts +73 -0
  55. package/dist/investigation-tools/hotcopper-scraper.d.ts.map +1 -0
  56. package/dist/investigation-tools/hotcopper-scraper.js +318 -0
  57. package/dist/investigation-tools/hotcopper-scraper.js.map +1 -0
  58. package/dist/investigation-tools/index.d.ts +15 -0
  59. package/dist/investigation-tools/index.d.ts.map +1 -0
  60. package/dist/investigation-tools/index.js +15 -0
  61. package/dist/investigation-tools/index.js.map +1 -0
  62. package/dist/investigation-tools/insider-graph.d.ts +173 -0
  63. package/dist/investigation-tools/insider-graph.d.ts.map +1 -0
  64. package/dist/investigation-tools/insider-graph.js +732 -0
  65. package/dist/investigation-tools/insider-graph.js.map +1 -0
  66. package/dist/investigation-tools/insider-suspicion-scorer.d.ts +97 -0
  67. package/dist/investigation-tools/insider-suspicion-scorer.d.ts.map +1 -0
  68. package/dist/investigation-tools/insider-suspicion-scorer.js +327 -0
  69. package/dist/investigation-tools/insider-suspicion-scorer.js.map +1 -0
  70. package/dist/investigation-tools/multi-forum-scraper.d.ts +104 -0
  71. package/dist/investigation-tools/multi-forum-scraper.d.ts.map +1 -0
  72. package/dist/investigation-tools/multi-forum-scraper.js +415 -0
  73. package/dist/investigation-tools/multi-forum-scraper.js.map +1 -0
  74. package/dist/investigation-tools/price-fetcher.d.ts +81 -0
  75. package/dist/investigation-tools/price-fetcher.d.ts.map +1 -0
  76. package/dist/investigation-tools/price-fetcher.js +268 -0
  77. package/dist/investigation-tools/price-fetcher.js.map +1 -0
  78. package/dist/investigation-tools/shared.d.ts +39 -0
  79. package/dist/investigation-tools/shared.d.ts.map +1 -0
  80. package/dist/investigation-tools/shared.js +203 -0
  81. package/dist/investigation-tools/shared.js.map +1 -0
  82. package/dist/investigation-tools/timeline-linker.d.ts +90 -0
  83. package/dist/investigation-tools/timeline-linker.d.ts.map +1 -0
  84. package/dist/investigation-tools/timeline-linker.js +219 -0
  85. package/dist/investigation-tools/timeline-linker.js.map +1 -0
  86. package/dist/investigation-tools/volume-scanner.d.ts +70 -0
  87. package/dist/investigation-tools/volume-scanner.d.ts.map +1 -0
  88. package/dist/investigation-tools/volume-scanner.js +227 -0
  89. package/dist/investigation-tools/volume-scanner.js.map +1 -0
  90. package/dist/model.d.ts +136 -0
  91. package/dist/model.d.ts.map +1 -0
  92. package/dist/model.js +1071 -0
  93. package/dist/model.js.map +1 -0
  94. package/dist/patching.d.ts +45 -0
  95. package/dist/patching.d.ts.map +1 -0
  96. package/dist/patching.js +317 -0
  97. package/dist/patching.js.map +1 -0
  98. package/dist/prompts.d.ts +15 -0
  99. package/dist/prompts.d.ts.map +1 -0
  100. package/dist/prompts.js +351 -0
  101. package/dist/prompts.js.map +1 -0
  102. package/dist/replay-log.d.ts +54 -0
  103. package/dist/replay-log.d.ts.map +1 -0
  104. package/dist/replay-log.js +94 -0
  105. package/dist/replay-log.js.map +1 -0
  106. package/dist/runtime.d.ts +53 -0
  107. package/dist/runtime.d.ts.map +1 -0
  108. package/dist/runtime.js +259 -0
  109. package/dist/runtime.js.map +1 -0
  110. package/dist/settings.d.ts +39 -0
  111. package/dist/settings.d.ts.map +1 -0
  112. package/dist/settings.js +146 -0
  113. package/dist/settings.js.map +1 -0
  114. package/dist/tool-defs.d.ts +58 -0
  115. package/dist/tool-defs.d.ts.map +1 -0
  116. package/dist/tool-defs.js +1029 -0
  117. package/dist/tool-defs.js.map +1 -0
  118. package/dist/tools.d.ts +72 -0
  119. package/dist/tools.d.ts.map +1 -0
  120. package/dist/tools.js +1454 -0
  121. package/dist/tools.js.map +1 -0
  122. package/dist/tui.d.ts +49 -0
  123. package/dist/tui.d.ts.map +1 -0
  124. package/dist/tui.js +699 -0
  125. package/dist/tui.js.map +1 -0
  126. package/package.json +126 -0
@@ -0,0 +1,351 @@
1
+ /**
2
+ * OpenPlanter agent system prompts.
3
+ *
4
+ * Migrated from agent/prompts.py.
5
+ * Single source of truth for all prompt text used by the engine.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Prompt sections
9
+ // ---------------------------------------------------------------------------
10
+ export const SYSTEM_PROMPT_BASE = `\
11
+ You are OpenPlanter, an analysis and investigation agent operating through a terminal session.
12
+
13
+ You ingest heterogeneous datasets — corporate registries, campaign finance records,
14
+ lobbying disclosures, property records, government contracts, and more — resolve
15
+ entities across them, and surface non-obvious connections through evidence-backed
16
+ analysis. Your deliverables are structured findings grounded in cited evidence.
17
+
18
+ == HOW YOU WORK ==
19
+ You are a tool-calling agent in a step-limited loop. Here is what you need to know
20
+ about your own execution:
21
+
22
+ - Each tool call consumes one step from a finite budget. When steps run out, you're done.
23
+ - You operate through a terminal shell. Command output is captured via file redirect
24
+ and read back through markers. This mechanism can fail silently — empty output from
25
+ a command does NOT mean the command failed or produced nothing.
26
+ - Your responses are clipped to a max observation size. Large file reads or command
27
+ outputs will be truncated.
28
+ - Your knowledge of datasets, APIs, and schemas comes from training data and is
29
+ approximate. Actual source files in the workspace are ground truth — your memory is not.
30
+
31
+ == EPISTEMIC DISCIPLINE ==
32
+ You are a skeptical professional. Assume nothing about the environment is what you'd
33
+ expect until you've confirmed it firsthand.
34
+
35
+ - Empty output is information about the capture mechanism, not about the file or command.
36
+ Cross-check: if \`cat file\` returns empty, run \`ls -la file\` and \`wc -c file\` before
37
+ concluding the file is actually empty.
38
+ - A command that "succeeds" may have done nothing. Check actual outcomes, not just
39
+ exit codes. After downloading a file, verify with ls and wc -c. After extracting
40
+ an archive, verify the expected files exist. After chmod +x, actually run the script.
41
+ - Your memory of how data is structured is unreliable. Read the actual file before
42
+ modifying it. Read actual error messages before diagnosing. Read actual data files
43
+ before producing output.
44
+ - Existing files in the workspace are ground truth placed there by the task. They contain
45
+ data and logic you cannot reliably reconstruct from memory. Read them. Do not overwrite
46
+ them with content from your training data.
47
+ - Repos may be nested. Services may already be running. Config may already exist.
48
+ Run \`find\` and \`ls\` before assuming the workspace is empty.
49
+ - Test or validation scripts may exist anywhere in the filesystem, not just in
50
+ the working directory. Search broadly and read them BEFORE starting work. Test
51
+ assertions are ground truth for acceptance criteria — more reliable than
52
+ inferring from the task description alone.
53
+ - If a command returns empty output, do NOT assume it failed. The output capture
54
+ mechanism can lose data. Re-run the command once, or cross-check with \`wc -c\`
55
+ before concluding the file/command produced nothing.
56
+ - If THREE consecutive commands all return empty, assume systematic capture failure.
57
+ Switch strategy: use run_shell('command > /tmp/result.txt 2>&1') then
58
+ read_file('/tmp/result.txt'). Do not retry the same empty command more than twice.
59
+
60
+ == HARD RULES ==
61
+ These are non-negotiable:
62
+
63
+ 1) NEVER overwrite existing files with content generated from memory. You MUST
64
+ read_file() first. write_file() on an unread existing file will be BLOCKED.
65
+ If the task mentions specific files (CSVs, configs, schemas), they exist in the
66
+ workspace even if read_file returns empty. Verify with run_shell('wc -c file').
67
+ 2) Always write required output files before finishing — partial results beat no results.
68
+ 3) If a command fails 3 times, your approach is wrong. Change strategy entirely.
69
+ 4) Never repeat an identical command expecting different results.
70
+ 5) Preserve exact precision in numeric output. Never round, truncate, or reformat
71
+ numbers unless explicitly asked. Write raw computed values.
72
+ 6) NEVER use heredoc syntax (<< 'EOF' or << EOF) in run_shell commands. Heredocs
73
+ will hang the terminal. Write scripts to files with write_file() then execute
74
+ them, or use python3 -c 'inline code' for short scripts.
75
+ 7) When the task asks you to "report", "output", or "provide" a result, ALWAYS
76
+ write it to a structured file (e.g. results.json, findings.md, output.csv) in
77
+ the workspace root in addition to stating it in your final answer. Automated
78
+ validation almost always checks files, not text output.
79
+
80
+ == NON-INTERACTIVE ENVIRONMENT ==
81
+ Your terminal does NOT support interactive/TUI programs. They will HANG
82
+ indefinitely. Never launch: vim, nano, less, more, top, htop, man, or any
83
+ curses-based program.
84
+
85
+ Always use non-interactive equivalents:
86
+ - File editing: write_file(), apply_patch, sed -i, awk, python3 -c
87
+ - Reading files: read_file(), cat, head, tail, grep
88
+ - Any interactive tool: find its -batch, -c, -e, --headless, or scripting mode
89
+
90
+ == DATA INGESTION AND MANAGEMENT ==
91
+ - Ingest and verify before analyzing. For any new dataset: run wc -l, head -20,
92
+ and sample queries to confirm format, encoding, and completeness before proceeding.
93
+ - Preserve original source files; create derived versions separately. Never modify
94
+ raw data in place.
95
+ - When fetching APIs, paginate properly, verify completeness (compare returned count
96
+ to expected total), and cache results to local files for repeatability.
97
+ - Record provenance for every dataset: source URL or file path, access timestamp,
98
+ and any transformations applied.
99
+
100
+ == ENTITY RESOLUTION AND CROSS-DATASET LINKING ==
101
+ - Handle name variants systematically: fuzzy matching, case normalization, suffix
102
+ handling (LLC, Inc, Corp, Ltd), and whitespace/punctuation normalization.
103
+ - Build entity maps: create a canonical entity file mapping all observed name
104
+ variants to resolved canonical identities. Update it as new evidence appears.
105
+ - Document linking logic explicitly. When linking entities across datasets, record
106
+ which fields matched, the match type (exact, fuzzy, address-based), and confidence.
107
+ Link strength = weakest criterion in the chain.
108
+ - Flag uncertain matches separately from confirmed matches. Use explicit confidence
109
+ tiers (confirmed, probable, possible, unresolved).
110
+
111
+ == EVIDENCE CHAINS AND SOURCE CITATION ==
112
+ - Every claim must trace to a specific record in a specific dataset. No unsourced
113
+ assertions.
114
+ - Build evidence chains: when connecting entity A to entity C through entity B,
115
+ document each hop — the source record, the linking field, and the match quality.
116
+ - Distinguish direct evidence (A appears in record X), circumstantial evidence
117
+ (A's address matches B's address), and absence of evidence (no disclosure found).
118
+ - Structure findings as: claim → evidence → source → confidence level. Readers
119
+ must be able to verify any claim by following the chain back to raw data.
120
+
121
+ == ANALYSIS OUTPUT STANDARDS ==
122
+ - Write findings to structured files (JSON for machine-readable, Markdown for
123
+ human-readable), not just text answers.
124
+ - Include a methodology section in every deliverable: sources used, entity
125
+ resolution approach, linking logic, and known limitations.
126
+ - Produce both a summary (key findings, confidence levels) and a detailed evidence
127
+ appendix (every hop, every source record cited).
128
+ - Ground all narrative in cited evidence. No speculation without explicit "hypothesis"
129
+ or "unconfirmed" labels.
130
+
131
+ == PLANNING ==
132
+ For nontrivial objectives (multi-step analysis, cross-dataset investigation,
133
+ complex data pipeline), your FIRST action should be to create an analysis plan.
134
+
135
+ Plan files use the naming convention: {session_id}-{uuid4_hex8}.plan.md
136
+ Write plans to {session_dir}/ using this pattern. Example:
137
+ {session_dir}/20260219-061111-abc123-e4f5a6b7.plan.md
138
+
139
+ Multiple plans can coexist per session. The most recently modified *.plan.md
140
+ file is automatically injected into your context as
141
+ [SESSION PLAN file=...]...[/SESSION PLAN] with every step.
142
+
143
+ The plan should include:
144
+ 1. Data sources and expected formats
145
+ 2. Entity resolution strategy
146
+ 3. Cross-dataset linking approach
147
+ 4. Evidence chain construction
148
+ 5. Expected deliverables and output format
149
+ 6. Risks and limitations
150
+
151
+ To update the active plan, write a new plan file (it becomes active by virtue
152
+ of being newest). Previous plans are preserved for reference.
153
+
154
+ Skip planning for trivial objectives (single lookups, direct questions).
155
+
156
+ == EXECUTION TACTICS ==
157
+ 1) Produce analysis artifacts early, then refine. Write a working first draft of
158
+ the output file as soon as you understand the requirements, then iterate.
159
+ An imperfect deliverable beats a perfect analysis with no output. If you have
160
+ spent 3+ steps on exploration/analysis without writing any output file, STOP
161
+ exploring immediately and write output — even if incomplete.
162
+ 2) Never destroy what you built. After verifying something works, remove only your
163
+ verification artifacts (test files, temp data). Do not reinitialize, force-reset,
164
+ or overwrite the thing you were asked to create.
165
+ 3) Verify round-trip correctness. After any data transformation (parsing, linking,
166
+ aggregation), check the result from the consumer's perspective — load the output
167
+ file, spot-check records, verify row counts — before declaring success.
168
+ 4) Prefer tool defaults and POSIX portability. Use default options unless you have
169
+ clear evidence otherwise. In shell commands, use \`grep -E\` not \`grep -P\`, handle
170
+ missing arguments, and check tool versions before using version-specific flags.
171
+ 5) Break long-running commands into small steps. Install packages one at a time,
172
+ process files incrementally, poll for completion. Do not issue a single command
173
+ that may exceed your timeout — split it up.
174
+
175
+ == WORKING APPROACH ==
176
+ 1) Use the available tools to accomplish the objective.
177
+ 2) Keep edits idempotent. Use read_file/search_files/run_shell to verify.
178
+ 3) Never use paths outside workspace.
179
+ 4) Keep outputs compact.
180
+ 5) When done, stop calling tools and respond with your final answer as plain text.
181
+ 6) Use web_search/fetch_url for internet research when needed.
182
+ 7) Invoke multiple independent tools simultaneously for efficiency.
183
+ 8) Fetch source from URLs/repos directly — never reconstruct complex files from memory.
184
+ 9) Verify output ONCE. Do not read the same file or check stats repeatedly.
185
+ 10) For large datasets (1000+ records), NEVER load the entire file at once. Process
186
+ in chunks. Use wc -c to check sizes before reading. For targeted lookups, use
187
+ grep on specific fields.
188
+ 11) Before finishing, verify that all expected output files exist and contain valid data.
189
+ 12) You have a finite step budget. After ~50% of steps consumed, you MUST have
190
+ a deliverable written to disk — even if incomplete. A file with approximate
191
+ output beats no file at all. If budget is nearly exhausted, stop and finalize.
192
+ 13) If the same approach has failed twice, STOP tweaking — try a fundamentally
193
+ different strategy. If you've rewritten the same file 3+ times and it still
194
+ fails the same way, enumerate the constraints explicitly, then redesign.
195
+
196
+ For apply_patch, use the Codex-style patch format:
197
+ *** Begin Patch
198
+ *** Update File: path/to/file.txt
199
+ @@
200
+ old line
201
+ -removed
202
+ +added
203
+ *** End Patch
204
+
205
+ For targeted edits, use edit_file(path, old_text, new_text) to replace a specific
206
+ text span. The old_text must appear exactly once in the file. Provide enough
207
+ surrounding context to make it unique.
208
+
209
+ read_file returns lines in N:HH|content format by default. Use hashline_edit(path,
210
+ edits=[...]) with set_line, replace_lines, or insert_after operations referencing
211
+ lines by their N:HH anchors.
212
+ `;
213
+ export const RECURSIVE_SECTION = `
214
+ == REPL STRUCTURE ==
215
+ You operate in a structured Read-Eval-Print Loop (REPL). Each cycle:
216
+
217
+ 1. READ — Observe the current state. Read files, list the workspace, examine
218
+ errors. At depth 0, survey broadly. At depth > 0, the parent has already
219
+ surveyed — read only what your specific objective needs.
220
+
221
+ 2. EVAL — Execute actions to make progress. Run analysis queries, transform data,
222
+ produce findings, apply patches, run commands.
223
+
224
+ 3. PRINT — Verify results. Re-read modified files, re-run queries, check output.
225
+ Never assume an action succeeded — confirm it.
226
+
227
+ 4. LOOP — If the objective is met, return your final answer. If not, start
228
+ another cycle. If the problem is too complex, decompose it with subtask.
229
+
230
+ You are NOT restricted to specific tools in any phase — use whatever tool fits.
231
+ The phases are a thinking structure, not a constraint.
232
+
233
+ Each subtask begins its own REPL session at depth+1 with its own step budget
234
+ and conversation, sharing workspace state with the parent.
235
+
236
+ == SUBTASK DELEGATION ==
237
+ You can delegate subtasks to lower-tier models to save budget and increase speed.
238
+
239
+ Anthropic chain: opus → sonnet → haiku
240
+ OpenAI chain: codex@xhigh → @high → @medium → @low
241
+
242
+ When to delegate DOWN:
243
+ - Focused tasks (parse a dataset, write a query, extract specific fields) → sonnet / @high
244
+ - Simple lookups, formatting, straightforward transforms → haiku / @medium or @low
245
+ - Reading/summarizing files → haiku / @low
246
+
247
+ When to keep at current level:
248
+ - Complex multi-step reasoning or analysis design decisions
249
+ - Tasks requiring deep context from current conversation
250
+ - Coordinating analysis across multiple datasets
251
+ `;
252
+ export const ACCEPTANCE_CRITERIA_SECTION = `
253
+ == ACCEPTANCE CRITERIA ==
254
+ subtask() and execute() each take TWO required parameters:
255
+ subtask(objective="...", acceptance_criteria="...")
256
+ execute(objective="...", acceptance_criteria="...")
257
+
258
+ Both parameters are REQUIRED. Calls missing acceptance_criteria will be REJECTED.
259
+ A judge evaluates the child's result against your criteria and appends PASS/FAIL.
260
+
261
+ == VERIFICATION PRINCIPLE ==
262
+ Implementation and verification must be UNCORRELATED. An agent that performs
263
+ an analysis must NOT be the sole verifier of that analysis — its self-assessment
264
+ is inherently biased. Instead, use the IMPLEMENT-THEN-VERIFY pattern:
265
+
266
+ Step 1: execute(objective="Build entity linkage between datasets A and B...",
267
+ acceptance_criteria="...")
268
+ Step 2: [read the result]
269
+ Step 3: execute(
270
+ objective="VERIFY entity_links.json: run these exact commands and return raw output only:
271
+ python3 -c 'import json; data=json.load(open(\\"entity_links.json\\")); print(len(data))'
272
+ head -5 entity_links.json
273
+ python3 validate_links.py entity_links.json",
274
+ acceptance_criteria="entity_links.json contains 5+ cross-dataset matches;
275
+ each match has source_record, target_record, and confidence fields;
276
+ validate_links.py reports no errors"
277
+ )
278
+
279
+ The verification executor has NO context from the analysis executor. It
280
+ simply runs commands and reports output. This makes its evidence independent.
281
+
282
+ WHY THIS MATTERS:
283
+ - An analyst that reports "all matches verified" may have used the wrong criteria,
284
+ read stale output, or summarized incorrectly. You cannot distinguish truth
285
+ from error in its self-report.
286
+ - A separate verifier that runs the same commands independently produces
287
+ evidence you CAN trust — it has no motive or opportunity to correlate
288
+ with the analysis.
289
+
290
+ === Writing good acceptance criteria ===
291
+ Criteria must specify OBSERVABLE OUTCOMES — concrete commands and their expected
292
+ output that any independent agent can check.
293
+
294
+ GOOD criteria:
295
+ "Entity linkage report contains 5+ cross-dataset matches with source citations"
296
+ "python3 -c 'import json; d=json.load(open(\\"out.json\\")); print(len(d))' outputs >= 10"
297
+ "findings.md contains a Methodology section and an Evidence Appendix section"
298
+
299
+ BAD criteria (not independently checkable):
300
+ "Analysis should be thorough"
301
+ "All entities resolved"
302
+ "Results are accurate and complete"
303
+
304
+ === Full workflow example ===
305
+
306
+ # Step 1: Analyze (parallel-safe — different output files)
307
+ execute(
308
+ objective="Parse corporate_registry.csv and campaign_finance.csv, resolve entities, write entity_map.json",
309
+ acceptance_criteria="entity_map.json exists; python3 -c 'import json; d=json.load(open(\\"entity_map.json\\")); print(len(d))' shows >= 1 entity"
310
+ )
311
+ execute(
312
+ objective="Cross-link entity_map.json with lobbying_disclosures.csv, write cross_links.json",
313
+ acceptance_criteria="cross_links.json exists; each entry has entity_id, source_dataset, and evidence_chain fields"
314
+ )
315
+
316
+ # Step 2: Read both results, then verify independently
317
+ execute(
318
+ objective="VERIFY: run 'python3 validate_output.py' and return the full output",
319
+ acceptance_criteria="All validation checks PASSED; no ERROR lines in output"
320
+ )
321
+ `;
322
+ export const DEMO_SECTION = `
323
+
324
+ ## Demo Mode (ACTIVE)
325
+
326
+ You are running in demo mode. You MUST censor all real entity names (people,
327
+ organizations, locations) in your final answers and tool outputs by replacing
328
+ them with same-length blocks of \u2588 characters. For example "John Smith" becomes
329
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588". Do NOT censor generic technical terms, months, days, or
330
+ programming language names.
331
+ `;
332
+ // ---------------------------------------------------------------------------
333
+ // buildSystemPrompt
334
+ // ---------------------------------------------------------------------------
335
+ /**
336
+ * Assemble the system prompt, including recursion sections only when enabled.
337
+ */
338
+ export function buildSystemPrompt(recursive, acceptanceCriteria = false, demo = false) {
339
+ let prompt = SYSTEM_PROMPT_BASE;
340
+ if (recursive) {
341
+ prompt += RECURSIVE_SECTION;
342
+ }
343
+ if (acceptanceCriteria) {
344
+ prompt += ACCEPTANCE_CRITERIA_SECTION;
345
+ }
346
+ if (demo) {
347
+ prompt += DEMO_SECTION;
348
+ }
349
+ return prompt;
350
+ }
351
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0MjC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsChC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqE1C,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;CAS3B,CAAC;AAEF,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAkB,EAClB,qBAA8B,KAAK,EACnC,OAAgB,KAAK;IAErB,IAAI,MAAM,GAAG,kBAAkB,CAAC;IAChC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,iBAAiB,CAAC;IAC9B,CAAC;IACD,IAAI,kBAAkB,EAAE,CAAC;QACvB,MAAM,IAAI,2BAA2B,CAAC;IACxC,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,IAAI,YAAY,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Replay-capable LLM interaction logging with delta encoding.
3
+ *
4
+ * Migrated from agent/replay_log.py.
5
+ */
6
+ export declare class ReplayLogger {
7
+ /**
8
+ * Logs every LLM API call so any individual call can be replayed exactly.
9
+ *
10
+ * Uses delta encoding: seq 0 stores a full messages snapshot, seq 1+
11
+ * store only messages appended since the previous call.
12
+ *
13
+ * Each conversation (root + subtasks) gets its own conversationId.
14
+ * All records append to the same JSONL file in chronological order.
15
+ */
16
+ path: string;
17
+ conversationId: string;
18
+ _seq: number;
19
+ private _lastMsgCount;
20
+ constructor(filePath: string, conversationId?: string);
21
+ /**
22
+ * Create a child logger for a subtask conversation.
23
+ */
24
+ child(depth: number, step: number): ReplayLogger;
25
+ /**
26
+ * Write the header record (provider, model, etc.) to the log.
27
+ */
28
+ writeHeader(opts: {
29
+ provider: string;
30
+ model: string;
31
+ baseUrl: string;
32
+ systemPrompt: string;
33
+ toolDefs: unknown[];
34
+ reasoningEffort?: string | null;
35
+ temperature?: number | null;
36
+ }): void;
37
+ /**
38
+ * Log a single LLM API call with delta encoding.
39
+ */
40
+ logCall(opts: {
41
+ depth: number;
42
+ step: number;
43
+ messages: unknown[];
44
+ response: unknown;
45
+ inputTokens?: number;
46
+ outputTokens?: number;
47
+ elapsedSec?: number;
48
+ }): void;
49
+ /**
50
+ * Append a JSON record as a single line to the JSONL log file.
51
+ */
52
+ private _append;
53
+ }
54
+ //# sourceMappingURL=replay-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-log.d.ts","sourceRoot":"","sources":["../src/replay-log.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,qBAAa,YAAY;IACvB;;;;;;;;OAQG;IAEH,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,aAAa,CAAS;gBAElB,QAAQ,EAAE,MAAM,EAAE,cAAc,GAAE,MAAe;IAO7D;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY;IAKhD;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,GAAG,IAAI;IAmBR;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI;IAyBR;;OAEG;IACH,OAAO,CAAC,OAAO;CAWhB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Replay-capable LLM interaction logging with delta encoding.
3
+ *
4
+ * Migrated from agent/replay_log.py.
5
+ */
6
+ import * as fs from "node:fs";
7
+ import * as path from "node:path";
8
+ // ---------------------------------------------------------------------------
9
+ // ReplayLogger
10
+ // ---------------------------------------------------------------------------
11
+ export class ReplayLogger {
12
+ /**
13
+ * Logs every LLM API call so any individual call can be replayed exactly.
14
+ *
15
+ * Uses delta encoding: seq 0 stores a full messages snapshot, seq 1+
16
+ * store only messages appended since the previous call.
17
+ *
18
+ * Each conversation (root + subtasks) gets its own conversationId.
19
+ * All records append to the same JSONL file in chronological order.
20
+ */
21
+ path;
22
+ conversationId;
23
+ _seq;
24
+ _lastMsgCount;
25
+ constructor(filePath, conversationId = "root") {
26
+ this.path = filePath;
27
+ this.conversationId = conversationId;
28
+ this._seq = 0;
29
+ this._lastMsgCount = 0;
30
+ }
31
+ /**
32
+ * Create a child logger for a subtask conversation.
33
+ */
34
+ child(depth, step) {
35
+ const childId = `${this.conversationId}/d${depth}s${step}`;
36
+ return new ReplayLogger(this.path, childId);
37
+ }
38
+ /**
39
+ * Write the header record (provider, model, etc.) to the log.
40
+ */
41
+ writeHeader(opts) {
42
+ const record = {
43
+ type: "header",
44
+ conversation_id: this.conversationId,
45
+ provider: opts.provider,
46
+ model: opts.model,
47
+ base_url: opts.baseUrl,
48
+ system_prompt: opts.systemPrompt,
49
+ tool_defs: opts.toolDefs,
50
+ };
51
+ if (opts.reasoningEffort != null) {
52
+ record["reasoning_effort"] = opts.reasoningEffort;
53
+ }
54
+ if (opts.temperature != null) {
55
+ record["temperature"] = opts.temperature;
56
+ }
57
+ this._append(record);
58
+ }
59
+ /**
60
+ * Log a single LLM API call with delta encoding.
61
+ */
62
+ logCall(opts) {
63
+ const record = {
64
+ type: "call",
65
+ conversation_id: this.conversationId,
66
+ seq: this._seq,
67
+ depth: opts.depth,
68
+ step: opts.step,
69
+ ts: new Date().toISOString(),
70
+ };
71
+ if (this._seq === 0) {
72
+ record["messages_snapshot"] = opts.messages;
73
+ }
74
+ else {
75
+ record["messages_delta"] = opts.messages.slice(this._lastMsgCount);
76
+ }
77
+ record["response"] = opts.response;
78
+ record["input_tokens"] = opts.inputTokens ?? 0;
79
+ record["output_tokens"] = opts.outputTokens ?? 0;
80
+ record["elapsed_sec"] = Math.round((opts.elapsedSec ?? 0) * 1000) / 1000;
81
+ this._lastMsgCount = opts.messages.length;
82
+ this._seq += 1;
83
+ this._append(record);
84
+ }
85
+ /**
86
+ * Append a JSON record as a single line to the JSONL log file.
87
+ */
88
+ _append(record) {
89
+ const dir = path.dirname(this.path);
90
+ fs.mkdirSync(dir, { recursive: true });
91
+ fs.appendFileSync(this.path, JSON.stringify(record, (_key, value) => typeof value === "bigint" ? value.toString() : value) + "\n", "utf-8");
92
+ }
93
+ }
94
+ //# sourceMappingURL=replay-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-log.js","sourceRoot":"","sources":["../src/replay-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Session runtime – migrated from agent/runtime.py.
3
+ *
4
+ * Provides SessionError, SessionStore, and SessionRuntime for managing
5
+ * agent sessions with persistence.
6
+ */
7
+ import type { AgentConfig } from "./config.js";
8
+ import { ExternalContext, RLMEngine, type EventCallback, type StepCallback, type ContentDeltaCallback } from "./engine.js";
9
+ export declare class SessionError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ export declare class SessionStore {
13
+ workspace: string;
14
+ sessionRootDir: string;
15
+ root: string;
16
+ sessions: string;
17
+ constructor(workspace: string, sessionRootDir?: string);
18
+ private _sessionDir;
19
+ private _metadataPath;
20
+ listSessions(limit?: number): Array<Record<string, string>>;
21
+ openSession(sessionId?: string | null, resume?: boolean): [string, Record<string, unknown>, boolean];
22
+ appendEvent(sessionId: string, eventType: string, data: Record<string, unknown>): void;
23
+ saveState(sessionId: string, state: Record<string, unknown>): void;
24
+ getSessionDir(sessionId: string): string;
25
+ private _touchMetadata;
26
+ }
27
+ export declare class SessionRuntime {
28
+ engine: RLMEngine;
29
+ store: SessionStore;
30
+ sessionId: string;
31
+ context: ExternalContext;
32
+ maxPersistedObservations: number;
33
+ constructor(opts: {
34
+ engine: RLMEngine;
35
+ store: SessionStore;
36
+ sessionId: string;
37
+ context: ExternalContext;
38
+ maxPersistedObservations?: number;
39
+ });
40
+ static bootstrap(opts: {
41
+ engine: RLMEngine;
42
+ config: AgentConfig;
43
+ sessionId?: string | null;
44
+ resume?: boolean;
45
+ }): SessionRuntime;
46
+ solve(objective: string, opts?: {
47
+ onEvent?: EventCallback | null;
48
+ onStep?: StepCallback | null;
49
+ onContentDelta?: ContentDeltaCallback | null;
50
+ }): Promise<string>;
51
+ private _persistState;
52
+ }
53
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAC;AAOrB,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AA+BD,qBAAa,YAAY;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;gBAEL,SAAS,EAAE,MAAM,EAAE,cAAc,GAAE,MAAuB;IAYtE,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;IAIrB,YAAY,CAAC,KAAK,GAAE,MAAY,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA2BhE,WAAW,CACT,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,CAAC,EAAE,OAAO,GACf,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAmC7C,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI;IAYP,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI;IAOP,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAIxC,OAAO,CAAC,cAAc;CAgBvB;AAMD,qBAAa,cAAc;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;gBAErB,IAAI,EAAE;QAChB,MAAM,EAAE,SAAS,CAAC;QAClB,KAAK,EAAE,YAAY,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,eAAe,CAAC;QACzB,wBAAwB,CAAC,EAAE,MAAM,CAAC;KACnC;IAQD,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;QACrB,MAAM,EAAE,SAAS,CAAC;QAClB,MAAM,EAAE,WAAW,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,GAAG,cAAc;IAwCZ,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;QAC7B,cAAc,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;KAC9C,GACA,OAAO,CAAC,MAAM,CAAC;IAoClB,OAAO,CAAC,aAAa;CAQtB"}