@ara-commons/ara-skills 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/package.json +3 -2
- package/skills/compiler/SKILL.md +26 -0
- package/skills/compiler/references/ara-schema.md +28 -0
- package/skills/research-visualizer/SKILL.md +172 -0
- package/skills/research-visualizer/references/binding.md +245 -0
- package/skills/research-visualizer/references/parsing.md +211 -0
- package/skills/research-visualizer/references/trajectory-template.html +804 -0
- package/src/index.js +1 -1
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Parsing tolerance — normalize the exploration tree across ARA variants
|
|
2
|
+
|
|
3
|
+
The canonical `exploration-tree-spec.md` uses **generic** field names; many real artifacts instead
|
|
4
|
+
use **type-named** fields. Parse against the *model*, tolerate the *variants*. Never
|
|
5
|
+
hardcode to one example; never assume a fixed field set. The goal: **every node yields an `id`,
|
|
6
|
+
`type`, `title`, `body`, and a `parent`** (plus optional metadata), no matter which dialect.
|
|
7
|
+
|
|
8
|
+
## 1. Root form
|
|
9
|
+
|
|
10
|
+
Accept both:
|
|
11
|
+
- `tree:` → a **list** of root nodes (canonical).
|
|
12
|
+
- `root:` → a **single** root node. Treat it as a one-element root list.
|
|
13
|
+
|
|
14
|
+
Children nest under each node's `children:` list. A node's `parent` is the nearest enclosing node;
|
|
15
|
+
top-level nodes have `parent: null`.
|
|
16
|
+
|
|
17
|
+
## 2. Node identity & type
|
|
18
|
+
|
|
19
|
+
- `id` — required (any stable identifier the tree uses, e.g. `N01`, `E07`). Keep verbatim.
|
|
20
|
+
- `type` — one of `question | experiment | decision | dead_end | pivot | insight` (or anything else;
|
|
21
|
+
unknown types still render with a neutral glyph). Keep verbatim.
|
|
22
|
+
- `support_level` — `explicit | inferred` if present, else `null`.
|
|
23
|
+
- `source_refs` — list of strings if present, else `[]`. **External pointers; shown, never resolved.**
|
|
24
|
+
- `isolated: true` — carry through (renders in a separated box).
|
|
25
|
+
- `also_depends_on: [ids]` → emit as `depends_on` (DAG cross-edges).
|
|
26
|
+
- `thinking` — verbatim agent deliberation, **passed straight through** (the primary reasoning block).
|
|
27
|
+
Absent ⇒ omit. Never paraphrase or synthesize it.
|
|
28
|
+
- `code_change` — when the compiler wrote one onto the node (`base_artifact` / `variant_artifact` /
|
|
29
|
+
`lang` / `diff_file`), **pass it through**. The `diff_file`→`diff` inlining and the top-level
|
|
30
|
+
`artifacts[]` index are done in the binding/inline step (binding.md); the visualizer never computes a
|
|
31
|
+
diff itself. Absent ⇒ omit.
|
|
32
|
+
|
|
33
|
+
## 3. Title + body normalization (the dialect bridge)
|
|
34
|
+
|
|
35
|
+
For each node, derive a **display title** and a **body** by probing known fields **in order**, per type.
|
|
36
|
+
Use the first non-empty match; fall back gracefully so nothing is blank.
|
|
37
|
+
|
|
38
|
+
| type | title — try in order | body — try in order |
|
|
39
|
+
|-------------|-----------------------------------------------|-------------------------------------------------------|
|
|
40
|
+
| question | `title` → `question` | `description` → `question` (if used as title, leave body empty) |
|
|
41
|
+
| experiment | `title` → first sentence of `experiment` | `result` → `outcome` → `experiment` |
|
|
42
|
+
| decision | `title` → first sentence of `decision` | `choice` (+ `alternatives`) → `decision` |
|
|
43
|
+
| dead_end | `title` → first sentence of `dead_end` | `failure_mode`/`why_failed` (+ `hypothesis`,`lesson`) → `dead_end` |
|
|
44
|
+
| pivot | `title` → `trigger` | `from` → `to` → `trigger` |
|
|
45
|
+
| insight | `title` → first sentence of `insight` | `description` → `insight` |
|
|
46
|
+
| *(other)* | `title` → `<type>` field → `description` | the `<type>` field → `description` |
|
|
47
|
+
|
|
48
|
+
Rules:
|
|
49
|
+
- "first sentence of X" = X truncated at the first `. ` or ~80 chars — only when there is no separate
|
|
50
|
+
`title`. If a single field is both the only content and long, use a truncated form as title and the
|
|
51
|
+
full text as body.
|
|
52
|
+
- `decision`: append `alternatives` to the body as "alternatives: a; b" when present.
|
|
53
|
+
- `dead_end`: prefer to show *why it failed* in the body — it is the most valuable content.
|
|
54
|
+
- Never emit an empty title. If truly nothing usable, use the `id`.
|
|
55
|
+
|
|
56
|
+
## 4. `evidence:` routing
|
|
57
|
+
|
|
58
|
+
A node's `evidence:` (and a decision's `evidence:` string) may mix kinds. Split tokens and route:
|
|
59
|
+
- `C\d+` → claim IDs → drive the `why` / `result` binding (see `binding.md`).
|
|
60
|
+
- `Figure N` / `Table N` / a figure/table filename → evidence file refs → `result.figures`/`tables`.
|
|
61
|
+
- `§...` / prose → keep as a `source_refs`-style chip (context only).
|
|
62
|
+
|
|
63
|
+
## 5. Provenance
|
|
64
|
+
|
|
65
|
+
May appear as:
|
|
66
|
+
- a per-claim `provenance:` / `Provenance:` field, **or**
|
|
67
|
+
- prose in the `claims.md` header ("all claims are `ai-executed`; C06, C08 are `user-revised`").
|
|
68
|
+
|
|
69
|
+
Capture whichever exists and attach the right tag to each claim in `why[]`. If neither exists, omit
|
|
70
|
+
provenance — do not guess.
|
|
71
|
+
|
|
72
|
+
## 6. Claims, experiments, evidence index (the hub layers)
|
|
73
|
+
|
|
74
|
+
- `logic/claims.md` — split on `## C\d+` headings. Pull `Statement`, `Status`, `Conditions`,
|
|
75
|
+
`Falsification criteria`, `Proof` (→ `E##`), `Sources` (verbatim «quote» + `← file:line`),
|
|
76
|
+
`Dependencies`. Field labels are bold-prefixed (`**Statement.**` or `- **Statement**:`) — match both.
|
|
77
|
+
- `logic/experiments.md` — split on `## E\d+`. Pull `Verifies` (→ `C##`), `Run`, `Setup`, `Metrics`.
|
|
78
|
+
- `evidence/README.md` — parse the Tables/Figures index to build `claim_id → [evidence files]`.
|
|
79
|
+
|
|
80
|
+
## 7. Degrade, don't fail — the tree is the only hard requirement
|
|
81
|
+
|
|
82
|
+
Any missing/oddly-shaped field → fall back per the tables above and continue. A smaller honest view
|
|
83
|
+
is correct. **Hard-stop on exactly one condition: `trace/exploration_tree.yaml` is absent or parses to
|
|
84
|
+
zero nodes** (nothing to show). Minimal-validity guard = *the tree parses AND yields ≥1 node* — this
|
|
85
|
+
replaces the old "`PAPER.md` missing ⇒ not an ARA" guard, which no longer hard-stops (a missing
|
|
86
|
+
`PAPER.md` just means the visualizer synthesizes a minimal `meta` from a tree-level `title:` / the dir
|
|
87
|
+
name). Everything else — `logic/`, `evidence/`, `src/`, the four enrichment layers — is optional; absent
|
|
88
|
+
⇒ contributes nothing, never an error.
|
|
89
|
+
|
|
90
|
+
### 7a. Raw-trajectory input mode (first-class)
|
|
91
|
+
|
|
92
|
+
The minimum a node needs to render a useful step is `id` + (`title` **or** a type-named text field);
|
|
93
|
+
`body` / `thinking` are optional but make the step legible. So a **bare exploration tree with no
|
|
94
|
+
`logic/`, no `evidence/`, and no `PAPER.md`** — i.e. a raw agent run — is a fully supported input, not a
|
|
95
|
+
degraded one. Each node renders from its own normalized `title` / `body` (per §3) plus its `thinking`
|
|
96
|
+
(the agent's deliberation, when the source carries it — a verbatim pass-through field); the
|
|
97
|
+
`why` / `result` / `how-verified` blocks are simply empty and omitted.
|
|
98
|
+
|
|
99
|
+
**Adapter recipe (generic agent run → minimal tree).** A typical agent log is a sequence of steps, each
|
|
100
|
+
a `{thought, action, observation/result}`. Map it onto the tree:
|
|
101
|
+
- one tree node per step (or per meaningful decision/experiment); `id` = the step index/label.
|
|
102
|
+
- `type` from the step kind: a tried approach → `experiment`; a chosen direction → `decision`; an
|
|
103
|
+
abandoned/failed approach → `dead_end`; an opening/guiding question → `question`.
|
|
104
|
+
- `title` = a one-line summary of the step (first sentence of the action, ≤80 chars).
|
|
105
|
+
- `thinking` = the agent's thought/deliberation for the step (**verbatim** — why it did/branched).
|
|
106
|
+
- `body` = what it actually did + what came back (action + observation).
|
|
107
|
+
- `source_refs` = a pointer back to the log line(s) (shown, never resolved).
|
|
108
|
+
- nesting via `children`; convergence via `also_depends_on`; a discarded branch via `isolated`.
|
|
109
|
+
|
|
110
|
+
No `logic/` or `evidence/` is required; enrich the same tree later (via the compiler) to add claims,
|
|
111
|
+
evidence, and per-node `code_change` diffs.
|
|
112
|
+
|
|
113
|
+
# 8. The four `logic/` enrichment layers (all optional)
|
|
114
|
+
|
|
115
|
+
These produce the OPTIONAL `context` / `glossary` / `dependencies` / `recipes` keys (and the per-node
|
|
116
|
+
`built_on` / `rejected_here` / `recipe_refs` / `concepts` fields, derived in `binding.md`). **Each is
|
|
117
|
+
independent and absent ⇒ omit its key entirely** (no empty stubs). The renderer is inert for any key
|
|
118
|
+
it doesn't see, so an ARA with none of these renders exactly as before.
|
|
119
|
+
|
|
120
|
+
**Governing rule — classify by markdown SHAPE + generic cross-ref regexes; NEVER key on field
|
|
121
|
+
vocabulary.** Do not look for "optimizer", "Fig.", "loss", "shortcut", etc. — only headings, bold-lead
|
|
122
|
+
labels, id tokens, and the ref battery below. Verbatim everywhere: `text`/`definition`/`delta`/`value`,
|
|
123
|
+
all numbers, quotes, table cells, relation strings, and headings are reproduced exactly; a missing
|
|
124
|
+
field is `""`/`[]`; positive-absence signals (`present:false`, `unstructured`, `is_footprint`,
|
|
125
|
+
`inferred_id`) are *shown*, never invented.
|
|
126
|
+
|
|
127
|
+
## 8.0 Shared sub-routines (define once, reuse for every layer)
|
|
128
|
+
|
|
129
|
+
- **`splitEntries(sectionText)`** — try delimiters in order, take the first that yields ≥1 hit:
|
|
130
|
+
(a) `^### ` H3 headings; (b) `^## ` with a leading id token (`^##\s*([A-Za-z]{1,3}\d+|RW\d+|[OGA]\d+)`);
|
|
131
|
+
(c) top-level bold-lead bullets `^\s*-\s*\*\*(.+?)\.?\*\*`; (d) blank-line-separated paragraph blocks.
|
|
132
|
+
(d) always succeeds ⇒ prose-only dialects still yield entries.
|
|
133
|
+
- **`probeFields(entryText)`** — collect every `^\s*-?\s*\*\*([^*]+?)\*\*\s*[:—]` labeled leader into an
|
|
134
|
+
**open** `[{label,value}]` list. **Labels verbatim, no whitelist.** Empty ⇒ `unstructured:true`,
|
|
135
|
+
`fields:[]`.
|
|
136
|
+
- **`harvestRefs(text)` → `typed-ref[]`** — run the FULL union of patterns; never assume one scheme.
|
|
137
|
+
The shared **typed-ref** is `{ "raw":"<verbatim token>", "kind":"…", "target":null }`; `target` is set
|
|
138
|
+
later in the binding pass (it stays `null` for anything that doesn't resolve inside this ARA).
|
|
139
|
+
|
|
140
|
+
| pattern | kind |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `\[?\b(C\d{1,3})\b\]?` (optionally `(claims.md…)`) | `claim` |
|
|
143
|
+
| `\bRW\d{1,3}\b` | `related_work` |
|
|
144
|
+
| `\b([OGA])\d{1,3}\b` | `observation` / `gap` / `assumption` |
|
|
145
|
+
| `\bK\d{1,3}\b` or a minted term-id | `concept` |
|
|
146
|
+
| `PR\s*#?\d+` | `pr` |
|
|
147
|
+
| `arXiv[:\s]\S+` | `arxiv` |
|
|
148
|
+
| `10\.\d{4,}/\S+` | `doi` |
|
|
149
|
+
| `[\w./-]+\.\w+:\d+(?:-\d+)?` · `trace:N\d+` · `logic/\S+#\w+` | `source` / `node` |
|
|
150
|
+
| `§[\w".]+` · `Table\s*\S+` · `Fig\.?\s*\S+` · `Eqn\.?\s*\S+` | `figure` |
|
|
151
|
+
| `https?://\S+` | `url` |
|
|
152
|
+
|
|
153
|
+
## 8.1 `logic/problem.md` → `context`
|
|
154
|
+
Absent ⇒ omit (do NOT fabricate context from claims). Split on `^## `; classify each heading by a
|
|
155
|
+
**case-insensitive role-synonym map** (NOT exact names): `setting ⇐ {setting,task,constraints,
|
|
156
|
+
background,context,problem statement}`; `observations ⇐ {observation*,findings,evidence}`;
|
|
157
|
+
`gaps ⇐ {gap*,open question*,challenges,limitations of prior work}`; `insight ⇐ {key insight,insight,
|
|
158
|
+
core idea,approach,thesis}`; `assumptions ⇐ {assumption*,scope,caveats}`. Unmatched ⇒ `role:"other"`,
|
|
159
|
+
heading kept verbatim, **never dropped**. **Merge** same-role sections. Any canonical role that never
|
|
160
|
+
appeared ⇒ emit a `{present:false}` stub (signals the compile, greys the chip). Per section run
|
|
161
|
+
`splitEntries`; `ent_id = \b([OGA]\d+)\b` (width-agnostic) else positional + `inferred_id:true`;
|
|
162
|
+
`ent_title` = text to the first `:`/`—`/`.` else first sentence; `probeFields` (empty ⇒
|
|
163
|
+
`unstructured:true`); `text` = verbatim body (mandatory); `harvestRefs`. `summary` = the insight
|
|
164
|
+
entry's first sentence (else `""`).
|
|
165
|
+
|
|
166
|
+
## 8.2 `logic/concepts.md` → `glossary`
|
|
167
|
+
Absent ⇒ omit (⇒ popovers globally disabled). **Detect grouping:** a `##` is a *group* (not a term)
|
|
168
|
+
iff it has no `—`/`:` id-separator AND the next non-blank line is a `- ` bullet AND no following
|
|
169
|
+
`**Definition`. Split terms via `splitEntries` (`^##\s+(.+)$` → `^- \*\*(.+?)\.?\*\*` → paragraphs).
|
|
170
|
+
Per term: `term_id` = leading `^(K|C|RW|[A-Z]{1,3})\d{2,}` before the separator, else **mint**
|
|
171
|
+
`G01,G02,…` positionally (a stable popover anchor); `name` = heading minus id/separator (mandatory);
|
|
172
|
+
`aliases` = split a trailing `(…)` and `/`; `definition` = `**Definition**:` value else whole body
|
|
173
|
+
(mandatory); `probeFields` (captures resnet-style `Notation`/`Boundary conditions`; nothing for
|
|
174
|
+
codex/ptb — correct); `related` = any `/relat/i`-labeled field split on commas (resolved to `term_id`s
|
|
175
|
+
in binding); `harvestRefs`. **Build `lexicon`** = lowercased `name` + each alias → `term_id`, skipping
|
|
176
|
+
tokens <3 chars and pure-numeric aliases, first-wins on collision (the renderer uses it for popovers).
|
|
177
|
+
|
|
178
|
+
## 8.3 `logic/related_work.md` → `dependencies`
|
|
179
|
+
Absent ⇒ omit. Strip the preamble before the first `## ` → `preamble`; parse `**word** (gloss)` pairs →
|
|
180
|
+
`legend[]`; capture a `> **Cross-agent attribution.**` blockquote → `attribution`. Split on `^## `,
|
|
181
|
+
match `^##\s*(RW\d+)?\s*[—:-]?\s*(.*)$`. If a heading has no `RW\d+` and matches `/brief|additional
|
|
182
|
+
referenced|citations/i`, parse its bullets into `footprint[]` (`{ref_id,citation}`) and skip structured
|
|
183
|
+
probing (`is_footprint` entries, or just the `footprint` tail). Per entry: `relation_raw` from a
|
|
184
|
+
` — **type** ` in the heading ELSE a `**Type:**` line — **kept verbatim**, incl. compound
|
|
185
|
+
(`bounds / refutes`) and transition (`extends → quarantined`); `relation_norm` = the first of
|
|
186
|
+
`{baseline,imports,extends,bounds,refutes}` found, else `""` (color only); `name` = heading after the
|
|
187
|
+
separator; `delta` = `**Delta**`/`What changed:`+`Why:` (concatenate) else body; `adopted` =
|
|
188
|
+
`**Adopted elements**`; `grounding`/`claims` = `harvestRefs` partitioned by kind; `cross_agent:true` if
|
|
189
|
+
the entry is named in `attribution` or its relation mentions another agent. Unnumbered ⇒ positional +
|
|
190
|
+
`inferred_id`. **Degrade:** an entry with no source and no claim keeps `grounding:[]`+`claims:[]` (the
|
|
191
|
+
renderer shows a muted "ungrounded").
|
|
192
|
+
|
|
193
|
+
## 8.4 `logic/solution/*` → `recipes`
|
|
194
|
+
Glob `logic/solution/*.md`; dir absent ⇒ omit. **Role-classify each file by content signal (priority):**
|
|
195
|
+
filename `constraints.md` → `constraints`; filename `method.md` OR title `/method|recipe|procedure|
|
|
196
|
+
process|pipeline/i` → `method`; uniform `^##\s*[A-Z]\d+:` entries → `heuristics`;
|
|
197
|
+
`## Mathematical formulation`/pseudocode fence/`$…$` → `algorithm`; repeated component `###` micro-schema
|
|
198
|
+
→ `architecture`; else → `recipe`. (Only the `constraints.md` filename is special — a universal ARA
|
|
199
|
+
convention, not a field term.) Split each file on `^## ` (recurse `###`). **`heading` kept verbatim —
|
|
200
|
+
never normalized.** Per section pick the **dominant `kind`** in order: table `| … |` → `table`
|
|
201
|
+
(`markdown`); typed bullets `- **K**: v` → `kv` (`fields`); numbered `^\d+\.` → `steps`;
|
|
202
|
+
fenced/ASCII-DAG → `code`; `$$…$$`/`$…$` → `math` (put TeX in `code`); else → `prose`. `text` = verbatim
|
|
203
|
+
body (mandatory fallback); `sec_id` = leading id; `warn` = body under a `/confound|cut-off|incomplete|
|
|
204
|
+
not specified|unverified/i` heading; `refs` = `harvestRefs` (harvest **bare** `C05` too, not only
|
|
205
|
+
`[C05]`). **Degrade:** only `constraints.md` present ⇒ render just it (no "method missing" stub);
|
|
206
|
+
`method.md` absent but `algorithm.md`/`architecture.md` present ⇒ those carry the method role.
|
|
207
|
+
|
|
208
|
+
## 8.5 Universal absence rule
|
|
209
|
+
Each key is independent; any combination is valid. A `minimal-artifact` (only `problem.md`+`claims.md`)
|
|
210
|
+
yields `context` only — `glossary`/`dependencies`/`recipes` omitted, all per-node enrichment fields
|
|
211
|
+
`[]`, nothing errors.
|