sensemaking 0.3.2 → 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/dist/cjs/cli.js +1 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands/find.js +2 -2
- package/dist/cjs/commands/find.js.map +1 -1
- package/dist/cjs/commands/map.js +3 -3
- package/dist/cjs/commands/map.js.map +1 -1
- package/dist/cjs/commands/named.js +2 -2
- package/dist/cjs/commands/named.js.map +1 -1
- package/dist/cjs/commands/peek.js +2 -2
- package/dist/cjs/commands/peek.js.map +1 -1
- package/dist/cjs/commands/query.js +2 -2
- package/dist/cjs/commands/query.js.map +1 -1
- package/dist/cjs/commands/rebuild.js +2 -2
- package/dist/cjs/commands/rebuild.js.map +1 -1
- package/dist/cjs/commands/{vault.d.cts → shared.d.cts} +1 -1
- package/dist/cjs/commands/{vault.d.ts → shared.d.ts} +1 -1
- package/dist/cjs/commands/{vault.js → shared.js} +3 -3
- package/dist/cjs/commands/shared.js.map +1 -0
- package/dist/cjs/commands/status.js +2 -2
- package/dist/cjs/commands/status.js.map +1 -1
- package/dist/cjs/commands/watch.js +2 -2
- package/dist/cjs/commands/watch.js.map +1 -1
- package/dist/cjs/features/links.js +1 -1
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/index.d.cts +2 -2
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/verbs.d.cts +2 -2
- package/dist/cjs/verbs.d.ts +2 -2
- package/dist/cjs/verbs.js +5 -5
- package/dist/cjs/verbs.js.map +1 -1
- package/dist/esm/cli.js +1 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands/find.js +2 -2
- package/dist/esm/commands/find.js.map +1 -1
- package/dist/esm/commands/map.js +4 -4
- package/dist/esm/commands/map.js.map +1 -1
- package/dist/esm/commands/named.js +1 -1
- package/dist/esm/commands/named.js.map +1 -1
- package/dist/esm/commands/peek.js +2 -2
- package/dist/esm/commands/peek.js.map +1 -1
- package/dist/esm/commands/query.js +1 -1
- package/dist/esm/commands/query.js.map +1 -1
- package/dist/esm/commands/rebuild.js +1 -1
- package/dist/esm/commands/rebuild.js.map +1 -1
- package/dist/esm/commands/{vault.d.ts → shared.d.ts} +1 -1
- package/dist/esm/commands/{vault.js → shared.js} +2 -2
- package/dist/esm/commands/shared.js.map +1 -0
- package/dist/esm/commands/status.js +1 -1
- package/dist/esm/commands/status.js.map +1 -1
- package/dist/esm/commands/watch.js +1 -1
- package/dist/esm/commands/watch.js.map +1 -1
- package/dist/esm/features/links.js +1 -1
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/types.js +1 -1
- package/dist/esm/features/types.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/verbs.d.ts +2 -2
- package/dist/esm/verbs.js +3 -3
- package/dist/esm/verbs.js.map +1 -1
- package/package.json +1 -1
- package/skills/sense/EXAMPLES.md +12 -13
- package/skills/sense/SKILL.md +24 -15
- package/dist/cjs/commands/vault.js.map +0 -1
- package/dist/esm/commands/vault.js.map +0 -1
package/dist/esm/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS } from './commands/index.ts';\nimport type { Ctx } from './commands/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\n// Parsing and dispatch only. Commands live in src/commands/, one file each, lazy-loaded --\n// nothing
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS } from './commands/index.ts';\nimport type { Ctx } from './commands/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\n// Parsing and dispatch only. Commands live in src/commands/, one file each, lazy-loaded --\n// nothing tree- or dependency-heavy may be imported at the top of this file.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n return (\n `usage: ${name} <name> [params...] [--format table|json] [--config path]\\n` +\n ` ${name} query \"<sql>\" [params...]\\n` +\n ` ${name} find \"<terms>\" [--where \"<sql>\"] [--k n]\\n` +\n ` ${name} map\\n` +\n ` ${name} peek <path>\\n` +\n ` ${name} --list\\n` +\n ` ${name} init\\n` +\n ` ${name} watch [--force]\\n` +\n ` ${name} status\\n` +\n ` ${name} rebuild\\n` +\n ` ${name} --version`\n );\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n let values: Record<string, string | boolean | undefined>;\n let positionals: string[];\n try {\n ({ values, positionals } = parseArgs({\n args: argv,\n options: {\n format: { type: 'string', default: 'table' },\n config: { type: 'string' },\n where: { type: 'string' },\n k: { type: 'string' },\n list: { type: 'boolean', default: false },\n force: { type: 'boolean', default: false },\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n if (values.version) {\n console.log(`v${packageVersion()}`);\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n\n const ctx: Ctx = {\n name,\n rest: positionals.slice(1),\n format: values.format === 'json' ? 'json' : 'table',\n values: values as Ctx['values'],\n resolveConfig() {\n const cfg = loadConfig(values.config as string | undefined);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n return cfg;\n },\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n if (values.list) {\n for (const queryName of Object.keys(ctx.resolveConfig().queries).sort()) console.log(queryName);\n return;\n }\n\n const [first, ...params] = positionals;\n if (!first) {\n console.error(usage(name));\n process.exit(2);\n }\n\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else (await import('./commands/named.ts')).default(ctx, first, params);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["createRequire","parseArgs","COMMANDS","loadConfig","SUPPORTED_CONFIG_VERSION","packageVersion","load","url","rel","pkg","name","version","usage","cli","argv","values","positionals","args","options","format","type","default","config","where","k","list","force","short","help","allowPositionals","err","console","error","message","process","exit","log","ctx","rest","slice","resolveConfig","cfg","migratedFrom","undefined","warn","configPath","usageError","queryName","Object","keys","queries","sort","first","params"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { printRows } from '../output.js';
|
|
2
2
|
import { find } from '../verbs.js';
|
|
3
|
-
import {
|
|
3
|
+
import { withDb } from './shared.js';
|
|
4
4
|
const findCmd = (ctx)=>{
|
|
5
5
|
const [terms] = ctx.rest;
|
|
6
6
|
if (!terms) ctx.usageError(`usage: ${ctx.name} find "<terms>" [--where "<sql>"] [--k n]`);
|
|
7
7
|
const k = ctx.values.k === undefined ? undefined : Number.parseInt(ctx.values.k, 10);
|
|
8
8
|
if (ctx.values.k !== undefined && !Number.isInteger(k)) ctx.usageError(`--k expects an integer, got "${ctx.values.k}"`);
|
|
9
|
-
|
|
9
|
+
withDb(ctx, (db, cfg)=>printRows(find(db, cfg, terms, {
|
|
10
10
|
k,
|
|
11
11
|
where: ctx.values.where
|
|
12
12
|
}), ctx.format));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/find.ts"],"sourcesContent":["import { printRows } from '../output.ts';\nimport { find } from '../verbs.ts';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/find.ts"],"sourcesContent":["import { printRows } from '../output.ts';\nimport { find } from '../verbs.ts';\nimport { withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst findCmd: Command = (ctx) => {\n const [terms] = ctx.rest;\n if (!terms) ctx.usageError(`usage: ${ctx.name} find \"<terms>\" [--where \"<sql>\"] [--k n]`);\n const k = ctx.values.k === undefined ? undefined : Number.parseInt(ctx.values.k, 10);\n if (ctx.values.k !== undefined && !Number.isInteger(k)) ctx.usageError(`--k expects an integer, got \"${ctx.values.k}\"`);\n withDb(ctx, (db, cfg) => printRows(find(db, cfg, terms, { k, where: ctx.values.where }), ctx.format));\n};\nexport default findCmd;\n"],"names":["printRows","find","withDb","findCmd","ctx","terms","rest","usageError","name","k","values","undefined","Number","parseInt","isInteger","db","cfg","where","format"],"mappings":"AAAA,SAASA,SAAS,QAAQ,eAAe;AACzC,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,MAAM,QAAQ,cAAc;AAGrC,MAAMC,UAAmB,CAACC;IACxB,MAAM,CAACC,MAAM,GAAGD,IAAIE,IAAI;IACxB,IAAI,CAACD,OAAOD,IAAIG,UAAU,CAAC,CAAC,OAAO,EAAEH,IAAII,IAAI,CAAC,yCAAyC,CAAC;IACxF,MAAMC,IAAIL,IAAIM,MAAM,CAACD,CAAC,KAAKE,YAAYA,YAAYC,OAAOC,QAAQ,CAACT,IAAIM,MAAM,CAACD,CAAC,EAAE;IACjF,IAAIL,IAAIM,MAAM,CAACD,CAAC,KAAKE,aAAa,CAACC,OAAOE,SAAS,CAACL,IAAIL,IAAIG,UAAU,CAAC,CAAC,6BAA6B,EAAEH,IAAIM,MAAM,CAACD,CAAC,CAAC,CAAC,CAAC;IACtHP,OAAOE,KAAK,CAACW,IAAIC,MAAQhB,UAAUC,KAAKc,IAAIC,KAAKX,OAAO;YAAEI;YAAGQ,OAAOb,IAAIM,MAAM,CAACO,KAAK;QAAC,IAAIb,IAAIc,MAAM;AACrG;AACA,eAAef,QAAQ"}
|
package/dist/esm/commands/map.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { renderMap } from '../output.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { mapTree } from '../verbs.js';
|
|
3
|
+
import { withDb } from './shared.js';
|
|
4
4
|
const map = (ctx)=>{
|
|
5
|
-
|
|
6
|
-
const result =
|
|
5
|
+
withDb(ctx, (db, cfg)=>{
|
|
6
|
+
const result = mapTree(db, cfg);
|
|
7
7
|
console.log(ctx.format === 'json' ? JSON.stringify(result, null, 2) : renderMap(result));
|
|
8
8
|
});
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import { renderMap } from '../output.ts';\nimport {
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import { renderMap } from '../output.ts';\nimport { mapTree } from '../verbs.ts';\nimport { withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst map: Command = (ctx) => {\n withDb(ctx, (db, cfg) => {\n const result = mapTree(db, cfg);\n console.log(ctx.format === 'json' ? JSON.stringify(result, null, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["renderMap","mapTree","withDb","map","ctx","db","cfg","result","console","log","format","JSON","stringify"],"mappings":"AAAA,SAASA,SAAS,QAAQ,eAAe;AACzC,SAASC,OAAO,QAAQ,cAAc;AACtC,SAASC,MAAM,QAAQ,cAAc;AAGrC,MAAMC,MAAe,CAACC;IACpBF,OAAOE,KAAK,CAACC,IAAIC;QACf,MAAMC,SAASN,QAAQI,IAAIC;QAC3BE,QAAQC,GAAG,CAACL,IAAIM,MAAM,KAAK,SAASC,KAAKC,SAAS,CAACL,QAAQ,MAAM,KAAKP,UAAUO;IAClF;AACF;AACA,eAAeJ,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/named.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/named.ts"],"sourcesContent":["import { runSql } from './shared.ts';\nimport type { Ctx } from './types.ts';\n\n// Fallback when the first positional is not a command: a named query from config.\nexport default function named(ctx: Ctx, queryName: string, params: string[]): void {\n const cfg = ctx.resolveConfig();\n const sql = cfg.queries[queryName];\n if (!sql) {\n console.error(`unknown query: \"${queryName}\"`);\n console.error(`valid queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n runSql(cfg, sql, params, ctx.format, `query \"${queryName}\"`);\n}\n"],"names":["runSql","named","ctx","queryName","params","cfg","resolveConfig","sql","queries","console","error","Object","keys","sort","join","process","exit","format"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAc;AAGrC,kFAAkF;AAClF,eAAe,SAASC,MAAMC,GAAQ,EAAEC,SAAiB,EAAEC,MAAgB;IACzE,MAAMC,MAAMH,IAAII,aAAa;IAC7B,MAAMC,MAAMF,IAAIG,OAAO,CAACL,UAAU;IAClC,IAAI,CAACI,KAAK;QACRE,QAAQC,KAAK,CAAC,CAAC,gBAAgB,EAAEP,UAAU,CAAC,CAAC;QAC7CM,QAAQC,KAAK,CAAC,CAAC,eAAe,EAAEC,OAAOC,IAAI,CAACP,IAAIG,OAAO,EAAEK,IAAI,GAAGC,IAAI,CAAC,OAAO;QAC5EC,QAAQC,IAAI,CAAC;IACf;IACAhB,OAAOK,KAAKE,KAAKH,QAAQF,IAAIe,MAAM,EAAE,CAAC,OAAO,EAAEd,UAAU,CAAC,CAAC;AAC7D"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { renderPeek } from '../output.js';
|
|
2
2
|
import { peek } from '../verbs.js';
|
|
3
|
-
import {
|
|
3
|
+
import { withDb } from './shared.js';
|
|
4
4
|
const peekCmd = (ctx)=>{
|
|
5
5
|
const [pathArg] = ctx.rest;
|
|
6
6
|
if (!pathArg) ctx.usageError(`usage: ${ctx.name} peek <path>`);
|
|
7
|
-
|
|
7
|
+
withDb(ctx, (db, cfg)=>{
|
|
8
8
|
const result = peek(db, cfg, pathArg);
|
|
9
9
|
console.log(ctx.format === 'json' ? JSON.stringify(result, null, 2) : renderPeek(result));
|
|
10
10
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import { renderPeek } from '../output.ts';\nimport { peek } from '../verbs.ts';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import { renderPeek } from '../output.ts';\nimport { peek } from '../verbs.ts';\nimport { withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst peekCmd: Command = (ctx) => {\n const [pathArg] = ctx.rest;\n if (!pathArg) ctx.usageError(`usage: ${ctx.name} peek <path>`);\n withDb(ctx, (db, cfg) => {\n const result = peek(db, cfg, pathArg);\n console.log(ctx.format === 'json' ? JSON.stringify(result, null, 2) : renderPeek(result));\n });\n};\nexport default peekCmd;\n"],"names":["renderPeek","peek","withDb","peekCmd","ctx","pathArg","rest","usageError","name","db","cfg","result","console","log","format","JSON","stringify"],"mappings":"AAAA,SAASA,UAAU,QAAQ,eAAe;AAC1C,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,MAAM,QAAQ,cAAc;AAGrC,MAAMC,UAAmB,CAACC;IACxB,MAAM,CAACC,QAAQ,GAAGD,IAAIE,IAAI;IAC1B,IAAI,CAACD,SAASD,IAAIG,UAAU,CAAC,CAAC,OAAO,EAAEH,IAAII,IAAI,CAAC,YAAY,CAAC;IAC7DN,OAAOE,KAAK,CAACK,IAAIC;QACf,MAAMC,SAASV,KAAKQ,IAAIC,KAAKL;QAC7BO,QAAQC,GAAG,CAACT,IAAIU,MAAM,KAAK,SAASC,KAAKC,SAAS,CAACL,QAAQ,MAAM,KAAKX,WAAWW;IACnF;AACF;AACA,eAAeR,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/query.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/query.ts"],"sourcesContent":["import { runSql } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst query: Command = (ctx) => {\n const [sql, ...params] = ctx.rest;\n if (!sql) ctx.usageError(`usage: ${ctx.name} query \"<sql>\" [params...]`);\n runSql(ctx.resolveConfig(), sql, params, ctx.format, 'ad-hoc query');\n};\nexport default query;\n"],"names":["runSql","query","ctx","sql","params","rest","usageError","name","resolveConfig","format"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAc;AAGrC,MAAMC,QAAiB,CAACC;IACtB,MAAM,CAACC,KAAK,GAAGC,OAAO,GAAGF,IAAIG,IAAI;IACjC,IAAI,CAACF,KAAKD,IAAII,UAAU,CAAC,CAAC,OAAO,EAAEJ,IAAIK,IAAI,CAAC,0BAA0B,CAAC;IACvEP,OAAOE,IAAIM,aAAa,IAAIL,KAAKC,QAAQF,IAAIO,MAAM,EAAE;AACvD;AACA,eAAeR,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/rebuild.ts"],"sourcesContent":["import { docCount, rebuild } from '../db.ts';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/rebuild.ts"],"sourcesContent":["import { docCount, rebuild } from '../db.ts';\nimport { printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst rebuildCmd: Command = (ctx) => {\n const result = rebuild(ctx.resolveConfig());\n printWarnings(result.warnings);\n console.log(`rebuilt: ${docCount(result.db)} docs`);\n result.db.close();\n};\nexport default rebuildCmd;\n"],"names":["docCount","rebuild","printWarnings","rebuildCmd","ctx","result","resolveConfig","warnings","console","log","db","close"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,OAAO,QAAQ,WAAW;AAC7C,SAASC,aAAa,QAAQ,cAAc;AAG5C,MAAMC,aAAsB,CAACC;IAC3B,MAAMC,SAASJ,QAAQG,IAAIE,aAAa;IACxCJ,cAAcG,OAAOE,QAAQ;IAC7BC,QAAQC,GAAG,CAAC,CAAC,SAAS,EAAET,SAASK,OAAOK,EAAE,EAAE,KAAK,CAAC;IAClDL,OAAOK,EAAE,CAACC,KAAK;AACjB;AACA,eAAeR,WAAW"}
|
|
@@ -2,5 +2,5 @@ import type { ResolvedConfig } from '../config.js';
|
|
|
2
2
|
import type { OpenResult } from '../db.js';
|
|
3
3
|
import type { Ctx } from './types.js';
|
|
4
4
|
export declare function printWarnings(warnings: string[]): void;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function withDb(ctx: Ctx, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void): void;
|
|
6
6
|
export declare function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string): void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { open } from '../db.js';
|
|
2
2
|
import { printRows } from '../output.js';
|
|
3
|
-
// Shared open-query-close envelope for commands that touch the
|
|
3
|
+
// Shared open-query-close envelope for commands that touch the tree.
|
|
4
4
|
export function printWarnings(warnings) {
|
|
5
5
|
for (const w of warnings)console.warn(w);
|
|
6
6
|
}
|
|
7
|
-
export function
|
|
7
|
+
export function withDb(ctx, fn) {
|
|
8
8
|
const cfg = ctx.resolveConfig();
|
|
9
9
|
const { db, warnings } = open(cfg);
|
|
10
10
|
printWarnings(warnings);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/shared.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport type { Ctx } from './types.ts';\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport function withDb(ctx: Ctx, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void): void {\n const cfg = ctx.resolveConfig();\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n printRows(db.prepare(sql).all(...params) as Row[], format);\n db.close();\n}\n"],"names":["open","printRows","printWarnings","warnings","w","console","warn","withDb","ctx","fn","cfg","resolveConfig","db","close","runSql","sql","params","format","label","placeholderCount","match","length","error","process","exit","prepare","all"],"mappings":"AAEA,SAASA,IAAI,QAAQ,WAAW;AAEhC,SAASC,SAAS,QAAQ,eAAe;AAGzC,qEAAqE;AAErE,OAAO,SAASC,cAAcC,QAAkB;IAC9C,KAAK,MAAMC,KAAKD,SAAUE,QAAQC,IAAI,CAACF;AACzC;AAEA,OAAO,SAASG,OAAOC,GAAQ,EAAEC,EAAuD;IACtF,MAAMC,MAAMF,IAAIG,aAAa;IAC7B,MAAM,EAAEC,EAAE,EAAET,QAAQ,EAAE,GAAGH,KAAKU;IAC9BR,cAAcC;IACd,IAAI;QACFM,GAAGG,IAAIF;IACT,SAAU;QACRE,GAAGC,KAAK;IACV;AACF;AAEA,sFAAsF;AACtF,OAAO,SAASC,OAAOJ,GAAmB,EAAEK,GAAW,EAAEC,MAAgB,EAAEC,MAAwB,EAAEC,KAAa;QACtFH;IAA1B,MAAMI,mBAAmB,EAACJ,aAAAA,IAAIK,KAAK,CAAC,oBAAVL,wBAAAA,aAAoB,EAAE,EAAEM,MAAM;IACxD,IAAIL,OAAOK,MAAM,KAAKF,kBAAkB;QACtCd,QAAQiB,KAAK,CAAC,GAAGJ,MAAM,SAAS,EAAEC,iBAAiB,mBAAmB,EAAEH,OAAOK,MAAM,EAAE;QACvFE,QAAQC,IAAI,CAAC;IACf;IACA,MAAM,EAAEZ,EAAE,EAAET,QAAQ,EAAE,GAAGH,KAAKU;IAC9BR,cAAcC;IACdF,UAAUW,GAAGa,OAAO,CAACV,KAAKW,GAAG,IAAIV,SAAkBC;IACnDL,GAAGC,KAAK;AACV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/status.ts"],"sourcesContent":["import { docCount, getMeta, open } from '../db.ts';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/status.ts"],"sourcesContent":["import { docCount, getMeta, open } from '../db.ts';\nimport { printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst status: Command = (ctx) => {\n const { db, dbPath, warnings } = open(ctx.resolveConfig());\n printWarnings(warnings);\n console.log(`db: ${dbPath}`);\n console.log(`docs: ${docCount(db)}`);\n const heartbeat = getMeta(db, 'watch_heartbeat');\n if (heartbeat) console.log(`watcher: last heartbeat ${Math.round((Date.now() - Date.parse(heartbeat)) / 1000)}s ago`);\n else console.log('watcher: no watcher');\n db.close();\n};\nexport default status;\n"],"names":["docCount","getMeta","open","printWarnings","status","ctx","db","dbPath","warnings","resolveConfig","console","log","heartbeat","Math","round","Date","now","parse","close"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,OAAO,EAAEC,IAAI,QAAQ,WAAW;AACnD,SAASC,aAAa,QAAQ,cAAc;AAG5C,MAAMC,SAAkB,CAACC;IACvB,MAAM,EAAEC,EAAE,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGN,KAAKG,IAAII,aAAa;IACvDN,cAAcK;IACdE,QAAQC,GAAG,CAAC,CAAC,IAAI,EAAEJ,QAAQ;IAC3BG,QAAQC,GAAG,CAAC,CAAC,MAAM,EAAEX,SAASM,KAAK;IACnC,MAAMM,YAAYX,QAAQK,IAAI;IAC9B,IAAIM,WAAWF,QAAQC,GAAG,CAAC,CAAC,wBAAwB,EAAEE,KAAKC,KAAK,CAAC,AAACC,CAAAA,KAAKC,GAAG,KAAKD,KAAKE,KAAK,CAACL,UAAS,IAAK,MAAM,KAAK,CAAC;SAC/GF,QAAQC,GAAG,CAAC;IACjBL,GAAGY,KAAK;AACV;AACA,eAAed,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/watch.ts"],"sourcesContent":["import type { WatchEvent } from '../watch.ts';\nimport { runWatch } from '../watch.ts';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/watch.ts"],"sourcesContent":["import type { WatchEvent } from '../watch.ts';\nimport { runWatch } from '../watch.ts';\nimport { printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst watch: Command = async (ctx) => {\n await runWatch(ctx.resolveConfig(), {\n force: ctx.values.force,\n onEvent: (event: WatchEvent) => {\n if (event.type === 'started') {\n console.log(`${ctx.name} watch: watching ${event.baseDir}`);\n console.log(`${ctx.name} watch: db ${event.dbPath}`);\n } else if (event.type === 'reconciled') {\n printWarnings(event.warnings);\n if (event.parsed > 0) console.log(`${ctx.name} watch: reconciled, ${event.parsed} file(s) reparsed (${event.total} total)`);\n } else {\n console.error(`${ctx.name} watch: reconcile error: ${event.message}`);\n }\n },\n });\n};\nexport default watch;\n"],"names":["runWatch","printWarnings","watch","ctx","resolveConfig","force","values","onEvent","event","type","console","log","name","baseDir","dbPath","warnings","parsed","total","error","message"],"mappings":"AACA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,aAAa,QAAQ,cAAc;AAG5C,MAAMC,QAAiB,OAAOC;IAC5B,MAAMH,SAASG,IAAIC,aAAa,IAAI;QAClCC,OAAOF,IAAIG,MAAM,CAACD,KAAK;QACvBE,SAAS,CAACC;YACR,IAAIA,MAAMC,IAAI,KAAK,WAAW;gBAC5BC,QAAQC,GAAG,CAAC,GAAGR,IAAIS,IAAI,CAAC,iBAAiB,EAAEJ,MAAMK,OAAO,EAAE;gBAC1DH,QAAQC,GAAG,CAAC,GAAGR,IAAIS,IAAI,CAAC,WAAW,EAAEJ,MAAMM,MAAM,EAAE;YACrD,OAAO,IAAIN,MAAMC,IAAI,KAAK,cAAc;gBACtCR,cAAcO,MAAMO,QAAQ;gBAC5B,IAAIP,MAAMQ,MAAM,GAAG,GAAGN,QAAQC,GAAG,CAAC,GAAGR,IAAIS,IAAI,CAAC,oBAAoB,EAAEJ,MAAMQ,MAAM,CAAC,mBAAmB,EAAER,MAAMS,KAAK,CAAC,OAAO,CAAC;YAC5H,OAAO;gBACLP,QAAQQ,KAAK,CAAC,GAAGf,IAAIS,IAAI,CAAC,yBAAyB,EAAEJ,MAAMW,OAAO,EAAE;YACtE;QACF;IACF;AACF;AACA,eAAejB,MAAM"}
|
|
@@ -36,7 +36,7 @@ function resolveTarget(src, target, pathSet, byBase) {
|
|
|
36
36
|
return (_ref = (_byBase_get = byBase.get(baseKey(clean))) === null || _byBase_get === void 0 ? void 0 : _byBase_get[0]) !== null && _ref !== void 0 ? _ref : null;
|
|
37
37
|
}
|
|
38
38
|
// A new or deleted file can change any note's resolution, so re-resolve the whole table
|
|
39
|
-
// whenever the
|
|
39
|
+
// whenever the tree changes. An in-memory probe per row; writes only on change.
|
|
40
40
|
function resolveAll(db, files) {
|
|
41
41
|
const pathSet = new Set(files.map((f)=>f.relPath));
|
|
42
42
|
const byBase = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/links.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { FileStat } from '../scan.ts';\nimport type { Feature } from './types.ts';\n\n// links(src, target, dst): target as written, dst the resolved path or NULL (a queryable dead link).\n\n// Wikilinks ([[target]], [[target#anchor|alias]], embeds) plus relative markdown links to .md files.\nfunction extract(_raw: string, body: string): string[] {\n const targets = new Set<string>();\n for (const m of body.matchAll(/\\[\\[([^\\]|#]+)(?:#[^\\]|]*)?(?:\\|[^\\]]*)?\\]\\]/g)) {\n const target = m[1].trim();\n if (target) targets.add(target);\n }\n for (const m of body.matchAll(/\\]\\(([^)]+\\.md)(?:#[^)]*)?\\)/g)) {\n const target = m[1].trim();\n if (target && !/^[a-z]+:\\/\\//i.test(target)) targets.add(target);\n }\n return [...targets];\n}\n\nfunction baseKey(path: string): string {\n return posix.basename(path).replace(/\\.md$/i, '').toLowerCase();\n}\n\n// Obsidian-style: exact relative path (with/without .md), path relative to the linking\n// note's directory, then basename match (lexicographically first on ties).\nfunction resolveTarget(src: string, target: string, pathSet: Set<string>, byBase: Map<string, string[]>): string | null {\n const clean = target.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n const fromSrc = posix.normalize(posix.join(posix.dirname(src), clean));\n for (const candidate of [clean, `${clean}.md`, fromSrc, `${fromSrc}.md`]) {\n if (pathSet.has(candidate)) return candidate;\n }\n return byBase.get(baseKey(clean))?.[0] ?? null;\n}\n\n// A new or deleted file can change any note's resolution, so re-resolve the whole table\n// whenever the
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/links.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { FileStat } from '../scan.ts';\nimport type { Feature } from './types.ts';\n\n// links(src, target, dst): target as written, dst the resolved path or NULL (a queryable dead link).\n\n// Wikilinks ([[target]], [[target#anchor|alias]], embeds) plus relative markdown links to .md files.\nfunction extract(_raw: string, body: string): string[] {\n const targets = new Set<string>();\n for (const m of body.matchAll(/\\[\\[([^\\]|#]+)(?:#[^\\]|]*)?(?:\\|[^\\]]*)?\\]\\]/g)) {\n const target = m[1].trim();\n if (target) targets.add(target);\n }\n for (const m of body.matchAll(/\\]\\(([^)]+\\.md)(?:#[^)]*)?\\)/g)) {\n const target = m[1].trim();\n if (target && !/^[a-z]+:\\/\\//i.test(target)) targets.add(target);\n }\n return [...targets];\n}\n\nfunction baseKey(path: string): string {\n return posix.basename(path).replace(/\\.md$/i, '').toLowerCase();\n}\n\n// Obsidian-style: exact relative path (with/without .md), path relative to the linking\n// note's directory, then basename match (lexicographically first on ties).\nfunction resolveTarget(src: string, target: string, pathSet: Set<string>, byBase: Map<string, string[]>): string | null {\n const clean = target.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n const fromSrc = posix.normalize(posix.join(posix.dirname(src), clean));\n for (const candidate of [clean, `${clean}.md`, fromSrc, `${fromSrc}.md`]) {\n if (pathSet.has(candidate)) return candidate;\n }\n return byBase.get(baseKey(clean))?.[0] ?? null;\n}\n\n// A new or deleted file can change any note's resolution, so re-resolve the whole table\n// whenever the tree changes. An in-memory probe per row; writes only on change.\nfunction resolveAll(db: DatabaseSync, files: FileStat[]): void {\n const pathSet = new Set(files.map((f) => f.relPath));\n const byBase = new Map<string, string[]>();\n for (const path of [...pathSet].sort()) {\n const list = byBase.get(baseKey(path));\n if (list) list.push(path);\n else byBase.set(baseKey(path), [path]);\n }\n const rows = db.prepare('SELECT src, target, dst FROM links').all() as Array<{ src: string; target: string; dst: string | null }>;\n const update = db.prepare('UPDATE links SET dst = ? WHERE src = ? AND target = ?');\n for (const row of rows) {\n const dst = resolveTarget(row.src, row.target, pathSet, byBase);\n if (dst !== row.dst) update.run(dst, row.src, row.target);\n }\n}\n\n// Resolved edges, for rank and for find's graph expansion.\nexport function linkEdges(db: DatabaseSync): [string, string][] {\n return (db.prepare('SELECT src, dst FROM links WHERE dst IS NOT NULL').all() as Array<{ src: string; dst: string }>).map((r) => [r.src, r.dst]);\n}\n\nexport const links: Feature = {\n name: 'links',\n schema(db) {\n db.exec('CREATE TABLE IF NOT EXISTS links (src TEXT, target TEXT, dst TEXT, PRIMARY KEY (src, target))');\n db.exec('CREATE INDEX IF NOT EXISTS links_dst ON links(dst)');\n },\n extract,\n remove(db, path) {\n db.prepare('DELETE FROM links WHERE src = ?').run(path);\n },\n store(db, path, extracted) {\n const insert = db.prepare('INSERT OR REPLACE INTO links (src, target, dst) VALUES (?, ?, NULL)');\n for (const target of extracted as string[]) insert.run(path, target);\n },\n afterReconcile: resolveAll,\n};\n"],"names":["posix","extract","_raw","body","targets","Set","m","matchAll","target","trim","add","test","baseKey","path","basename","replace","toLowerCase","resolveTarget","src","pathSet","byBase","clean","fromSrc","normalize","join","dirname","candidate","has","get","resolveAll","db","files","map","f","relPath","Map","sort","list","push","set","rows","prepare","all","update","row","dst","run","linkEdges","r","links","name","schema","exec","remove","store","extracted","insert","afterReconcile"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/types.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { FeatureName } from '../config.ts';\nimport type { FileStat } from '../scan.ts';\n\n// A feature owns its schema, per-file extraction/storage, and any whole-
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/types.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { FeatureName } from '../config.ts';\nimport type { FileStat } from '../scan.ts';\n\n// A feature owns its schema, per-file extraction/storage, and any whole-tree pass.\n// Adding a feature = one module here + one entry in the registry (index.ts).\nexport interface Feature {\n name: FeatureName;\n schema(db: DatabaseSync): void;\n // Pure, per file: raw is the full file, body the prose after frontmatter.\n extract?(raw: string, body: string): unknown;\n remove?(db: DatabaseSync, path: string): void;\n store?(db: DatabaseSync, path: string, extracted: unknown): void;\n // After all rows are current, inside the reconcile transaction (resolution, rank).\n afterReconcile?(db: DatabaseSync, files: FileStat[]): void;\n}\n"],"names":[],"mappings":"AAIA,mFAAmF;AACnF,6EAA6E;AAC7E,WASC"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type { Row } from './output.js';
|
|
|
13
13
|
export { printRows } from './output.js';
|
|
14
14
|
export type { FileStat, ParsedDoc } from './scan.js';
|
|
15
15
|
export { listFiles, parseFile } from './scan.js';
|
|
16
|
-
export type { FindOptions, Peek,
|
|
17
|
-
export { find,
|
|
16
|
+
export type { FindOptions, Peek, TreeMap } from './verbs.js';
|
|
17
|
+
export { find, mapTree, peek } from './verbs.js';
|
|
18
18
|
export type { WatchEvent, WatchOptions } from './watch.js';
|
|
19
19
|
export { runWatch } from './watch.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -6,5 +6,5 @@ export { activeFeatures, FEATURES, linkEdges } from './features/index.js';
|
|
|
6
6
|
export { pagerank, personalizedRank } from './graph.js';
|
|
7
7
|
export { printRows } from './output.js';
|
|
8
8
|
export { listFiles, parseFile } from './scan.js';
|
|
9
|
-
export { find,
|
|
9
|
+
export { find, mapTree, peek } from './verbs.js';
|
|
10
10
|
export { runWatch } from './watch.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API.\n\nexport type { Config, FeatureName, ResolvedConfig } from './config.ts';\nexport { CONFIG_FILENAME, enabledFeatures, FEATURE_NAMES, featureEnabled, findConfigPath, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\nexport type { OpenResult } from './db.ts';\nexport { DB_FILENAME, docCount, getMeta, open, rebuild, reconcile, setMeta } from './db.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport { activeFeatures, FEATURES, linkEdges } from './features/index.ts';\nexport type { Section } from './features/sections.ts';\nexport type { Feature } from './features/types.ts';\n\nexport type { Edge } from './graph.ts';\nexport { pagerank, personalizedRank } from './graph.ts';\n\nexport type { Row } from './output.ts';\nexport { printRows } from './output.ts';\n\nexport type { FileStat, ParsedDoc } from './scan.ts';\nexport { listFiles, parseFile } from './scan.ts';\n\nexport type { FindOptions, Peek,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API.\n\nexport type { Config, FeatureName, ResolvedConfig } from './config.ts';\nexport { CONFIG_FILENAME, enabledFeatures, FEATURE_NAMES, featureEnabled, findConfigPath, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\nexport type { OpenResult } from './db.ts';\nexport { DB_FILENAME, docCount, getMeta, open, rebuild, reconcile, setMeta } from './db.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport { activeFeatures, FEATURES, linkEdges } from './features/index.ts';\nexport type { Section } from './features/sections.ts';\nexport type { Feature } from './features/types.ts';\n\nexport type { Edge } from './graph.ts';\nexport { pagerank, personalizedRank } from './graph.ts';\n\nexport type { Row } from './output.ts';\nexport { printRows } from './output.ts';\n\nexport type { FileStat, ParsedDoc } from './scan.ts';\nexport { listFiles, parseFile } from './scan.ts';\n\nexport type { FindOptions, Peek, TreeMap } from './verbs.ts';\nexport { find, mapTree, peek } from './verbs.ts';\n\nexport type { WatchEvent, WatchOptions } from './watch.ts';\nexport { runWatch } from './watch.ts';\n"],"names":["CONFIG_FILENAME","enabledFeatures","FEATURE_NAMES","featureEnabled","findConfigPath","initConfig","loadConfig","migrateConfig","STATE_DIR","SUPPORTED_CONFIG_VERSION","DB_FILENAME","docCount","getMeta","open","rebuild","reconcile","setMeta","SenseError","activeFeatures","FEATURES","linkEdges","pagerank","personalizedRank","printRows","listFiles","parseFile","find","mapTree","peek","runWatch"],"mappings":"AAAA,sBAAsB;AAGtB,SAASA,eAAe,EAAEC,eAAe,EAAEC,aAAa,EAAEC,cAAc,EAAEC,cAAc,EAAEC,UAAU,EAAEC,UAAU,EAAEC,aAAa,EAAEC,SAAS,EAAEC,wBAAwB,QAAQ,cAAc;AAG1L,SAASC,WAAW,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,IAAI,EAAEC,OAAO,EAAEC,SAAS,EAAEC,OAAO,QAAQ,UAAU;AAE5F,SAASC,UAAU,QAAQ,cAAc;AACzC,SAASC,cAAc,EAAEC,QAAQ,EAAEC,SAAS,QAAQ,sBAAsB;AAK1E,SAASC,QAAQ,EAAEC,gBAAgB,QAAQ,aAAa;AAGxD,SAASC,SAAS,QAAQ,cAAc;AAGxC,SAASC,SAAS,EAAEC,SAAS,QAAQ,YAAY;AAGjD,SAASC,IAAI,EAAEC,OAAO,EAAEC,IAAI,QAAQ,aAAa;AAGjD,SAASC,QAAQ,QAAQ,aAAa"}
|
package/dist/esm/verbs.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface FindOptions {
|
|
|
6
6
|
where?: string;
|
|
7
7
|
}
|
|
8
8
|
export declare function find(db: DatabaseSync, cfg: Config, terms: string, opts?: FindOptions): Row[];
|
|
9
|
-
export interface
|
|
9
|
+
export interface TreeMap {
|
|
10
10
|
docs: {
|
|
11
11
|
count: number;
|
|
12
12
|
bytes: number;
|
|
@@ -16,7 +16,7 @@ export interface VaultMap {
|
|
|
16
16
|
hubs: Row[];
|
|
17
17
|
recent: Row[];
|
|
18
18
|
}
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function mapTree(db: DatabaseSync, cfg: Config): TreeMap;
|
|
20
20
|
export interface Peek {
|
|
21
21
|
path: string;
|
|
22
22
|
tokens: number;
|
package/dist/esm/verbs.js
CHANGED
|
@@ -3,7 +3,7 @@ import { featureEnabled } from './config.js';
|
|
|
3
3
|
import { SenseError } from './errors.js';
|
|
4
4
|
import { linkEdges } from './features/index.js';
|
|
5
5
|
import { personalizedRank } from './graph.js';
|
|
6
|
-
// The three layer verbs:
|
|
6
|
+
// The three layer verbs: mapTree (orient), find (locate), peek (structure).
|
|
7
7
|
// Each returns data; cli.ts renders. All of them degrade when a feature is off.
|
|
8
8
|
const WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0)';
|
|
9
9
|
const RRF_K = 60;
|
|
@@ -65,8 +65,8 @@ const INTERNAL_COLUMNS = new Set([
|
|
|
65
65
|
'_size',
|
|
66
66
|
'_rank'
|
|
67
67
|
]);
|
|
68
|
-
// Layer 0: what is this
|
|
69
|
-
export function
|
|
68
|
+
// Layer 0: what is this tree. Fixed-size output regardless of tree size.
|
|
69
|
+
export function mapTree(db, cfg) {
|
|
70
70
|
const docs = db.prepare('SELECT COUNT(*) AS count, COALESCE(SUM("_size"), 0) AS bytes FROM frontmatter').get();
|
|
71
71
|
const columns = db.prepare('PRAGMA table_info(frontmatter)').all().map((r)=>r.name).filter((name)=>!INTERNAL_COLUMNS.has(name));
|
|
72
72
|
const allFields = columns.map((name)=>{
|
package/dist/esm/verbs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/verbs.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { Config } from './config.ts';\nimport { featureEnabled } from './config.ts';\nimport { SenseError } from './errors.ts';\nimport { linkEdges } from './features/index.ts';\nimport { personalizedRank } from './graph.ts';\nimport type { Row } from './output.ts';\n\n// The three layer verbs: vaultMap (orient), find (locate), peek (structure).\n// Each returns data; cli.ts renders. All of them degrade when a feature is off.\n\nconst WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0)';\nconst RRF_K = 60;\n\nexport interface FindOptions {\n k?: number;\n where?: string; // SQL fragment against frontmatter alias `f`, e.g. \"f.status = 'active'\"\n}\n\n// Layer 1: BM25 + link-graph expansion, fused by reciprocal rank. `via` says which\n// signal produced each row so the agent knows what evidence it is trusting.\nexport function find(db: DatabaseSync, cfg: Config, terms: string, opts: FindOptions = {}): Row[] {\n const k = opts.k ?? 10;\n const fetch = Math.max(k * 3, 30);\n\n // Terms pass verbatim to FTS5 MATCH: bare words AND-join, operators are the caller's.\n // Invalid syntax propagates as an error, zero matches return zero -- no silent rewrites.\n const matchSql = `SELECT content.path AS path, snippet(content, -1, '«', '»', '…', 10) AS hit FROM content WHERE content MATCH ? ORDER BY ${WEIGHTED_BM25} LIMIT ${fetch}`;\n const matchRows = db.prepare(matchSql).all(terms) as Array<{ path: string; hit: string }>;\n\n const hits = new Map(matchRows.map((r) => [r.path, r.hit]));\n const candidates = new Map<string, { score: number; via: string }>();\n matchRows.forEach((r, i) => {\n candidates.set(r.path, { score: 1 / (RRF_K + i), via: 'match' });\n });\n\n if (featureEnabled(cfg, 'links') && matchRows.length > 0) {\n const nodes = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const seeds = new Map(matchRows.map((r, i) => [r.path, 1 / (i + 1)]));\n const ranked = [...personalizedRank(nodes, linkEdges(db), seeds)]\n .filter(([, score]) => score > 1e-9)\n .sort((a, b) => b[1] - a[1])\n .slice(0, fetch);\n ranked.forEach(([path], i) => {\n const existing = candidates.get(path);\n if (existing) {\n existing.score += 1 / (RRF_K + i);\n existing.via = 'match+link';\n } else {\n candidates.set(path, { score: 1 / (RRF_K + i), via: 'link' });\n }\n });\n }\n\n db.exec('CREATE TEMP TABLE IF NOT EXISTS _find (\"path\" TEXT PRIMARY KEY, score REAL, via TEXT, hit TEXT)');\n db.exec('DELETE FROM _find');\n const insert = db.prepare('INSERT INTO _find (\"path\", score, via, hit) VALUES (?, ?, ?, ?)');\n for (const [path, c] of candidates) insert.run(path, c.score, c.via, hits.get(path) ?? null);\n\n const where = opts.where ? `WHERE ${opts.where}` : '';\n return db\n .prepare(\n `SELECT f.\"path\" AS path, content.title, content.summary, _find.hit, _find.via, round(_find.score, 4) AS score\n FROM _find JOIN frontmatter f ON f.\"path\" = _find.\"path\" JOIN content ON content.path = _find.\"path\"\n ${where} ORDER BY _find.score DESC LIMIT ?`\n )\n .all(k) as Row[];\n}\n\nexport interface VaultMap {\n docs: { count: number; bytes: number };\n fields: Row[]; // top 20 by coverage; fieldsTotal carries the real count\n fieldsTotal: number;\n hubs: Row[];\n recent: Row[];\n}\n\nconst INTERNAL_COLUMNS = new Set(['path', '_mtime', '_size', '_rank']);\n\n// Layer 0: what is this vault. Fixed-size output regardless of vault size.\nexport function vaultMap(db: DatabaseSync, cfg: Config): VaultMap {\n const docs = db.prepare('SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter').get() as { count: number; bytes: number };\n\n const columns = (db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>).map((r) => r.name).filter((name) => !INTERNAL_COLUMNS.has(name));\n const allFields = columns\n .map((name) => {\n const { n } = db.prepare(`SELECT COUNT(\"${name.split('\"').join('\"\"')}\") AS n FROM frontmatter`).get() as { n: number };\n return { field: name, coverage: n };\n })\n .sort((a, b) => (b.coverage as number) - (a.coverage as number)) as Row[];\n const fields = allFields.slice(0, 20);\n\n const hubs = featureEnabled(cfg, 'rank') ? (db.prepare(`SELECT f.\"path\" AS path, round(f.\"_rank\" * 100, 2) AS rank, content.title FROM frontmatter f JOIN content ON content.path = f.\"path\" WHERE f.\"_rank\" IS NOT NULL ORDER BY f.\"_rank\" DESC LIMIT 8`).all() as Row[]) : [];\n\n const recent = db.prepare(`SELECT \"path\", datetime(\"_mtime\" / 1000, 'unixepoch') AS modified FROM frontmatter ORDER BY \"_mtime\" DESC LIMIT 5`).all() as Row[];\n\n return { docs, fields, fieldsTotal: allFields.length, hubs, recent };\n}\n\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n sections: Row[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n // Totals before truncation: a hub can have thousands of backlinks, and peek's whole\n // point is bounded output. Query the links table directly for the full list.\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n}\n\nconst PEEK_LINK_LIMIT = 20;\n\n// Layer 2: everything about one note except its prose -- frontmatter, outline with line\n// ranges + token estimates (so the follow-up Read is a range, not the file), links both ways.\nexport function peek(db: DatabaseSync, cfg: Config, pathArg: string): Peek {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n let path = paths.find((p) => p === pathArg);\n if (!path) {\n const base = posix.basename(pathArg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) path = matches[0];\n else if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${pathArg}\" is ambiguous: ${matches.join(', ')}`);\n else throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${pathArg}\"`);\n }\n\n const row = db.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?').get(path) as Row;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n const sections = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx').all(path) as Row[]) : [];\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n if (featureEnabled(cfg, 'links')) {\n const out = db.prepare('SELECT target, dst FROM links WHERE src = ? ORDER BY target').all(path) as Array<{ target: string; dst: string | null }>;\n outbound = [...new Set(out.filter((l) => l.dst !== null).map((l) => l.dst as string))];\n unresolved = out.filter((l) => l.dst === null).map((l) => l.target);\n backlinksTotal = (db.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ?').get(path) as { n: number }).n;\n backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? ORDER BY src LIMIT ?').all(path, PEEK_LINK_LIMIT) as Array<{ src: string }>).map((r) => r.src);\n }\n\n return {\n path,\n tokens: Math.ceil(((row._size as number) ?? 0) / 4),\n frontmatter,\n sections,\n outbound: outbound.slice(0, PEEK_LINK_LIMIT),\n backlinks,\n unresolved: unresolved.slice(0, PEEK_LINK_LIMIT),\n outboundTotal: outbound.length,\n backlinksTotal,\n unresolvedTotal: unresolved.length,\n };\n}\n"],"names":["posix","featureEnabled","SenseError","linkEdges","personalizedRank","WEIGHTED_BM25","RRF_K","find","db","cfg","terms","opts","hits","k","fetch","Math","max","matchSql","matchRows","prepare","all","Map","map","r","path","hit","candidates","forEach","i","set","score","via","length","nodes","seeds","ranked","filter","sort","a","b","slice","existing","get","exec","insert","c","run","where","INTERNAL_COLUMNS","Set","vaultMap","docs","columns","name","has","allFields","n","split","join","field","coverage","fields","hubs","recent","fieldsTotal","PEEK_LINK_LIMIT","peek","pathArg","row","paths","p","base","basename","replace","toLowerCase","matches","frontmatter","key","value","Object","entries","sections","outbound","backlinks","unresolved","backlinksTotal","out","l","dst","target","src","tokens","ceil","_size","outboundTotal","unresolvedTotal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/verbs.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { Config } from './config.ts';\nimport { featureEnabled } from './config.ts';\nimport { SenseError } from './errors.ts';\nimport { linkEdges } from './features/index.ts';\nimport { personalizedRank } from './graph.ts';\nimport type { Row } from './output.ts';\n\n// The three layer verbs: mapTree (orient), find (locate), peek (structure).\n// Each returns data; cli.ts renders. All of them degrade when a feature is off.\n\nconst WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0)';\nconst RRF_K = 60;\n\nexport interface FindOptions {\n k?: number;\n where?: string; // SQL fragment against frontmatter alias `f`, e.g. \"f.status = 'active'\"\n}\n\n// Layer 1: BM25 + link-graph expansion, fused by reciprocal rank. `via` says which\n// signal produced each row so the agent knows what evidence it is trusting.\nexport function find(db: DatabaseSync, cfg: Config, terms: string, opts: FindOptions = {}): Row[] {\n const k = opts.k ?? 10;\n const fetch = Math.max(k * 3, 30);\n\n // Terms pass verbatim to FTS5 MATCH: bare words AND-join, operators are the caller's.\n // Invalid syntax propagates as an error, zero matches return zero -- no silent rewrites.\n const matchSql = `SELECT content.path AS path, snippet(content, -1, '«', '»', '…', 10) AS hit FROM content WHERE content MATCH ? ORDER BY ${WEIGHTED_BM25} LIMIT ${fetch}`;\n const matchRows = db.prepare(matchSql).all(terms) as Array<{ path: string; hit: string }>;\n\n const hits = new Map(matchRows.map((r) => [r.path, r.hit]));\n const candidates = new Map<string, { score: number; via: string }>();\n matchRows.forEach((r, i) => {\n candidates.set(r.path, { score: 1 / (RRF_K + i), via: 'match' });\n });\n\n if (featureEnabled(cfg, 'links') && matchRows.length > 0) {\n const nodes = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const seeds = new Map(matchRows.map((r, i) => [r.path, 1 / (i + 1)]));\n const ranked = [...personalizedRank(nodes, linkEdges(db), seeds)]\n .filter(([, score]) => score > 1e-9)\n .sort((a, b) => b[1] - a[1])\n .slice(0, fetch);\n ranked.forEach(([path], i) => {\n const existing = candidates.get(path);\n if (existing) {\n existing.score += 1 / (RRF_K + i);\n existing.via = 'match+link';\n } else {\n candidates.set(path, { score: 1 / (RRF_K + i), via: 'link' });\n }\n });\n }\n\n db.exec('CREATE TEMP TABLE IF NOT EXISTS _find (\"path\" TEXT PRIMARY KEY, score REAL, via TEXT, hit TEXT)');\n db.exec('DELETE FROM _find');\n const insert = db.prepare('INSERT INTO _find (\"path\", score, via, hit) VALUES (?, ?, ?, ?)');\n for (const [path, c] of candidates) insert.run(path, c.score, c.via, hits.get(path) ?? null);\n\n const where = opts.where ? `WHERE ${opts.where}` : '';\n return db\n .prepare(\n `SELECT f.\"path\" AS path, content.title, content.summary, _find.hit, _find.via, round(_find.score, 4) AS score\n FROM _find JOIN frontmatter f ON f.\"path\" = _find.\"path\" JOIN content ON content.path = _find.\"path\"\n ${where} ORDER BY _find.score DESC LIMIT ?`\n )\n .all(k) as Row[];\n}\n\nexport interface TreeMap {\n docs: { count: number; bytes: number };\n fields: Row[]; // top 20 by coverage; fieldsTotal carries the real count\n fieldsTotal: number;\n hubs: Row[];\n recent: Row[];\n}\n\nconst INTERNAL_COLUMNS = new Set(['path', '_mtime', '_size', '_rank']);\n\n// Layer 0: what is this tree. Fixed-size output regardless of tree size.\nexport function mapTree(db: DatabaseSync, cfg: Config): TreeMap {\n const docs = db.prepare('SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter').get() as { count: number; bytes: number };\n\n const columns = (db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>).map((r) => r.name).filter((name) => !INTERNAL_COLUMNS.has(name));\n const allFields = columns\n .map((name) => {\n const { n } = db.prepare(`SELECT COUNT(\"${name.split('\"').join('\"\"')}\") AS n FROM frontmatter`).get() as { n: number };\n return { field: name, coverage: n };\n })\n .sort((a, b) => (b.coverage as number) - (a.coverage as number)) as Row[];\n const fields = allFields.slice(0, 20);\n\n const hubs = featureEnabled(cfg, 'rank') ? (db.prepare(`SELECT f.\"path\" AS path, round(f.\"_rank\" * 100, 2) AS rank, content.title FROM frontmatter f JOIN content ON content.path = f.\"path\" WHERE f.\"_rank\" IS NOT NULL ORDER BY f.\"_rank\" DESC LIMIT 8`).all() as Row[]) : [];\n\n const recent = db.prepare(`SELECT \"path\", datetime(\"_mtime\" / 1000, 'unixepoch') AS modified FROM frontmatter ORDER BY \"_mtime\" DESC LIMIT 5`).all() as Row[];\n\n return { docs, fields, fieldsTotal: allFields.length, hubs, recent };\n}\n\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n sections: Row[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n // Totals before truncation: a hub can have thousands of backlinks, and peek's whole\n // point is bounded output. Query the links table directly for the full list.\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n}\n\nconst PEEK_LINK_LIMIT = 20;\n\n// Layer 2: everything about one note except its prose -- frontmatter, outline with line\n// ranges + token estimates (so the follow-up Read is a range, not the file), links both ways.\nexport function peek(db: DatabaseSync, cfg: Config, pathArg: string): Peek {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n let path = paths.find((p) => p === pathArg);\n if (!path) {\n const base = posix.basename(pathArg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) path = matches[0];\n else if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${pathArg}\" is ambiguous: ${matches.join(', ')}`);\n else throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${pathArg}\"`);\n }\n\n const row = db.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?').get(path) as Row;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n const sections = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx').all(path) as Row[]) : [];\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n if (featureEnabled(cfg, 'links')) {\n const out = db.prepare('SELECT target, dst FROM links WHERE src = ? ORDER BY target').all(path) as Array<{ target: string; dst: string | null }>;\n outbound = [...new Set(out.filter((l) => l.dst !== null).map((l) => l.dst as string))];\n unresolved = out.filter((l) => l.dst === null).map((l) => l.target);\n backlinksTotal = (db.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ?').get(path) as { n: number }).n;\n backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? ORDER BY src LIMIT ?').all(path, PEEK_LINK_LIMIT) as Array<{ src: string }>).map((r) => r.src);\n }\n\n return {\n path,\n tokens: Math.ceil(((row._size as number) ?? 0) / 4),\n frontmatter,\n sections,\n outbound: outbound.slice(0, PEEK_LINK_LIMIT),\n backlinks,\n unresolved: unresolved.slice(0, PEEK_LINK_LIMIT),\n outboundTotal: outbound.length,\n backlinksTotal,\n unresolvedTotal: unresolved.length,\n };\n}\n"],"names":["posix","featureEnabled","SenseError","linkEdges","personalizedRank","WEIGHTED_BM25","RRF_K","find","db","cfg","terms","opts","hits","k","fetch","Math","max","matchSql","matchRows","prepare","all","Map","map","r","path","hit","candidates","forEach","i","set","score","via","length","nodes","seeds","ranked","filter","sort","a","b","slice","existing","get","exec","insert","c","run","where","INTERNAL_COLUMNS","Set","mapTree","docs","columns","name","has","allFields","n","split","join","field","coverage","fields","hubs","recent","fieldsTotal","PEEK_LINK_LIMIT","peek","pathArg","row","paths","p","base","basename","replace","toLowerCase","matches","frontmatter","key","value","Object","entries","sections","outbound","backlinks","unresolved","backlinksTotal","out","l","dst","target","src","tokens","ceil","_size","outboundTotal","unresolvedTotal"],"mappings":"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"}
|
package/package.json
CHANGED
package/skills/sense/EXAMPLES.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Outputs below are illustrative. Every result is a reference; reading happens afterward, through
|
|
4
4
|
the filesystem, on the paths that earned it.
|
|
5
5
|
|
|
6
|
-
## A. "
|
|
6
|
+
## A. "Do the notes say anything about X?"
|
|
7
7
|
|
|
8
8
|
```
|
|
9
9
|
sense find "pricing OR billing OR invoicing" --k 10 --format json
|
|
@@ -19,8 +19,7 @@ sense find "pricing OR billing OR invoicing" --k 10 --format json
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
~30 tokens per row; often the `summary` answers the question with no read at all. A row with
|
|
22
|
-
`via: "link"` never contained the terms — it is linked from notes that did
|
|
23
|
-
worth following, not noise.
|
|
22
|
+
`via: "link"` never contained the terms — it is linked from notes that did.
|
|
24
23
|
|
|
25
24
|
## B. Known-field filtering (no search)
|
|
26
25
|
|
|
@@ -68,7 +67,7 @@ sense query "SELECT path, round(_rank*100,2) r FROM frontmatter ORDER BY _rank D
|
|
|
68
67
|
|
|
69
68
|
`sense map` prints the hub list without SQL; use these when you need it filtered or joined.
|
|
70
69
|
|
|
71
|
-
## E. Cold start on an unknown
|
|
70
|
+
## E. Cold start on an unknown notes tree
|
|
72
71
|
|
|
73
72
|
```
|
|
74
73
|
sense map # fields, hubs, recent — read this first
|
|
@@ -76,14 +75,14 @@ sense --list # named queries someone already saved
|
|
|
76
75
|
sense query "SELECT DISTINCT type FROM frontmatter" # what a field's values are
|
|
77
76
|
```
|
|
78
77
|
|
|
79
|
-
##
|
|
78
|
+
## Consequences
|
|
80
79
|
|
|
81
|
-
|
|
|
80
|
+
| query | what happens | bounded alternative |
|
|
82
81
|
|---|---|---|
|
|
83
|
-
| `SELECT text FROM content` |
|
|
84
|
-
| `sense find "pricing"` |
|
|
85
|
-
| `sense find "pricing model details"` | bare words AND-join
|
|
86
|
-
| `sense find "customer-facing OR on-site"` | bare punctuation is FTS5 syntax (`-`
|
|
87
|
-
| `Read` a
|
|
88
|
-
| queries without `LIMIT` | unbounded output
|
|
89
|
-
|
|
|
82
|
+
| `SELECT text FROM content` | returns the tree's entire prose | `snippet(content, -1, '«', '»', '…', 10)` excerpts the match |
|
|
83
|
+
| `sense find "pricing"` | matches only that word's stem | OR-in synonyms and instances: `"pricing OR billing OR invoicing"` |
|
|
84
|
+
| `sense find "pricing model details"` | bare words AND-join; one absent word = zero rows | OR the words, or quote an exact phrase |
|
|
85
|
+
| `sense find "customer-facing OR on-site"` | bare punctuation is FTS5 syntax (`-` reads as a column filter) | double-quote: `"customer-facing" OR "on-site"` |
|
|
86
|
+
| `Read` of a large file for one section | costs the whole file | `peek`, then `Read` the line range |
|
|
87
|
+
| row queries without `LIMIT` | unbounded output (aggregates are already bounded) | `LIMIT n` |
|
|
88
|
+
| saving one-off queries to config | config churn | ad-hoc `sense query`; save reusable views |
|