docs: split schema.md into focused references (api-reference.md + compact SQL map)

Extract helper API documentation into a standalone api-reference.md and
  reduce schema.md to a compact field/join/table map for raw SQL work.
  Add a Reference Map table to SKILL.md for quick routing by task type.
This commit is contained in:
tommy0103
2026-06-18 01:52:44 +08:00
parent 12407227cc
commit d5d5df46fa
3 changed files with 735 additions and 918 deletions
+27 -7
View File
@@ -108,6 +108,19 @@ Routing rules:
infer recap from broad requests for weekly/monthly summaries, charts, infer recap from broad requests for weekly/monthly summaries, charts,
rankings, shareable cards, or playlist-style metaphors. rankings, shareable cards, or playlist-style metaphors.
## Reference Map
Use references by job, not by habit:
| Reference | Use when |
|---|---|
| `references/query-patterns.md` | Broad synthesis, progress summaries, design history, weekly/monthly reviews, approved memory write/archive/update scripts, or questions about what the user did/learned/decided/tried/abandoned. |
| `references/retrieval-semantics.md` | Multi-step retrieval, scoped project/file/session searches, or when scope/artifact/semantic boundaries affect query design. |
| `references/schema.md` | Raw SQL field and join quick reference before writing non-trivial `sql()`. |
| `references/api-reference.md` | Helper signatures, option names, return fields, or exact `remember()` / `forget()` parameter details are unclear. |
| `references/pitfalls.md` | Error recovery, FTS syntax, aliases, ordering, row-shape surprises, or compact/raw tradeoffs. |
| `references/recap/overview.md` | Explicit `/obelisk recap ...` requests only. |
## Query Routing ## Query Routing
Before writing a query, classify the task. Progressive disclosure is useful, but Before writing a query, classify the task. Progressive disclosure is useful, but
@@ -115,12 +128,18 @@ skipping the relevant reference usually costs extra query rounds.
- Read `references/query-patterns.md` before the first query for broad synthesis, progress summaries, design history, ordinary weekly/monthly reviews, or questions that ask what the user did, learned, decided, tried, or abandoned. Start from the first-pass or one-shot synthesis pattern, then run a faceted detail pass if needed. - Read `references/query-patterns.md` before the first query for broad synthesis, progress summaries, design history, ordinary weekly/monthly reviews, or questions that ask what the user did, learned, decided, tried, or abandoned. Start from the first-pass or one-shot synthesis pattern, then run a faceted detail pass if needed.
- Read `references/retrieval-semantics.md` before multi-step retrieval, scoped project/file/session searches, or synthesis/conclusion/history questions. It defines the query design frame. - Read `references/retrieval-semantics.md` before multi-step retrieval, scoped project/file/session searches, or synthesis/conclusion/history questions. It defines the query design frame.
- Read `references/schema.md` before raw `sql()` unless the needed table/column relationship is already explicit here. Do this before running the SQL, not after a missing-column error. Do not start with raw SQL for broad synthesis unless helpers cannot express the needed aggregation or join. - Read `references/schema.md` before raw `sql()` unless the needed table/column relationship is already explicit here. It is intentionally short and SQL-focused. Do this before running the SQL, not after a missing-column error. Do not start with raw SQL for broad synthesis unless helpers cannot express the needed aggregation or join.
- Read `references/pitfalls.md` after an error or when helper fields, FTS syntax, aliases, or row shapes are unclear. - Read `references/api-reference.md` when helper option names, return fields, scalar shorthand behavior, or `remember()`/`forget()` details are unclear.
- Read `references/pitfalls.md` after an error or when FTS syntax, aliases, ordering, row shapes, or compact/raw tradeoffs are unclear.
If a helper row shape is unclear, first run a tiny scoped query and return If a helper row shape is unclear, first run a tiny scoped query and return
`Object.keys(row)` or a compact sample. Do not invent field names. `Object.keys(row)` or a compact sample. Do not invent field names.
For approved memory mutations, follow the Memory Layer section below first.
Use `references/query-patterns.md` for copyable `--attune` scripts
(`Attune Approved Memory`, `Forget Approved Memory`, `Update Approved Memory`),
and `references/api-reference.md` only for exact parameter semantics.
## Core API ## Core API
### `search(text, opts?)` ### `search(text, opts?)`
@@ -183,9 +202,9 @@ Read-only SQL SELECT/WITH with `?` placeholders. Returns array rows. SQL is an
escape hatch for exact structured joins and aggregations after the helper-first escape hatch for exact structured joins and aggregations after the helper-first
surface is insufficient; it is not the default retrieval entry point. surface is insufficient; it is not the default retrieval entry point.
Before writing non-trivial SQL, read `references/schema.md`. The executable DDL Before writing non-trivial SQL, read `references/schema.md`. It is the raw SQL
lives in `scripts/schema.sql`; use the reference for query semantics and the SQL field/join quick reference. The executable DDL lives in `scripts/schema.sql`;
file for schema-source alignment. Common safe joins: use the SQL file only when checking source alignment. Common safe joins:
- `tool_calls` does not have timestamps. Join `messages m ON m.uuid = tc.message_uuid`. - `tool_calls` does not have timestamps. Join `messages m ON m.uuid = tc.message_uuid`.
- `tool_results` does not have timestamps. Join `messages m ON m.uuid = tr.message_uuid`. - `tool_results` does not have timestamps. Join `messages m ON m.uuid = tr.message_uuid`.
@@ -202,8 +221,9 @@ not replace `sql()`, but they are the default first-pass surface. Use `sql()`
when you need an exact aggregation or a join the helper does not expose. when you need an exact aggregation or a join the helper does not expose.
All list helpers accept a bounded `limit`. Many also accept: All list helpers accept a bounded `limit`. Many also accept:
`{ project, after, before, sessionId, sessions, branch, source }`. Check the `{ project, after, before, sessionId, sessions, branch, source }`. Check
schema or a tiny sample before relying on less common filters. `references/api-reference.md` or a tiny sample before relying on less common
filters or return fields.
- `overview(opts?)` -- compact orientation map. Returns current cwd/project if knowable, global project/source counts, and current-project recent sessions plus memory records. It is a map, not evidence. - `overview(opts?)` -- compact orientation map. Returns current cwd/project if knowable, global project/source counts, and current-project recent sessions plus memory records. It is a map, not evidence.
- `sessions(opts?)` -- session rows, newest first. `project` is a SQL `LIKE` pattern. - `sessions(opts?)` -- session rows, newest first. `project` is a SQL `LIKE` pattern.
+460
View File
@@ -0,0 +1,460 @@
# Obelisk -- Helper API Reference
Detailed reference for globals available inside `runtime.mjs --query` and
`runtime.mjs --attune` scripts.
- Use `references/schema.md` for raw SQL table/field/join checks.
- Use `references/query-patterns.md` for copyable retrieval plans.
- Use `references/retrieval-semantics.md` for query design and scope choices.
- Use `references/pitfalls.md` after runtime errors or confusing row shapes.
Query scripts run inside an async IIFE with a 30-second timeout. Use `return` to
emit JSON. `--query` scripts are read-only. `--attune` scripts expose only
memory mutation helpers.
## Query API Reference
### Read Helpers
These globals are available only in `runtime.mjs --query` scripts:
```js
sql, search, context, trace, thread, raw,
overview, sessions, recent, summaries, memories,
subagents, workflows, workflowTree, fileHistory, failures
```
All list helpers accept bounded `limit` options. Many helpers also accept
`project`, `sessionId`, `sessions`, `after`, `before`, `branch`, and `source`
when the underlying table can express that scope. Passing a string to many list
helpers is treated as `sessionId`; passing a number is treated as `limit`.
### Mutation Helpers
These globals are available only in `runtime.mjs --attune` scripts:
```js
remember, forget
```
`--attune` does not expose `search()`, `sql()`, `memories()`, or other read
helpers. If you need IDs, discover them first with a normal `--query` script.
---
## Core Helpers
#### `search(text, opts?)`
Full-text search across all indexed message text using FTS5.
| Param | Type | Description |
| --- | --- | --- |
| `text` | `string` | FTS5 query string |
| `opts.limit` | `number` | Max results, default 20 |
| `opts.sessionId` | `string` | Restrict to one session |
| `opts.project` | `string` | SQL `LIKE` pattern over `sessions.project` |
| `opts.after` | `string` | ISO lower bound on message timestamp |
| `opts.before` | `string` | ISO upper bound on message timestamp |
| `opts.cwd` | `string` | SQL `LIKE` filter over `messages.cwd` |
| `opts.source` | `string` | `"claude"`, `"codex"`, or omitted/all |
| `opts.includeMeta` | `boolean` | Include `is_meta=1` rows, default false |
Returns:
```js
Array<{
message: { uuid, text, content_type, is_meta, role, timestamp, model, cwd, source },
session: { id, title, project, started_at, source },
rank,
context
}>
```
`context` is temporal neighbor context in the same session, not a parent chain.
Use `context(uuid)` or `trace(uuid)` for causal/parent-chain expansion. Lower
FTS rank sorts earlier; prefer returned order unless deliberately inspecting
FTS ranking.
#### `context(uuid)`
Full indexed context around one message.
| Param | Type | Description |
| --- | --- | --- |
| `uuid` | `string` | Message UUID |
Returns:
```js
{ message, parentChain, session, subagent, workflow } | null
```
`parentChain` contains ancestors, not temporal neighbors. If the message belongs
to a subagent or workflow agent, `subagent` or `workflow` is populated when the
metadata exists.
#### `sql(query, ...params)`
Read-only SQL helper with positional `?` bindings.
| Param | Type | Description |
| --- | --- | --- |
| `query` | `string` | `SELECT` or `WITH` statement |
| `...params` | `any` | Bind values |
Returns `Array<object>`.
Write statements are rejected. Use `references/schema.md` before non-trivial SQL
joins, and use `--attune` with `remember()` / `forget()` for memory mutation.
---
## Orientation And Lists
#### `overview(opts?)`
Compact orientation map for choosing retrieval scope. It is not evidence: it
does not return snippets, full messages, or markdown memory contents.
Passing a string is treated as `project`. Passing a number is treated as
`limit`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.project` | `string` | Project slug or SQL `LIKE` pattern to use as current scope |
| `opts.limit` | `number` | Max recent sessions in `current_project.sessions`, default 8 |
| `opts.projectLimit` | `number` | Max global project rows, default 20 |
| `opts.memoryLimit` | `number` | Max memories in `current_project.memories`, default 100 |
If `opts.project` is absent, `overview()` tries to identify the current project
from `process.cwd()` against `sessions.project_path`, then from exact
`messages.cwd` matches. It does not guess the current session.
Returns:
```js
{
current: {
cwd,
project: {
project,
project_path,
source: 'opts' | 'cwd_project_path' | 'cwd_messages',
confidence: 'exact' | 'inferred' | 'unknown'
} | null
},
current_project: {
project,
project_path,
session_total,
sessions: [
{ id, title, project, project_path, started_at, ended_at, git_branch, message_count, source }
],
memory_total,
memories: [
{ id, path, anchors, summary, session_id, project, created_at }
]
} | null,
projects: [
{
project,
project_path,
session_count,
memory_count,
last_session_at,
last_memory_at,
recent_branches
}
],
totals: {
projects,
sessions,
memories,
sources: [{ source: 'claude' | 'codex', session_count, last_session_at }]
}
}
```
Confirm facts with `memories()`, `search()`, other helpers, or `sql()`.
#### `sessions(opts?)`
Session rows ordered by `ended_at` descending. Passing a number is treated as
`limit`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.project` | `string` | SQL `LIKE` pattern over `sessions.project` |
| `opts.after` | `string` | ISO lower bound on `started_at` |
| `opts.before` | `string` | ISO upper bound on `started_at` |
| `opts.limit` | `number` | Max rows, default 50 |
| `opts.branch` | `string` | Exact git branch |
| `opts.source` | `string` | `"claude"`, `"codex"`, or omitted/all |
| `opts.sessionId` | `string` | Exact session ID |
| `opts.sessions` | `string[]` | Restrict to session IDs |
Returns `Array<session_row>`.
#### `recent(n?)`
Shorthand for `sessions({ limit: n })`. Default `n` is 10.
Returns `Array<session_row>`.
#### `summaries(opts?)`
Session summary rows ordered by summary `timestamp` descending. Passing a string
is treated as `sessionId`; passing a number is treated as `limit`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.sessionId` | `string` | Restrict to one session |
| `opts.sessions` | `string[]` | Restrict to session IDs |
| `opts.project` | `string` | SQL `LIKE` pattern over source session project |
| `opts.after` | `string` | ISO lower bound on summary timestamp |
| `opts.before` | `string` | ISO upper bound on summary timestamp |
| `opts.branch` | `string` | Exact source session branch |
| `opts.source` | `string` | Provider filter through joined session |
| `opts.limit` | `number` | Max rows, default 100 |
Returns:
```js
Array<summary_row & { session_title, project }>
```
`summaries.source` is the summary kind, such as `away_summary`; it is not the
provider source.
#### `memories(opts?)`
Active registered markdown memory records. Passing a string is treated as
`sessionId`; passing a number is treated as `limit`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.query` | `string` | English recall query over `summary` and `path` |
| `opts.project` | `string` | SQL `LIKE` pattern over `memories.project` |
| `opts.sessionId` | `string` | Restrict to one source session |
| `opts.sessions` | `string[]` | Restrict to source session IDs |
| `opts.after` | `string` | ISO lower bound on `created_at` |
| `opts.before` | `string` | ISO upper bound on `created_at` |
| `opts.branch` | `string` | Exact source session branch |
| `opts.source` | `string` | Provider filter through the source session |
| `opts.limit` | `number` | Max rows, default 50 |
Returns:
```js
Array<memory_row & { rank?: number }>
```
Archived memories are omitted. Without `query`, rows are newest first. With
`query`, rows are ordered by safe FTS rank first, then `created_at` descending.
Lower rank sorts earlier. Translate non-English requests into concise English
query terms before calling `memories()`. Read the markdown file at `path` for
full content.
---
## Structural Expansion Helpers
#### `trace(uuid)`
Walk the `parent_uuid` chain from a message to the conversation root.
Returns `Array<message>` ordered root-first.
#### `thread(sessionId, opts?)`
Messages in a session ordered by timestamp.
| Param | Type | Description |
| --- | --- | --- |
| `sessionId` | `string` | Session ID |
| `opts.includeMeta` | `boolean` | Include injected/control-plane rows, default false |
Returns `Array<message>`. Use `thread()` as a last resort; prefer targeted
search/context or compact SQL projections.
#### `raw(uuid, opts?)`
Windowed access to the original JSONL line for one indexed message. Use this
when indexed text, tool inputs, or tool results were truncated and you need the
raw source.
| Param | Type | Description |
| --- | --- | --- |
| `uuid` | `string` | Message UUID |
| `opts.offset` | `number` | Character offset into the JSONL line, default 0 |
| `opts.limit` | `number` | Max characters, default 10000 |
Returns:
```js
{ text, totalLength, offset, limit, hasMore } | null
```
`raw()` resolves main-session, subagent, workflow-agent, and Codex JSONL paths
from indexed metadata.
---
## Agent And Workflow Helpers
#### `subagents(opts?)`
Subagent metadata plus message counts. Passing a string is treated as
`sessionId`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.sessionId` | `string` | Restrict to one session |
| `opts.project` | `string` | SQL `LIKE` pattern over source session project |
| `opts.source` | `string` | Provider filter |
| `opts.limit` | `number` | Max rows, default 100 |
Returns:
```js
Array<{ ...subagent_row, messageCount }>
```
#### `workflows(opts?)`
Workflow run rows ordered newest first. Passing a string is treated as
`sessionId`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.sessionId` | `string` | Restrict to one session |
| `opts.project` | `string` | SQL `LIKE` pattern over source session project |
| `opts.after` | `string` | ISO lower bound on workflow timestamp |
| `opts.before` | `string` | ISO upper bound on workflow timestamp |
| `opts.source` | `string` | Provider filter |
| `opts.limit` | `number` | Max rows, default 100 |
Returns `Array<workflow_row>`.
#### `workflowTree(runId)`
Lightweight execution tree for one workflow run. It parses `result_json` and
adds per-agent message counts. It does not load agent messages.
Returns:
```js
{ ...workflow_row, result: object | null, agents: Array<{ ...workflow_agent_row, messageCount }> } | null
```
---
## Evidence Helpers
#### `fileHistory(filePath, opts?)`
Tool calls that touched one file, ordered oldest first. Includes `Read` rows as
well as `Edit`/`Write`.
| Param | Type | Description |
| --- | --- | --- |
| `filePath` | `string` | Absolute file path |
| `opts.after` | `string` | ISO lower bound |
| `opts.before` | `string` | ISO upper bound |
| `opts.source` | `string` | Provider filter |
| `opts.limit` | `number` | Max rows, default 200 |
Returns:
```js
Array<{ toolCall, session, timestamp }>
```
Use raw SQL with `ORDER BY m.timestamp DESC` when you need newest-first file
history.
#### `failures(opts?)`
Failed tool results with tool/session context and the next three messages after
the failure. Passing a string is treated as `sessionId`.
| Param | Type | Description |
| --- | --- | --- |
| `opts.sessionId` | `string` | Restrict to one session |
| `opts.project` | `string` | SQL `LIKE` pattern over source session project |
| `opts.after` | `string` | ISO lower bound on result message timestamp |
| `opts.before` | `string` | ISO upper bound on result message timestamp |
| `opts.source` | `string` | Provider filter |
| `opts.limit` | `number` | Max rows, default 50 |
Returns:
```js
Array<{ toolCall, result, session, nextMessages }>
```
Use SQL for precise counts and grouping; treat `failures()` as compact evidence,
not a counting primitive.
---
## Memory Mutation Helpers
#### `remember(record)`
Register a human-approved markdown memory file. Available only in
`runtime.mjs --attune` scripts.
| Param | Type | Description |
| --- | --- | --- |
| `record.path` | `string` | Existing markdown file path |
| `record.summary` | `string` | Required English retrieval summary |
| `record.session_id` | `string` | Source session ID, if known |
| `record.message_start` | `string` | First relevant source message UUID |
| `record.message_end` | `string` | Last relevant source message UUID |
| `record.project` | `string` | Project slug override |
| `record.anchors` | `array` or JSON `string` | Optional recall anchors |
Relative paths resolve against the source session `project_path` when
`session_id` is provided, otherwise against the runtime cwd. `remember()`
validates that `path` exists and is a regular file, rejects obvious CJK text in
`summary`, stores the normalized absolute path, and accepts nullable `anchors`.
Returns:
```js
{ id, path, project, anchors, created_at }
```
#### `forget(record)`
Archive a human-approved memory record. Available only in
`runtime.mjs --attune` scripts.
| Param | Type | Description |
| --- | --- | --- |
| `record.id` | `string` | Exact memory ID |
| `record.reason` | `string` | Required archive reason |
`forget()` sets `deleted_at` and `deleted_reason`. It does not delete the
markdown file at `path`. Active recall helpers omit archived rows.
Returns:
```js
{ id, deleted_at, deleted_reason } |
{ id, deleted_at, deleted_reason, already_deleted: true }
```
### Memory Mutation Approval
Agents may decide whether to use, ignore, or verify memory in a single answer
without approval. Approval is required only for persistent memory mutations.
When the user explicitly says a memory is wrong, outdated, should be forgotten,
or should say something else, that utterance is approval to mutate the exact
matching memory. If multiple memories could match, ask the user to choose.
Updating is not in-place: archive the old record with `forget()`, then write and
register a replacement markdown file with `remember()` under the same approval.
+248 -911
View File
File diff suppressed because it is too large Load Diff