@ghostpaw/questlog 0.9.1 → 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 +180 -18
- package/SKILL.md +161 -32
- package/dist/{chunk-3Y5F3SMB.js → chunk-55JAQORX.js} +245 -665
- package/dist/{questlog_skill_spec-LOQ2FNOF.js → chunk-D2W5MYNO.js} +9 -54
- package/dist/chunk-GVD6A3RR.js +108 -0
- package/dist/chunk-IL2QRKZL.js +14 -0
- package/dist/chunk-N7V7VUI5.js +982 -0
- package/dist/chunk-QYSIJ2YN.js +47 -0
- package/dist/{chunk-3B6FMHZU.js → chunk-ZHTX64KD.js} +24 -0
- package/dist/cli.js +1 -1
- package/dist/{cli_main-ELAKW6KW.js → cli_main-7AIEZV75.js} +136 -120
- package/dist/index.cjs +2046 -1393
- package/dist/index.d.cts +142 -11
- package/dist/index.d.ts +142 -11
- package/dist/index.js +2046 -1394
- package/dist/mcp-server.js +959 -386
- package/dist/mcp.cjs +810 -328
- package/dist/mcp.js +811 -329
- package/dist/open_questlog_db-LAEH7UDM.js +2 -0
- package/dist/questlog_skill_spec-HEW2B6EB.js +76 -0
- package/dist/run_hook_command-C42BQC36.js +95 -0
- package/dist/{serve_questlog_mcp-QSHMNNFT.js → serve_questlog_mcp-W3R63HW4.js} +14 -4
- package/dist/{skill_markdown-7HCMSJYR.js → skill_markdown-HXYQ3K6U.js} +34 -6
- package/package.json +6 -3
- package/skills/questlog/SKILL.md +161 -32
- package/skills/questlog/references/webhooks.md +91 -0
- package/dist/chunk-KRQDV4KF.js +0 -58
- package/dist/open_questlog_db-SH3DAU4C.js +0 -2
package/skills/questlog/SKILL.md
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: questlog
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use the release binary ghostpaw-questlog to manage local tasks, calendar commitments, and recurring work. Use when planning, executing, reviewing, or organizing work."
|
|
4
4
|
license: "MIT"
|
|
5
|
-
compatibility: "
|
|
5
|
+
compatibility: "Release binary ghostpaw-questlog (no runtime needed); MCP stdio via ghostpaw-questlog mcp."
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# questlog
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Linux/macOS:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
curl -fsSL https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.sh | sh
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Installs `~/.local/bin/ghostpaw-questlog` after checking SHA256SUMS.
|
|
19
|
+
|
|
20
|
+
Windows x64 (PowerShell):
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
irm https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.ps1 | iex
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Run tools as `ghostpaw-questlog ...`; use `~/.local/bin/ghostpaw-questlog` if it is not on PATH.
|
|
27
|
+
|
|
11
28
|
`questlog` and `ghostpaw-questlog` are the same binary.
|
|
12
29
|
|
|
13
30
|
- `questlog search <words>` before `add` to avoid duplicates.
|
|
14
|
-
- `questlog add
|
|
15
|
-
- `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.
|
|
31
|
+
- `ghostpaw-questlog add "..." --tag a,b --due tomorrow`
|
|
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.
|
|
16
33
|
- `questlog done <id> --outcome "..."`
|
|
17
34
|
- `questlog search <words>`
|
|
18
35
|
- `questlog show <id>`
|
|
@@ -20,6 +37,7 @@ No install? Use `npx -y @ghostpaw/questlog <command>`.
|
|
|
20
37
|
- Exit codes: 0 ok / 1 error / 2 usage / 3 needs input.
|
|
21
38
|
- Database: `~/.ghostpaw/questlog.db`; override with `--db` or `GHOSTPAW_QUESTLOG_DB`.
|
|
22
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.
|
|
23
41
|
|
|
24
42
|
## Appendix: MCP and tool calls
|
|
25
43
|
|
|
@@ -29,10 +47,32 @@ Questlog manages local tasks, calendar commitments, and recurring work. Search b
|
|
|
29
47
|
|
|
30
48
|
MCP: connect to ghostpaw-questlog, then call a tool by name with its JSON arguments.
|
|
31
49
|
|
|
32
|
-
CLI: `ghostpaw-questlog call <tool> '<JSON object>'` or `ghostpaw-questlog <tool> --parameter value
|
|
50
|
+
CLI: `ghostpaw-questlog call <tool> '<JSON object>'` or `ghostpaw-questlog <tool> --parameter value`.
|
|
33
51
|
|
|
34
52
|
Inspect schemas with `ghostpaw-questlog describe <tool>`. Use `--db <path>` to select a database.
|
|
35
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
|
+
|
|
36
76
|
### search_questlog
|
|
37
77
|
|
|
38
78
|
Search quests and rumors by text when you need to find an existing item before inspecting or changing it.
|
|
@@ -50,6 +90,10 @@ Read-only.
|
|
|
50
90
|
| kinds | array | no | Optional entity kinds to search. |
|
|
51
91
|
| mode | string | no | browse, identify_one. Whether to browse results normally or ask for clarification when several matches are found. |
|
|
52
92
|
|
|
93
|
+
```sh
|
|
94
|
+
ghostpaw-questlog call search_questlog '{"query":"release"}'
|
|
95
|
+
```
|
|
96
|
+
|
|
53
97
|
### review_questlog
|
|
54
98
|
|
|
55
99
|
Review one operational questlog surface such as available quests, open rumors, blocked work, or due repeatable anchors.
|
|
@@ -62,10 +106,18 @@ Read-only.
|
|
|
62
106
|
|
|
63
107
|
| Parameter | Type | Required | Values / description |
|
|
64
108
|
| --- | --- | --- | --- |
|
|
65
|
-
| 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. |
|
|
66
110
|
| filters | object | no | Optional filters for supported review surfaces. |
|
|
111
|
+
| filters.questlineId | integer | no | Optional questline id used by quest views. |
|
|
112
|
+
| filters.tagNames | array | no | Optional tag names used by quest views. |
|
|
113
|
+
| filters.includeDeleted | boolean | no | Whether deleted quests should be included in quest views. |
|
|
114
|
+
| filters.dayAt | integer | no | UTC timestamp within the day to review for scheduled-for-day. |
|
|
67
115
|
| now | integer | no | Optional evaluation timestamp for time-sensitive views. |
|
|
68
116
|
|
|
117
|
+
```sh
|
|
118
|
+
ghostpaw-questlog call review_questlog '{"view":"deliveries"}'
|
|
119
|
+
```
|
|
120
|
+
|
|
69
121
|
### inspect_questlog_item
|
|
70
122
|
|
|
71
123
|
Inspect one specific questlog item in depth and return its richer structured detail and important related refs.
|
|
@@ -79,9 +131,15 @@ Read-only.
|
|
|
79
131
|
| Parameter | Type | Required | Values / description |
|
|
80
132
|
| --- | --- | --- | --- |
|
|
81
133
|
| target | object | yes | The specific item to inspect. |
|
|
134
|
+
| target.kind | string | yes | quest, questline, repeatable_quest, rumor. The kind of item to inspect. |
|
|
135
|
+
| target.id | integer | yes | The numeric id of the item to inspect. |
|
|
82
136
|
| detailLevel | string | no | compact, full. How much detail to return. |
|
|
83
137
|
| now | integer | no | Optional evaluation timestamp for time-sensitive detail. |
|
|
84
138
|
|
|
139
|
+
```sh
|
|
140
|
+
ghostpaw-questlog call inspect_questlog_item '{"target":{"kind":"quest","id":1}}'
|
|
141
|
+
```
|
|
142
|
+
|
|
85
143
|
### capture_rumor
|
|
86
144
|
|
|
87
145
|
Capture uncertain incoming work as a rumor so it can be triaged later without prematurely turning it into committed execution.
|
|
@@ -98,6 +156,10 @@ Writes: writes_state.
|
|
|
98
156
|
| details | string | no | Optional supporting context that explains why the rumor might matter. |
|
|
99
157
|
| now | integer | no | Optional creation timestamp for the rumor. |
|
|
100
158
|
|
|
159
|
+
```sh
|
|
160
|
+
ghostpaw-questlog call capture_rumor '{"title":"Review release notes"}'
|
|
161
|
+
```
|
|
162
|
+
|
|
101
163
|
### shape_work
|
|
102
164
|
|
|
103
165
|
Create a quest (with timing, tags, and objective in one call), create a questline, settle a rumor into concrete work, or manage quest-questline membership. Use create_quest for clear commitments — include tags and timing directly to avoid follow-up calls.
|
|
@@ -114,7 +176,11 @@ Writes: writes_state.
|
|
|
114
176
|
| questId | integer | no | Quest to attach or detach. |
|
|
115
177
|
| questlineId | integer | no | Questline that should receive the quest. |
|
|
116
178
|
| quest | object | no | |
|
|
179
|
+
| quest.title | string | yes | Title for the new quest. |
|
|
180
|
+
| quest.objective | string | yes | Objective for the new quest. |
|
|
117
181
|
| questline | object | no | |
|
|
182
|
+
| questline.title | string | yes | Questline title. |
|
|
183
|
+
| questline.description | string | no | Optional questline description. |
|
|
118
184
|
| rumorId | integer | no | Rumor to settle, dismiss, or reopen. |
|
|
119
185
|
| dismissedAt | integer | no | Optional dismissal timestamp. |
|
|
120
186
|
| settledAt | integer | no | Optional settlement timestamp. |
|
|
@@ -123,6 +189,12 @@ Writes: writes_state.
|
|
|
123
189
|
| title | string | no | New title for the update_rumor action. |
|
|
124
190
|
| details | string | no | New or enriched context text for the update_rumor action. |
|
|
125
191
|
|
|
192
|
+
```sh
|
|
193
|
+
ghostpaw-questlog call shape_work '{"action":"attach_quest_to_questline","questId":1,"questlineId":1}'
|
|
194
|
+
ghostpaw-questlog call shape_work '{"action":"create_quest","quest":{"title":"Review release notes","objective":"Check changes against the release"}}'
|
|
195
|
+
ghostpaw-questlog call shape_work '{"action":"create_questline","questline":{"title":"Review release notes"}}'
|
|
196
|
+
```
|
|
197
|
+
|
|
126
198
|
### plan_quest
|
|
127
199
|
|
|
128
200
|
Refine a quest by revising its objective before actual start or by changing its temporal planning fields.
|
|
@@ -146,6 +218,11 @@ Writes: writes_state.
|
|
|
146
218
|
| estimateSeconds | integer | no | Optional active-effort estimate in seconds. |
|
|
147
219
|
| now | integer | no | Optional update timestamp. |
|
|
148
220
|
|
|
221
|
+
```sh
|
|
222
|
+
ghostpaw-questlog call plan_quest '{"action":"revise_objective","questId":1,"objective":"Check changes against the release"}'
|
|
223
|
+
ghostpaw-questlog call plan_quest '{"action":"set_time","questId":1}'
|
|
224
|
+
```
|
|
225
|
+
|
|
149
226
|
### run_quest
|
|
150
227
|
|
|
151
228
|
Run quest lifecycle actions such as starting, logging effort, finishing, abandoning, or abandoning and spawning follow-up quests atomically.
|
|
@@ -168,6 +245,12 @@ Writes: writes_state.
|
|
|
168
245
|
| resolvedAt | integer | no | Optional resolved timestamp for finish or abandon actions. |
|
|
169
246
|
| followups | array | no | Follow-up quests to create atomically. Required for abandon_and_spawn_followups. |
|
|
170
247
|
|
|
248
|
+
```sh
|
|
249
|
+
ghostpaw-questlog call run_quest '{"action":"start","questId":1}'
|
|
250
|
+
ghostpaw-questlog call run_quest '{"action":"log_effort","questId":1,"effortSeconds":1}'
|
|
251
|
+
ghostpaw-questlog call run_quest '{"action":"finish","questId":1,"outcome":"release"}'
|
|
252
|
+
```
|
|
253
|
+
|
|
171
254
|
### organize_work
|
|
172
255
|
|
|
173
256
|
Organize grouping and dependency structure by updating questlines or changing hard unlock prerequisites between concrete quests.
|
|
@@ -192,6 +275,12 @@ Writes: writes_state.
|
|
|
192
275
|
| fromQuestIds | array | no | Full prerequisite quest id set. |
|
|
193
276
|
| now | integer | no | Optional timestamp. |
|
|
194
277
|
|
|
278
|
+
```sh
|
|
279
|
+
ghostpaw-questlog call organize_work '{"action":"add_unlock","fromQuestId":1,"toQuestId":2}'
|
|
280
|
+
ghostpaw-questlog call organize_work '{"action":"archive_questline","questlineId":1}'
|
|
281
|
+
ghostpaw-questlog call organize_work '{"action":"remove_unlock","fromQuestId":1,"toQuestId":2}'
|
|
282
|
+
```
|
|
283
|
+
|
|
195
284
|
### manage_repeatable
|
|
196
285
|
|
|
197
286
|
Manage recurring work definitions by creating, updating, previewing, spawning, or archiving repeatable quests.
|
|
@@ -207,6 +296,10 @@ Writes: writes_state.
|
|
|
207
296
|
| action | string | yes | archive, create, preview_due, spawn_due, update. Action to perform. |
|
|
208
297
|
| repeatableQuestId | integer | no | Repeatable quest to archive or update. |
|
|
209
298
|
| repeatableQuest | object | no | |
|
|
299
|
+
| repeatableQuest.title | string | yes | Title for the new repeatable quest. |
|
|
300
|
+
| repeatableQuest.objective | string | yes | Objective for the new repeatable quest. |
|
|
301
|
+
| repeatableQuest.rrule | string | yes | RRULE describing recurrence. |
|
|
302
|
+
| repeatableQuest.anchorAt | integer | yes | Recurrence anchor timestamp. |
|
|
210
303
|
| title | string | no | Optional new title for the update action. |
|
|
211
304
|
| objective | string | no | Optional new objective for the update action. |
|
|
212
305
|
| questlineId | integer | no | Optional new questline id. |
|
|
@@ -221,6 +314,12 @@ Writes: writes_state.
|
|
|
221
314
|
| archivedAt | integer | no | Optional archive timestamp. |
|
|
222
315
|
| now | integer | no | Evaluation or update timestamp. |
|
|
223
316
|
|
|
317
|
+
```sh
|
|
318
|
+
ghostpaw-questlog call manage_repeatable '{"action":"archive","repeatableQuestId":1}'
|
|
319
|
+
ghostpaw-questlog call manage_repeatable '{"action":"create","repeatableQuest":{"title":"Review release notes","objective":"Check changes against the release","rrule":"FREQ=WEEKLY","anchorAt":1800000000000}}'
|
|
320
|
+
ghostpaw-questlog call manage_repeatable '{"action":"preview_due"}'
|
|
321
|
+
```
|
|
322
|
+
|
|
224
323
|
### tag_work
|
|
225
324
|
|
|
226
325
|
Classify work by adding, removing, or replacing tags on quests and by replacing the future tag template set on repeatable quests.
|
|
@@ -235,9 +334,17 @@ Writes: writes_state.
|
|
|
235
334
|
| --- | --- | --- | --- |
|
|
236
335
|
| action | string | yes | add, remove, replace. Action to perform. |
|
|
237
336
|
| target | object | yes | |
|
|
337
|
+
| target.id | integer | yes | Target entity id. |
|
|
338
|
+
| target.kind | string | yes | quest, repeatable_quest. Target kind. |
|
|
238
339
|
| tagNames | array | yes | Tag names to add, remove, or replace. |
|
|
239
340
|
| now | integer | no | Optional timestamp for the tag mutation. |
|
|
240
341
|
|
|
342
|
+
```sh
|
|
343
|
+
ghostpaw-questlog call tag_work '{"action":"add","target":{"id":1,"kind":"quest"},"tagNames":["release"]}'
|
|
344
|
+
ghostpaw-questlog call tag_work '{"action":"remove","target":{"id":1,"kind":"quest"},"tagNames":["release"]}'
|
|
345
|
+
ghostpaw-questlog call tag_work '{"action":"replace","target":{"id":1,"kind":"quest"},"tagNames":["release"]}'
|
|
346
|
+
```
|
|
347
|
+
|
|
241
348
|
### reward_work
|
|
242
349
|
|
|
243
350
|
Manage rewards by adding, updating, removing, or claiming quest rewards, or by replacing future reward templates on repeatable quests.
|
|
@@ -252,11 +359,22 @@ Writes: writes_state.
|
|
|
252
359
|
| --- | --- | --- | --- |
|
|
253
360
|
| action | string | yes | add, claim, remove, replace_repeatable_template, update. Action to perform. |
|
|
254
361
|
| target | object | yes | |
|
|
362
|
+
| target.id | integer | yes | Target entity id. |
|
|
363
|
+
| target.kind | string | yes | quest, reward, repeatable_quest. Target kind. |
|
|
255
364
|
| reward | object | no | |
|
|
365
|
+
| reward.kind | string | yes | Reward kind. |
|
|
366
|
+
| reward.name | string | yes | Reward name. |
|
|
367
|
+
| reward.now | integer | no | Optional update timestamp for the update action. |
|
|
256
368
|
| rewards | array | no | Full future reward template set. Required for replace_repeatable_template. |
|
|
257
369
|
| claimedAt | integer | no | Optional claim timestamp. |
|
|
258
370
|
| now | integer | no | Optional timestamp for removal or template replacement. |
|
|
259
371
|
|
|
372
|
+
```sh
|
|
373
|
+
ghostpaw-questlog call reward_work '{"action":"add","target":{"id":1,"kind":"quest"},"reward":{"kind":"release","name":"release"}}'
|
|
374
|
+
ghostpaw-questlog call reward_work '{"action":"claim","target":{"id":1,"kind":"quest"}}'
|
|
375
|
+
ghostpaw-questlog call reward_work '{"action":"remove","target":{"id":1,"kind":"quest"}}'
|
|
376
|
+
```
|
|
377
|
+
|
|
260
378
|
### retire_work
|
|
261
379
|
|
|
262
380
|
Hide an item from normal active operation without rewriting history by soft-deleting a rumor, quest, questline, or repeatable quest.
|
|
@@ -271,35 +389,42 @@ Writes: writes_state.
|
|
|
271
389
|
| --- | --- | --- | --- |
|
|
272
390
|
| action | string | yes | hide. The retirement action to perform. |
|
|
273
391
|
| target | object | yes | The target to hide. |
|
|
392
|
+
| target.kind | string | yes | quest, questline, repeatable_quest, rumor. The kind of item to hide. |
|
|
393
|
+
| target.id | integer | yes | The numeric id of the item to hide. |
|
|
274
394
|
| deletedAt | integer | no | Optional timestamp to record when the item became hidden. |
|
|
275
395
|
|
|
396
|
+
```sh
|
|
397
|
+
ghostpaw-questlog call retire_work '{"action":"hide","target":{"kind":"quest","id":1}}'
|
|
398
|
+
```
|
|
399
|
+
|
|
276
400
|
### Workflow guides
|
|
277
401
|
|
|
278
|
-
- [
|
|
279
|
-
- [
|
|
280
|
-
- [
|
|
281
|
-
-
|
|
282
|
-
- [
|
|
283
|
-
- [
|
|
284
|
-
- [
|
|
285
|
-
- [
|
|
286
|
-
-
|
|
287
|
-
- [
|
|
288
|
-
- [
|
|
289
|
-
- [
|
|
290
|
-
- [
|
|
291
|
-
- [plan-
|
|
292
|
-
- [
|
|
293
|
-
- [
|
|
294
|
-
- [
|
|
295
|
-
- [
|
|
296
|
-
- [
|
|
297
|
-
- [
|
|
298
|
-
- [run-
|
|
299
|
-
- [
|
|
300
|
-
- [
|
|
301
|
-
- [
|
|
302
|
-
- [
|
|
402
|
+
- `ghostpaw-questlog skill webhooks` ([webhooks](references/webhooks.md)): Configure signed outbound event webhooks and verify deliveries.
|
|
403
|
+
- `ghostpaw-questlog skill archive-delete-and-prune` ([archive-delete-and-prune](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.
|
|
404
|
+
- `ghostpaw-questlog skill choose-work-shape` ([choose-work-shape](references/choose-work-shape.md)): Choose the right structure for new work by separating uncertainty, one-shot execution, multi-step arcs, and recurring patterns.
|
|
405
|
+
- `ghostpaw-questlog skill clarify-ambiguous-requests` ([clarify-ambiguous-requests](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.
|
|
406
|
+
- `ghostpaw-questlog skill close-work-and-claim-outcomes` ([close-work-and-claim-outcomes](references/close-work-and-claim-outcomes.md)): Close work with the correct terminal lifecycle action, then handle any concrete reward claim as a separate explicit step.
|
|
407
|
+
- `ghostpaw-questlog skill create-concrete-quest` ([create-concrete-quest](references/create-concrete-quest.md)): Create real, bounded executable quests only when the objective is concrete enough to execute without interpretive guesswork.
|
|
408
|
+
- `ghostpaw-questlog skill detect-slips-and-staleness` ([detect-slips-and-staleness](references/detect-slips-and-staleness.md)): Detect work that is slipping or going stale by reading overdue, deferred, in-progress, and related operational views before choosing one recovery move.
|
|
409
|
+
- `ghostpaw-questlog skill escalate-and-unblock` ([escalate-and-unblock](references/escalate-and-unblock.md)): Diagnose blockers honestly, then remove or realign hard gates when the model is wrong instead of treating every delay as generic escalation theater.
|
|
410
|
+
- `ghostpaw-questlog skill frame-initiative-questline` ([frame-initiative-questline](references/frame-initiative-questline.md)): Use questlines for shared initiative context, then attach concrete quests and maintain the structure without confusing one quest with one arc.
|
|
411
|
+
- `ghostpaw-questlog skill handle-exceptions-and-weird-cases` ([handle-exceptions-and-weird-cases](references/handle-exceptions-and-weird-cases.md)): Handle weird cases by diagnosing the actual tool outcome, routing into clarification or recovery when needed, and refusing to fake a clean normal-state story.
|
|
412
|
+
- `ghostpaw-questlog skill intake-triage` ([intake-triage](references/intake-triage.md)): Triage new asks, ideas, and vague incoming work into the right next step without prematurely committing execution structure.
|
|
413
|
+
- `ghostpaw-questlog skill maintain-clear-ownership` ([maintain-clear-ownership](references/maintain-clear-ownership.md)): Keep ownership explicit through quest content and classification because Questlog does not provide a separate assignee field or ownership tool.
|
|
414
|
+
- `ghostpaw-questlog skill manage-approvals-and-promises` ([manage-approvals-and-promises](references/manage-approvals-and-promises.md)): Treat approvals and commitments as modeled work with timing and dependencies instead of burying them as vague narrative promises.
|
|
415
|
+
- `ghostpaw-questlog skill plan-successor-work` ([plan-successor-work](references/plan-successor-work.md)): Create explicit successor work after closure by spawning follow-ups or shaping new work, while keeping uncertain next steps in intake instead of faking certainty.
|
|
416
|
+
- `ghostpaw-questlog skill plan-time-correctly` ([plan-time-correctly](references/plan-time-correctly.md)): Use quest planning fields honestly so availability, due pressure, and schedule intent stay meaningful instead of getting collapsed into one generic date.
|
|
417
|
+
- `ghostpaw-questlog skill prioritize-across-streams` ([prioritize-across-streams](references/prioritize-across-streams.md)): Prioritize across competing work streams by reading real candidate sets, distinguishing available from blocked work, and then reflecting the choice in planning.
|
|
418
|
+
- `ghostpaw-questlog skill protect-capacity-and-focus` ([protect-capacity-and-focus](references/protect-capacity-and-focus.md)): Protect capacity and focus by reading the real in-progress and scheduled-now load, then using planning to rebalance instead of silently overcommitting.
|
|
419
|
+
- `ghostpaw-questlog skill recover-from-modeling-mistakes` ([recover-from-modeling-mistakes](references/recover-from-modeling-mistakes.md)): Recover from modeling mistakes by diagnosing the exact current state first, then applying the smallest honest corrective tool instead of rewriting history blindly.
|
|
420
|
+
- `ghostpaw-questlog skill report-status-and-manage-expectations` ([report-status-and-manage-expectations](references/report-status-and-manage-expectations.md)): Build status reporting from the real questlog state, separating available, blocked, in-progress, slipping, and resolved work without relying on memory.
|
|
421
|
+
- `ghostpaw-questlog skill revise-or-reshape-commitment` ([revise-or-reshape-commitment](references/revise-or-reshape-commitment.md)): Revise a quest objective before execution starts, but reshape commitments honestly with lifecycle tools once real execution history exists.
|
|
422
|
+
- `ghostpaw-questlog skill run-operational-review` ([run-operational-review](references/run-operational-review.md)): Drive daily or weekly operational review from structured list views, then move from diagnosis into actual planning or execution changes.
|
|
423
|
+
- `ghostpaw-questlog skill run-recurring-rhythms` ([run-recurring-rhythms](references/run-recurring-rhythms.md)): Model recurring work as repeatable definitions that spawn fresh concrete quests over time instead of living forever as one immortal task.
|
|
424
|
+
- `ghostpaw-questlog skill search-and-retrieve-context` ([search-and-retrieve-context](references/search-and-retrieve-context.md)): Find relevant questlog context quickly, then switch from discovery to exact inspection without confusing free-text search with structured review surfaces.
|
|
425
|
+
- `ghostpaw-questlog skill sequence-with-unlocks` ([sequence-with-unlocks](references/sequence-with-unlocks.md)): Model hard sequencing with unlocks between concrete quests so blocked and available work stay truthful and reviewable.
|
|
426
|
+
- `ghostpaw-questlog skill settle-rumor-into-structure` ([settle-rumor-into-structure](references/settle-rumor-into-structure.md)): Turn a ready rumor into committed quest or questline structure without losing provenance or pretending vague intake is settled.
|
|
427
|
+
- `ghostpaw-questlog skill tag-and-filter-portfolios` ([tag-and-filter-portfolios](references/tag-and-filter-portfolios.md)): Use tags for cross-cutting classification and portfolio filtering without confusing tags for status, timing, or dependency modeling.
|
|
303
428
|
|
|
304
429
|
### Principles
|
|
305
430
|
|
|
@@ -307,3 +432,7 @@ Writes: writes_state.
|
|
|
307
432
|
- Read before you prescribe.
|
|
308
433
|
- Protect history when reality changes.
|
|
309
434
|
- Close the last mile, not just the main work.
|
|
435
|
+
|
|
436
|
+
## Without the binary
|
|
437
|
+
|
|
438
|
+
Use `npx -y @ghostpaw/questlog ...` in npm-based environments (Node 24+). Harnesses that embed it in code can import `@ghostpaw/questlog` as a library.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Webhooks
|
|
2
|
+
|
|
3
|
+
Use `questlog` to configure opt-in outbound automation. No server or scheduler is added.
|
|
4
|
+
No targets means no network calls. `manage_hooks` supports list, remove, tick with
|
|
5
|
+
`dry_run`, and deliveries; add/test are CLI-only. `review_questlog` view `deliveries`
|
|
6
|
+
and `questlog show <id>` expose pending/failed deliveries.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
questlog hook add https://example.org/wake --min-gap 60
|
|
10
|
+
questlog hook add https://example.org/team --tag work --events quest.due,quest.overdue --secret-stdin
|
|
11
|
+
questlog hook label work
|
|
12
|
+
questlog hook list
|
|
13
|
+
questlog tick --dry-run
|
|
14
|
+
questlog tick
|
|
15
|
+
questlog watch --interval 60
|
|
16
|
+
questlog hook test 1
|
|
17
|
+
questlog review deliveries
|
|
18
|
+
questlog show 12
|
|
19
|
+
questlog hook remove 1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`hook add` prints its random 32-byte signing secret once, also as `secret` in `--json`.
|
|
23
|
+
Save it securely. `--secret-stdin` supplies one via stdin; there is no secret flag.
|
|
24
|
+
List output redacts userinfo/query strings. Removal deletes the target and deliveries.
|
|
25
|
+
Default scope is the database; `--tag` matches quest tags, never rumors.
|
|
26
|
+
`--events` defaults to all types. The DB label defaults to the filename without its
|
|
27
|
+
path/extension (`questlog` in memory); set it to a name suitable for disclosure.
|
|
28
|
+
|
|
29
|
+
```cron
|
|
30
|
+
* * * * * questlog tick
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Cron's PATH may need `$HOME/.local/bin/questlog tick --db /path/to/quests.db`.
|
|
34
|
+
Watch defaults to 60 seconds (minimum 5); SIGINT/SIGTERM finishes the current tick.
|
|
35
|
+
Tick exits 0 even when deliveries need retries. Dry-run records nothing and sends nothing.
|
|
36
|
+
|
|
37
|
+
Events are detected from the model at tick time:
|
|
38
|
+
|
|
39
|
+
- `quest.due`: an unresolved, undeleted quest reaches its effective due time (own `due_at`, otherwise its undeleted questline's due time).
|
|
40
|
+
- `quest.overdue`: that effective deadline is strictly earlier than now and the quest remains unresolved.
|
|
41
|
+
- `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.
|
|
42
|
+
- `repeatable.spawned`: a concrete repeatable instance was created; occurrence time is its creation time. Tick first materializes due anchors through the existing spawn operation.
|
|
43
|
+
- `rumor.captured`: an undeleted rumor was created; occurrence time is its creation time, even if subsequently settled or dismissed.
|
|
44
|
+
|
|
45
|
+
Persistent event keys contain type, entity ids, and occurrence time. Restarts and repeated
|
|
46
|
+
ticks do not repeat occurrences. Removed transitions between ticks cannot be reconstructed.
|
|
47
|
+
Only occurrences at/after target creation are assigned; tags are evaluated at assignment.
|
|
48
|
+
Tick materializes due repeatables using the existing spawn path, including during preview
|
|
49
|
+
with rollback. Batches contain only ids, event types, timestamps, and the DB label:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{"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"}]}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Headers are `content-type: application/json`, `user-agent: questlog/<version>`,
|
|
56
|
+
`x-questlog-delivery: <deliveryId>`, `x-questlog-timestamp: <unix seconds>`, and
|
|
57
|
+
`x-questlog-signature: sha256=<hex HMAC-SHA256(secret, timestamp + "." + rawBody)>`.
|
|
58
|
+
No titles, objectives, details, or tag text are sent. `hook test` sends a logged `hook.test`
|
|
59
|
+
event immediately, ignoring the min gap. Add and test are CLI-only in the tool facade;
|
|
60
|
+
`manage_hooks` supports list, remove, tick (with `dry_run`), and deliveries.
|
|
61
|
+
|
|
62
|
+
2xx delivers. Timeout is 5 seconds. Failures retry after 30 s, 1 m, 2 m, 4 m, doubling
|
|
63
|
+
to 1 h plus <1 s jitter, subject to the target's min gap. Eight failures mark failed.
|
|
64
|
+
Retries keep the delivery id/events; new events queue behind them. Keep the last 500
|
|
65
|
+
delivered log entries per target and all pending/failed entries. Transactional claims
|
|
66
|
+
lease work for two minutes. A crash after receipt may retry: dedupe at the receiver.
|
|
67
|
+
|
|
68
|
+
### Verifying a delivery
|
|
69
|
+
|
|
70
|
+
Compute HMAC-SHA256 over `timestamp + "." + rawBody` with the secret and compare in constant
|
|
71
|
+
time. Reject timestamps older than 5 minutes (and timestamps too far in the future), then
|
|
72
|
+
dedupe on `x-questlog-delivery`. Use durable deduplication storage in a production receiver.
|
|
73
|
+
This 15-line Node example uses an in-memory set:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
77
|
+
import { createServer } from 'node:http';
|
|
78
|
+
const secret = process.env.WEBHOOK_SECRET, seen = new Set();
|
|
79
|
+
createServer(async (req, res) => {
|
|
80
|
+
const chunks = []; for await (const chunk of req) chunks.push(chunk);
|
|
81
|
+
const rawBody = Buffer.concat(chunks), h = req.headers;
|
|
82
|
+
const timestamp = h['x-questlog-timestamp'], id = h['x-questlog-delivery'];
|
|
83
|
+
const age = Date.now() / 1000 - Number(timestamp);
|
|
84
|
+
const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
|
|
85
|
+
const signature = String(h['x-questlog-signature'] || '');
|
|
86
|
+
const actual = Buffer.from(signature.slice(7), 'hex');
|
|
87
|
+
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; }
|
|
88
|
+
if (!seen.has(id)) { seen.add(id); console.log(JSON.parse(rawBody)); }
|
|
89
|
+
res.writeHead(204).end();
|
|
90
|
+
}).listen(8080, '127.0.0.1');
|
|
91
|
+
```
|
package/dist/chunk-KRQDV4KF.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
function resolveQuestlogDbPath(options = {}) {
|
|
6
|
-
return options.flag ?? ((options.env ?? process.env).GHOSTPAW_QUESTLOG_DB || join(homedir(), ".ghostpaw", "questlog.db"));
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// src/version.ts
|
|
10
|
-
var questlogVersion = "0.9.1";
|
|
11
|
-
|
|
12
|
-
// src/surfaces/surface_types.ts
|
|
13
|
-
function isErrorResult(result) {
|
|
14
|
-
return typeof result === "object" && result !== null && "ok" in result && result.ok === false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// src/surfaces/validate_input.ts
|
|
18
|
-
function validateInput(schema, input, path = "$") {
|
|
19
|
-
const errors = [];
|
|
20
|
-
const matchesType = (type) => {
|
|
21
|
-
switch (type) {
|
|
22
|
-
case "object":
|
|
23
|
-
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
24
|
-
case "array":
|
|
25
|
-
return Array.isArray(input);
|
|
26
|
-
case "integer":
|
|
27
|
-
return typeof input === "number" && Number.isInteger(input);
|
|
28
|
-
case "number":
|
|
29
|
-
return typeof input === "number" && Number.isFinite(input);
|
|
30
|
-
case "null":
|
|
31
|
-
return input === null;
|
|
32
|
-
default:
|
|
33
|
-
return typeof input === type;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
if (schema.type && !(Array.isArray(schema.type) ? schema.type : [schema.type]).some(matchesType)) {
|
|
37
|
-
return [`${path}: expected ${String(schema.type)}`];
|
|
38
|
-
}
|
|
39
|
-
if (schema.enum && !schema.enum.some((value) => JSON.stringify(value) === JSON.stringify(input)))
|
|
40
|
-
errors.push(`${path}: expected one of ${JSON.stringify(schema.enum)}`);
|
|
41
|
-
if (schema.oneOf && !schema.oneOf.some((branch) => validateInput(branch, input, path).length === 0))
|
|
42
|
-
errors.push(`${path}: must match at least one schema branch`);
|
|
43
|
-
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
44
|
-
const record = input;
|
|
45
|
-
for (const name of schema.required ?? [])
|
|
46
|
-
if (!Object.hasOwn(record, name)) errors.push(`${path}.${name}: required`);
|
|
47
|
-
for (const [name, property] of Object.entries(schema.properties ?? {}))
|
|
48
|
-
if (Object.hasOwn(record, name))
|
|
49
|
-
errors.push(...validateInput(property, record[name], `${path}.${name}`));
|
|
50
|
-
}
|
|
51
|
-
if (Array.isArray(input) && schema.items)
|
|
52
|
-
input.forEach((value, index) => {
|
|
53
|
-
errors.push(...validateInput(schema.items, value, `${path}[${index}]`));
|
|
54
|
-
});
|
|
55
|
-
return errors;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export { isErrorResult, questlogVersion, resolveQuestlogDbPath, validateInput };
|