quilltap 4.10.0-dev.175 → 4.10.0-dev.183
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
CHANGED
|
@@ -234,7 +234,8 @@ quilltap docs list # All mounts
|
|
|
234
234
|
quilltap docs show <mount> # One mount, with counts
|
|
235
235
|
quilltap docs files <mount> [--folder <path>] # Flat file list for a mount
|
|
236
236
|
quilltap docs ls <mount> [path] [--links] # POSIX-flavoured listing (alias: dir)
|
|
237
|
-
quilltap docs
|
|
237
|
+
quilltap docs ls <mount> [path] -R --sort time -r # Recursive, grouped by folder, sorted by time and reversed
|
|
238
|
+
quilltap docs tree <mount> [path] # ASCII tree of a folder hierarchy (--depth, --max-nodes, --long)
|
|
238
239
|
quilltap docs read [--rendered] <mount> <path> # File contents → stdout
|
|
239
240
|
quilltap docs export <mount> <outputDir> # Mount → directory
|
|
240
241
|
quilltap docs find <pattern> # Substring match on file names (--mount, --ext, --type, --limit)
|
|
@@ -258,6 +259,8 @@ quilltap docs rmdir <mount> <path> # Delete an empty
|
|
|
258
259
|
quilltap docs mvdir <mount> <fromPath> <toPath> # Rename/move a folder (server-required)
|
|
259
260
|
```
|
|
260
261
|
|
|
262
|
+
`ls` flags: `--recursive` / `-R` lists every file below the path, grouped by folder; `--sort name|time|size|links` (default `name`) with `--reverse` / `-r` to flip it; `--links` lists the other mount/path entries under each file that has more than one hard link. `tree` takes `--depth N` (default 20), `--max-nodes N` (default 1000) and `--long`, which is accepted but reserved — it does not yet add columns.
|
|
263
|
+
|
|
261
264
|
Mount arguments accept the mount name (case-insensitive) or a UUID; ambiguous names print candidates and exit non-zero. `--json` is supported by every verb; `reindex`, `embed`, `link`, `rmdir`, and `mvdir` refuse to run without a reachable server. `grep --semantic` goes through `POST /api/v1/mount-points?action=semantic-search`, because the embedding provider lives in the server; it defaults to `--top 20`, `--threshold 0.5`, `--port 3000`.
|
|
262
265
|
|
|
263
266
|
### Addressing documents with `qtap://` URIs
|
|
@@ -337,6 +340,7 @@ quilltap memories ls # All hol
|
|
|
337
340
|
quilltap memories ls --character Ariadne --sort created --limit 10 # One holder, newest first
|
|
338
341
|
quilltap memories find "concrete examples" # Substring match on summary (--in content|both)
|
|
339
342
|
quilltap memories grep -i --max 3 --context 1 "concrete examples" # Pattern search inside content, with snippets
|
|
343
|
+
quilltap memories grep -l "concrete examples" # Matching memory IDs only, one per line (--paths-only)
|
|
340
344
|
quilltap memories show <id|prefix> [--depth N] [--no-related] # Full record + related-memory neighbourhood
|
|
341
345
|
quilltap memories tree <id|prefix> [--depth N] [--max-nodes N] # ASCII walk of the bidirectional related-memory graph
|
|
342
346
|
quilltap memories status [--character <name|id>] [--port <n>] # Per-holder rollup, maintenance ledger + dangling-edge check
|
|
@@ -348,7 +352,7 @@ quilltap memories maintain --character Ariadne --phases consolidate # Queue a
|
|
|
348
352
|
quilltap memories maintain --character all [--phases demote,retire] # Queue maintenance for every character
|
|
349
353
|
```
|
|
350
354
|
|
|
351
|
-
Shared filter flags apply to `ls`, `find`, `grep`, and `status` where they make sense: `--character`, `--about` (with `self` / `none` shortcuts), `--source` (AUTO / MANUAL / CONSOLIDATED), `--tier` (hot / cold; both by default, cold rows are starred in the `src` column), `--chat` (with `none` for manual entries), `--project`, `--since`, `--until`, `--min-importance`, `--min-reinforced`, `--has-embedding` / `--no-embedding`. Sort flags (`--sort reinforced|importance|created|accessed|reinforcement-count|links`, plus `-r` to
|
|
355
|
+
Shared filter flags apply to `ls`, `find`, `grep`, and `status` where they make sense: `--character`, `--about` (with `self` / `none` shortcuts), `--source` (AUTO / MANUAL / CONSOLIDATED), `--tier` (hot / cold; both by default, cold rows are starred in the `src` column), `--chat` (with `none` for manual entries), `--project`, `--since`, `--until`, `--min-importance`, `--min-reinforced`, `--has-embedding` / `--no-embedding`. Sort flags (`--sort reinforced|importance|created|accessed|reinforcement-count|links`, plus `-r` / `--reverse` to flip it, `--limit N` (default 50) and `--full-titles` to stop chat titles being truncated to 32 characters) apply to `ls`, `find`, and `grep`. `grep -l` / `--paths-only` prints only the IDs of matching memories, one per line. Names accept fuzzy substrings; ambiguous names print candidates and exit 2. `--json` is supported by every verb. `validate` is `status`'s terse twin — read-only; it counts dangling `relatedMemoryIds` edges, dangling `consolidatedFrom` members (digests naming notes that are gone), dangling `supersededById` pointers, and rows with no embedding. It exits 1 if any dangling link remains (a missing embedding only warns), and `--list` prints the offending IDs. `grep --semantic` defaults to `--top 20`, `--threshold 0.5`, and scopes to **one holder at a time**: `--character all` is rejected. The legacy `quilltap db memories --character <name>` verb remains, now with `--tier hot|cold` (rows with no tier count as hot).
|
|
352
356
|
|
|
353
357
|
Verbs that call the server (`grep --semantic`, `status`'s ledger, `maintain`, `validate --repair`) take `--port`; without it they use the port recorded in the `--instance` / `--data-dir` instance's lock, else 3000.
|
|
354
358
|
|
|
@@ -480,7 +484,13 @@ quilltap themes create sunset # Scaffold a new theme
|
|
|
480
484
|
quilltap themes search "dark" # Search registries
|
|
481
485
|
quilltap themes update # Check for theme updates
|
|
482
486
|
quilltap themes registry list # List configured registries
|
|
483
|
-
quilltap themes registry add <url> # Add a registry source
|
|
487
|
+
quilltap themes registry add <url> # Add a registry source (--key <pubkey>, --name <name>)
|
|
488
|
+
quilltap themes registry remove <name> # Remove a registry source
|
|
489
|
+
quilltap themes registry refresh # Refresh all registry indexes
|
|
490
|
+
|
|
491
|
+
# For registry operators
|
|
492
|
+
quilltap themes registry keygen [--output <dir>] # Generate an Ed25519 keypair
|
|
493
|
+
quilltap themes registry sign <dir> --key <private> # Sign a registry directory
|
|
484
494
|
```
|
|
485
495
|
|
|
486
496
|
## Shell Completion
|
|
@@ -559,7 +569,7 @@ Fish picks new completion files up automatically — no shell restart needed.
|
|
|
559
569
|
|
|
560
570
|
Completions **parse the line rather than counting words**, so a flag typed anywhere the CLI itself accepts one does not derail them: `quilltap docs --instance Friday <TAB>` still offers the `docs` verbs. bash and zsh also reuse the `-i` / `-d` / `--passphrase` already on the line when looking store names up, so the names offered come from the instance you are addressing rather than the default one. fish completes `--mount` but not the positionals, and always reads the default instance.
|
|
561
571
|
|
|
562
|
-
Dynamic completions shell out to `quilltap`'s own subcommands. If the active instance is encrypted and no passphrase is reachable, the completion silently returns nothing rather than prompting in the middle of a tab.
|
|
572
|
+
Dynamic completions shell out to `quilltap`'s own subcommands — `quilltap instances list --names-only` and `quilltap docs list --names-only`, which print one name per line and are handy in scripts too. If the active instance is encrypted and no passphrase is reachable, the completion silently returns nothing rather than prompting in the middle of a tab.
|
|
563
573
|
|
|
564
574
|
## Requirements
|
|
565
575
|
|
package/bin/quilltap.js
CHANGED
|
@@ -103,7 +103,7 @@ Subcommands:
|
|
|
103
103
|
file-verify Force-download cloud-evicted data files (iCloud, etc.)
|
|
104
104
|
memory-diff <chatId> Dump existing memories and dry-run re-extraction for a chat
|
|
105
105
|
recall-replay <chatId> Replay a turn's memory recall, old vs episodic ranking
|
|
106
|
-
anchor-probe <characterId> Probe whether episodic anchor lines suppress
|
|
106
|
+
anchor-probe <characterId> Probe whether episodic anchor lines suppress reinforcement at admission
|
|
107
107
|
completion <shell> Generate a shell completion script (bash / zsh / fish)
|
|
108
108
|
|
|
109
109
|
Options:
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quilltap migrations status` compares the ledger against the ids it reads
|
|
3
|
+
* out of `migrations/scripts/*.ts`. Most migrations declare their id through a
|
|
4
|
+
* `MIGRATION_ID` constant rather than a string literal; when the reader only
|
|
5
|
+
* understood literals, every one of those vanished from "source" and showed up
|
|
6
|
+
* as "retired" on any instance that had run it.
|
|
7
|
+
*
|
|
8
|
+
* @jest-environment node
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
const { extractMigrationId } = require('../migrations-commands');
|
|
17
|
+
|
|
18
|
+
describe('extractMigrationId', () => {
|
|
19
|
+
it('reads a string-literal id', () => {
|
|
20
|
+
expect(extractMigrationId(`export const m = {\n id: 'foo-v1',\n};`)).toBe('foo-v1');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('resolves an id declared through MIGRATION_ID', () => {
|
|
24
|
+
const src = `const MIGRATION_ID = 'bar-v1';\nexport const m = {\n id: MIGRATION_ID,\n};`;
|
|
25
|
+
expect(extractMigrationId(src)).toBe('bar-v1');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('accepts a typed MIGRATION_ID constant', () => {
|
|
29
|
+
const src = `const MIGRATION_ID: string = 'baz-v1'\nexport const m = {\n id: MIGRATION_ID,\n};`;
|
|
30
|
+
expect(extractMigrationId(src)).toBe('baz-v1');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('returns null when no id is declared', () => {
|
|
34
|
+
expect(extractMigrationId('export const nothing = 1;')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('every migration script yields an id', () => {
|
|
39
|
+
const scriptsDir = path.join(__dirname, '..', '..', '..', '..', 'migrations', 'scripts');
|
|
40
|
+
const files = fs.existsSync(scriptsDir)
|
|
41
|
+
? fs.readdirSync(scriptsDir).filter((f) => f.endsWith('.ts') && f !== 'index.ts')
|
|
42
|
+
: [];
|
|
43
|
+
|
|
44
|
+
it('finds the migration scripts', () => {
|
|
45
|
+
expect(files.length).toBeGreaterThan(100);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('extracts an id from each one', () => {
|
|
49
|
+
const missing = files.filter(
|
|
50
|
+
(f) => !extractMigrationId(fs.readFileSync(path.join(scriptsDir, f), 'utf8'))
|
|
51
|
+
);
|
|
52
|
+
expect(missing).toEqual([]);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -61,7 +61,7 @@ complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'instances' -d 'Registe
|
|
|
61
61
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'memories' -d 'Search and browse memories'
|
|
62
62
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'memory-diff' -d 'Memory extraction dry-run'
|
|
63
63
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'recall-replay' -d 'Replay memory recall for a turn'
|
|
64
|
-
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'anchor-probe' -d 'Probe anchor-line effect on
|
|
64
|
+
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'anchor-probe' -d 'Probe anchor-line effect on admission'
|
|
65
65
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'logs' -d 'Tail or print log files'
|
|
66
66
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'migrations' -d 'Inspect migration status'
|
|
67
67
|
complete -c quilltap -n '__quilltap_no_subcommand' -f -a 'maintenance' -d 'Run retention/cleanup sweeps'
|
|
@@ -43,7 +43,7 @@ _quilltap() {
|
|
|
43
43
|
'memories:Search, browse, and graph memories'
|
|
44
44
|
'memory-diff:Dump existing memories and dry-run re-extraction'
|
|
45
45
|
'recall-replay:Replay a turn'\''s memory recall, old vs episodic ranking'
|
|
46
|
-
'anchor-probe:Probe whether episodic anchor lines suppress
|
|
46
|
+
'anchor-probe:Probe whether episodic anchor lines suppress reinforcement at admission'
|
|
47
47
|
'logs:Tail or print an instance log file'
|
|
48
48
|
'migrations:Inspect migration status'
|
|
49
49
|
'maintenance:Run retention/cleanup sweeps'
|
|
@@ -43,6 +43,19 @@ function parseFlags(args) {
|
|
|
43
43
|
|
|
44
44
|
// ---------- migration list parsing ----------
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* A migration's id is either a string literal on the object (`id: 'foo-v1'`)
|
|
48
|
+
* or a module constant (`id: MIGRATION_ID` beside `const MIGRATION_ID = 'foo-v1'`).
|
|
49
|
+
* Missing the constant form drops those migrations from "source", which then
|
|
50
|
+
* report as retired on every instance that ran them.
|
|
51
|
+
*/
|
|
52
|
+
function extractMigrationId(fileContent) {
|
|
53
|
+
const constMatch = fileContent.match(/^\s*const\s+MIGRATION_ID\s*(?::\s*\w+\s*)?=\s*['"]([^'"]+)['"]/m);
|
|
54
|
+
if (constMatch && /^\s*id:\s*MIGRATION_ID\b/m.test(fileContent)) return constMatch[1];
|
|
55
|
+
const literalMatch = fileContent.match(/^\s*id:\s*['"]([^'"]+)['"]/m);
|
|
56
|
+
return literalMatch ? literalMatch[1] : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
// Reads the registered migration list from migrations/scripts/index.ts and resolves each
|
|
47
60
|
// entry's real `id:` value by reading the imported source file. Heuristic camelCase→kebab
|
|
48
61
|
// conversion is unreliable (some migrations omit `-v1`, others use `-v2`), so we always
|
|
@@ -95,11 +108,11 @@ function extractMigrationsFromSource() {
|
|
|
95
108
|
const filePath = path.join(scriptsDir, info.filePath + '.ts');
|
|
96
109
|
if (!fs.existsSync(filePath)) continue;
|
|
97
110
|
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
98
|
-
const
|
|
99
|
-
if (!
|
|
111
|
+
const id = extractMigrationId(fileContent);
|
|
112
|
+
if (!id) continue;
|
|
100
113
|
migrations.push({
|
|
101
|
-
id
|
|
102
|
-
description: info.comment ||
|
|
114
|
+
id,
|
|
115
|
+
description: info.comment || id,
|
|
103
116
|
});
|
|
104
117
|
}
|
|
105
118
|
|
|
@@ -321,4 +334,5 @@ async function migrationsCommand(args) {
|
|
|
321
334
|
|
|
322
335
|
module.exports = {
|
|
323
336
|
migrationsCommand,
|
|
337
|
+
extractMigrationId,
|
|
324
338
|
};
|
package/package.json
CHANGED