@ghostpaw/questlog 0.9.2 → 0.10.1
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 +116 -2
- package/SKILL.md +27 -3
- package/dist/{chunk-UTUQPSGO.js → chunk-55JAQORX.js} +66 -588
- package/dist/{chunk-6KTQK3ZE.js → chunk-D2W5MYNO.js} +8 -0
- package/dist/chunk-GVD6A3RR.js +108 -0
- package/dist/{chunk-DKH623HU.js → chunk-IL2QRKZL.js} +1 -4
- package/dist/chunk-N7V7VUI5.js +982 -0
- package/dist/{chunk-3B6FMHZU.js → chunk-ZHTX64KD.js} +24 -0
- package/dist/cli.js +1 -1
- package/dist/{cli_main-XNZP4TY2.js → cli_main-7AIEZV75.js} +80 -118
- package/dist/index.cjs +1135 -627
- package/dist/index.d.cts +142 -11
- package/dist/index.d.ts +142 -11
- package/dist/index.js +1135 -628
- package/dist/mcp-server.js +821 -387
- package/dist/mcp.cjs +691 -321
- package/dist/mcp.js +692 -322
- package/dist/open_questlog_db-LAEH7UDM.js +2 -0
- package/dist/{questlog_skill_spec-EM6DGGVN.js → questlog_skill_spec-HEW2B6EB.js} +5 -3
- package/dist/run_hook_command-C42BQC36.js +95 -0
- package/dist/{serve_questlog_mcp-KFUYJB2P.js → serve_questlog_mcp-W3R63HW4.js} +4 -3
- package/package.json +1 -1
- package/skills/questlog/SKILL.md +27 -3
- package/skills/questlog/references/webhooks.md +91 -0
- package/dist/open_questlog_db-SH3DAU4C.js +0 -2
package/README.md
CHANGED
|
@@ -124,6 +124,8 @@ ghostpaw-questlog skill > SKILL.md
|
|
|
124
124
|
|
|
125
125
|
Each line downloads the latest release asset, checks it against the release’s SHA256SUMS and installs it on the PATH (~/.local/bin on Linux/macOS; the Windows script adds its folder to the user PATH).
|
|
126
126
|
|
|
127
|
+
These lines never edit ~/.profile or other shell startup files: `export PATH` applies to the current shell only. To keep it, add `export PATH="$HOME/.local/bin:$PATH"` to your shell profile yourself.
|
|
128
|
+
|
|
127
129
|
linux-x64:
|
|
128
130
|
|
|
129
131
|
```sh
|
|
@@ -148,17 +150,31 @@ darwin-x64:
|
|
|
148
150
|
curl -fsSL https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.sh | sh -s -- --target darwin-x64 && export PATH="$HOME/.local/bin:$PATH"
|
|
149
151
|
```
|
|
150
152
|
|
|
151
|
-
windows-x64 (PowerShell):
|
|
153
|
+
windows-x64 (PowerShell; persistently adds its folder to the user PATH):
|
|
152
154
|
|
|
153
155
|
```powershell
|
|
154
156
|
irm https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.ps1 | iex
|
|
155
157
|
```
|
|
156
158
|
|
|
159
|
+
Pinned to a release:
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
curl -fsSL https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.sh | sh -s -- --target linux-x64 --version 0.10.1 && export PATH="$HOME/.local/bin:$PATH"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
To skip the persistent Windows user PATH edit (the installer still installs and prints the folder to add):
|
|
166
|
+
|
|
167
|
+
```powershell
|
|
168
|
+
$env:GHOSTPAW_NO_MODIFY_PATH=1; irm https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.ps1 | iex
|
|
169
|
+
```
|
|
170
|
+
|
|
157
171
|
```text
|
|
158
172
|
$ ghostpaw-questlog --version
|
|
159
|
-
questlog 0.
|
|
173
|
+
questlog 0.10.1 (binary, linux-x64)
|
|
160
174
|
```
|
|
161
175
|
|
|
176
|
+
Scripts that compare versions should use `--version --short` or `--version --json`.
|
|
177
|
+
|
|
162
178
|
Standalone binaries are available from [GitHub Releases](https://github.com/GhostPawJS/questlog/releases).
|
|
163
179
|
|
|
164
180
|
A session with the 0.9.1 linux-x64 binary against a fresh database:
|
|
@@ -498,3 +514,101 @@ If this package helps your project, consider sponsoring its maintenance:
|
|
|
498
514
|
---
|
|
499
515
|
|
|
500
516
|
**[Anonyfox](https://anonyfox.com) • [MIT License](LICENSE)**
|
|
517
|
+
|
|
518
|
+
## Webhooks
|
|
519
|
+
|
|
520
|
+
Configure opt-in outbound wakes with the release binary. No server or scheduler is started.
|
|
521
|
+
With no targets, tick makes no network calls. Targets and retry state live in the database.
|
|
522
|
+
|
|
523
|
+
```sh
|
|
524
|
+
questlog hook add https://example.org/wake --min-gap 60
|
|
525
|
+
questlog hook add https://example.org/team --tag work --events quest.due,quest.overdue --secret-stdin
|
|
526
|
+
questlog hook label work
|
|
527
|
+
questlog hook list
|
|
528
|
+
questlog tick --dry-run
|
|
529
|
+
questlog tick
|
|
530
|
+
questlog watch --interval 60
|
|
531
|
+
questlog hook test 1
|
|
532
|
+
questlog review deliveries
|
|
533
|
+
questlog show 12
|
|
534
|
+
questlog hook remove 1
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Save the signing secret printed once by `hook add` (including its `--json` result).
|
|
538
|
+
`--secret-stdin` reads a supplied secret from standard input; there is no secret flag.
|
|
539
|
+
List output redacts URL userinfo and query strings. Removal deletes the target and its deliveries.
|
|
540
|
+
A target covers the database unless `--tag` restricts it to quests with that tag;
|
|
541
|
+
rumors have no tags and reach database targets only. `--events` defaults to all five events.
|
|
542
|
+
The label defaults to the database filename without directory or extension (`questlog` for memory).
|
|
543
|
+
Only use labels suitable for disclosure to the receiver.
|
|
544
|
+
|
|
545
|
+
For cron:
|
|
546
|
+
|
|
547
|
+
```cron
|
|
548
|
+
* * * * * questlog tick
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Cron's PATH may need `$HOME/.local/bin/questlog tick --db /path/to/quests.db`.
|
|
552
|
+
`watch` repeats tick (default 60 seconds, minimum 5), finishing its current tick on SIGINT/SIGTERM.
|
|
553
|
+
Tick exits 0 after running even when deliveries need retrying. Dry runs roll back all changes,
|
|
554
|
+
including repeatable materialization, and make no network calls.
|
|
555
|
+
|
|
556
|
+
Events are detected from the model at tick time:
|
|
557
|
+
|
|
558
|
+
- `quest.due`: an unresolved, undeleted quest reaches its effective due time (own `due_at`, otherwise its undeleted questline's due time).
|
|
559
|
+
- `quest.overdue`: that effective deadline is strictly earlier than now and the quest remains unresolved.
|
|
560
|
+
- `quest.unblocked`: an unresolved quest is available, all active prerequisites have succeeded or been deleted, and at least one prerequisite succeeded after its unlock was installed. Occurrence time is the latest active prerequisite success or not-before time, whichever is later.
|
|
561
|
+
- `repeatable.spawned`: a concrete repeatable instance was created; occurrence time is its creation time. Tick first materializes due anchors through the existing spawn operation.
|
|
562
|
+
- `rumor.captured`: an undeleted rumor was created; occurrence time is its creation time, even if subsequently settled or dismissed.
|
|
563
|
+
|
|
564
|
+
Each type, entity and occurrence timestamp has a persistent unique event key. Repeated ticks
|
|
565
|
+
and restarts do not create another occurrence. Changes removed before any tick cannot be
|
|
566
|
+
reconstructed. Occurrences earlier than target creation are excluded, preventing backlog floods.
|
|
567
|
+
Tags are evaluated when assigning an event. Already assigned events retain their batch membership.
|
|
568
|
+
|
|
569
|
+
One POST batch per target per tick contains only identifiers, types, timestamps, and the DB label:
|
|
570
|
+
|
|
571
|
+
```json
|
|
572
|
+
{"type":"questlog.events","db":"work","deliveryId":"d_…","sentAt":"2026-10-28T10:00:00.000Z","events":[{"id":"e_…","type":"quest.due","questId":12,"occurredAt":"2026-10-28T09:59:00.000Z"}]}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Headers are `content-type: application/json`, `user-agent: questlog/<version>`,
|
|
576
|
+
`x-questlog-delivery: <deliveryId>`, `x-questlog-timestamp: <unix seconds>`, and
|
|
577
|
+
`x-questlog-signature: sha256=<hex HMAC-SHA256(secret, timestamp + "." + rawBody)>`.
|
|
578
|
+
No titles, objectives, details, or tag text are sent. `hook test` sends a logged `hook.test`
|
|
579
|
+
event immediately, ignoring the min gap. Add and test are CLI-only in the tool facade;
|
|
580
|
+
`manage_hooks` supports list, remove, tick (with `dry_run`), and deliveries.
|
|
581
|
+
|
|
582
|
+
2xx delivers the batch. Requests time out after 5 seconds. Other responses, timeouts, and
|
|
583
|
+
network errors retry after 30 seconds, 1 minute, 2 minutes, 4 minutes, and so on, capped
|
|
584
|
+
at 1 hour, plus less than 1 second jitter. The target's min gap also applies to retries.
|
|
585
|
+
Eight unsuccessful attempts mark a delivery failed. Retries retain the delivery id and events.
|
|
586
|
+
Pending batches wait behind retries. Only the last 500 delivered entries per target are kept;
|
|
587
|
+
pending and failed entries are retained. Transactions and two-minute leases prevent overlapping
|
|
588
|
+
ticks from claiming the same delivery. A crash after receipt but before recording success can
|
|
589
|
+
cause another request: receivers must dedupe by delivery id.
|
|
590
|
+
|
|
591
|
+
### Verifying a delivery
|
|
592
|
+
|
|
593
|
+
Compute HMAC-SHA256 over `timestamp + "." + rawBody` with the secret and compare in constant
|
|
594
|
+
time. Reject timestamps older than 5 minutes (and timestamps too far in the future), then
|
|
595
|
+
dedupe on `x-questlog-delivery`. Use durable deduplication storage in a production receiver.
|
|
596
|
+
This 15-line Node example uses an in-memory set:
|
|
597
|
+
|
|
598
|
+
```js
|
|
599
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
600
|
+
import { createServer } from 'node:http';
|
|
601
|
+
const secret = process.env.WEBHOOK_SECRET, seen = new Set();
|
|
602
|
+
createServer(async (req, res) => {
|
|
603
|
+
const chunks = []; for await (const chunk of req) chunks.push(chunk);
|
|
604
|
+
const rawBody = Buffer.concat(chunks), h = req.headers;
|
|
605
|
+
const timestamp = h['x-questlog-timestamp'], id = h['x-questlog-delivery'];
|
|
606
|
+
const age = Date.now() / 1000 - Number(timestamp);
|
|
607
|
+
const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
|
|
608
|
+
const signature = String(h['x-questlog-signature'] || '');
|
|
609
|
+
const actual = Buffer.from(signature.slice(7), 'hex');
|
|
610
|
+
if (!id || !/^\d+$/.test(timestamp) || age > 300 || age < -300 || !/^sha256=[a-f0-9]{64}$/.test(signature) || actual.length !== expected.length || !timingSafeEqual(actual, expected)) { res.writeHead(401).end(); return; }
|
|
611
|
+
if (!seen.has(id)) { seen.add(id); console.log(JSON.parse(rawBody)); }
|
|
612
|
+
res.writeHead(204).end();
|
|
613
|
+
}).listen(8080, '127.0.0.1');
|
|
614
|
+
```
|
package/SKILL.md
CHANGED
|
@@ -29,7 +29,7 @@ Run tools as `ghostpaw-questlog ...`; use `~/.local/bin/ghostpaw-questlog` if it
|
|
|
29
29
|
|
|
30
30
|
- `questlog search <words>` before `add` to avoid duplicates.
|
|
31
31
|
- `ghostpaw-questlog add "..." --tag a,b --due tomorrow`
|
|
32
|
-
- `questlog list [--view <view>]`: questlines, quests.active, quests.available, quests.blocked, quests.deferred, quests.due_soon, quests.in_progress, quests.missed_scheduled, quests.open, quests.overdue, quests.resolved, quests.scheduled_for_day, quests.scheduled_now, repeatables.due_anchors, rumors.
|
|
32
|
+
- `questlog list [--view <view>]`: deliveries, questlines, quests.active, quests.available, quests.blocked, quests.deferred, quests.due_soon, quests.in_progress, quests.missed_scheduled, quests.open, quests.overdue, quests.resolved, quests.scheduled_for_day, quests.scheduled_now, repeatables.due_anchors, rumors.
|
|
33
33
|
- `questlog done <id> --outcome "..."`
|
|
34
34
|
- `questlog search <words>`
|
|
35
35
|
- `questlog show <id>`
|
|
@@ -37,6 +37,7 @@ Run tools as `ghostpaw-questlog ...`; use `~/.local/bin/ghostpaw-questlog` if it
|
|
|
37
37
|
- Exit codes: 0 ok / 1 error / 2 usage / 3 needs input.
|
|
38
38
|
- Database: `~/.ghostpaw/questlog.db`; override with `--db` or `GHOSTPAW_QUESTLOG_DB`.
|
|
39
39
|
- Use one database per agent or project.
|
|
40
|
+
- Webhooks: `questlog hook add <url>`, `questlog tick --dry-run`, `questlog watch`. Read `questlog skill webhooks` for events, signing, verification, and cron setup.
|
|
40
41
|
|
|
41
42
|
## Appendix: MCP and tool calls
|
|
42
43
|
|
|
@@ -50,6 +51,28 @@ CLI: `ghostpaw-questlog call <tool> '<JSON object>'` or `ghostpaw-questlog <tool
|
|
|
50
51
|
|
|
51
52
|
Inspect schemas with `ghostpaw-questlog describe <tool>`. Use `--db <path>` to select a database.
|
|
52
53
|
|
|
54
|
+
### manage_hooks
|
|
55
|
+
|
|
56
|
+
List or remove outbound webhook targets, run a tick, or inspect pending and failed deliveries.
|
|
57
|
+
|
|
58
|
+
Use when: Use to operate configured outbound webhooks. Add and test targets with the CLI.
|
|
59
|
+
|
|
60
|
+
Not for: Use quest tools to change work itself.
|
|
61
|
+
|
|
62
|
+
Writes: writes_state.
|
|
63
|
+
|
|
64
|
+
| Parameter | Type | Required | Values / description |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| action | string | yes | list, remove, tick, deliveries. Operation. |
|
|
67
|
+
| id | integer | no | Target id. |
|
|
68
|
+
| dry_run | boolean | no | Preview only. |
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
ghostpaw-questlog call manage_hooks '{"action":"list"}'
|
|
72
|
+
ghostpaw-questlog call manage_hooks '{"action":"remove","id":1}'
|
|
73
|
+
ghostpaw-questlog call manage_hooks '{"action":"tick"}'
|
|
74
|
+
```
|
|
75
|
+
|
|
53
76
|
### search_questlog
|
|
54
77
|
|
|
55
78
|
Search quests and rumors by text when you need to find an existing item before inspecting or changing it.
|
|
@@ -83,7 +106,7 @@ Read-only.
|
|
|
83
106
|
|
|
84
107
|
| Parameter | Type | Required | Values / description |
|
|
85
108
|
| --- | --- | --- | --- |
|
|
86
|
-
| view | string | yes | questlines, quests.active, quests.available, quests.blocked, quests.deferred, quests.due_soon, quests.in_progress, quests.missed_scheduled, quests.open, quests.overdue, quests.resolved, quests.scheduled_for_day, quests.scheduled_now, repeatables.due_anchors, rumors. Which operational review surface to return. |
|
|
109
|
+
| view | string | yes | deliveries, questlines, quests.active, quests.available, quests.blocked, quests.deferred, quests.due_soon, quests.in_progress, quests.missed_scheduled, quests.open, quests.overdue, quests.resolved, quests.scheduled_for_day, quests.scheduled_now, repeatables.due_anchors, rumors. Which operational review surface to return. |
|
|
87
110
|
| filters | object | no | Optional filters for supported review surfaces. |
|
|
88
111
|
| filters.questlineId | integer | no | Optional questline id used by quest views. |
|
|
89
112
|
| filters.tagNames | array | no | Optional tag names used by quest views. |
|
|
@@ -92,7 +115,7 @@ Read-only.
|
|
|
92
115
|
| now | integer | no | Optional evaluation timestamp for time-sensitive views. |
|
|
93
116
|
|
|
94
117
|
```sh
|
|
95
|
-
ghostpaw-questlog call review_questlog '{"view":"
|
|
118
|
+
ghostpaw-questlog call review_questlog '{"view":"deliveries"}'
|
|
96
119
|
```
|
|
97
120
|
|
|
98
121
|
### inspect_questlog_item
|
|
@@ -376,6 +399,7 @@ ghostpaw-questlog call retire_work '{"action":"hide","target":{"kind":"quest","i
|
|
|
376
399
|
|
|
377
400
|
### Workflow guides
|
|
378
401
|
|
|
402
|
+
- `ghostpaw-questlog skill webhooks` ([webhooks](skills/questlog/references/webhooks.md)): Configure signed outbound event webhooks and verify deliveries.
|
|
379
403
|
- `ghostpaw-questlog skill archive-delete-and-prune` ([archive-delete-and-prune](skills/questlog/references/archive-delete-and-prune.md)): Choose the right retirement action for each kind of work so history stays honest and hiding does not get confused with archival or terminal execution truth.
|
|
380
404
|
- `ghostpaw-questlog skill choose-work-shape` ([choose-work-shape](skills/questlog/references/choose-work-shape.md)): Choose the right structure for new work by separating uncertainty, one-shot execution, multi-step arcs, and recurring patterns.
|
|
381
405
|
- `ghostpaw-questlog skill clarify-ambiguous-requests` ([clarify-ambiguous-requests](skills/questlog/references/clarify-ambiguous-requests.md)): Treat ambiguity as a real state, capture uncertainty honestly, and only commit work structure once the next executable shape is clear.
|