@aitne-sh/aitne 0.1.5 → 0.1.6
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 +16 -0
- package/agent-assets/agent-profiles/_safety.md +17 -2
- package/agent-assets/agent-profiles/routine-fetch-window.md +75 -40
- package/agent-assets/agent-profiles/wiki-agent.md +19 -0
- package/agent-assets/docs/features/messaging/bang-commands.md +161 -0
- package/agent-assets/docs/features/messaging/overview.md +3 -0
- package/agent-assets/docs/features/wiki/commands.md +222 -0
- package/agent-assets/docs/features/wiki/overview.md +145 -0
- package/agent-assets/docs/getting-started/03-what-can-this-do.md +18 -0
- package/agent-assets/docs/glossary.md +34 -0
- package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +123 -0
- package/agent-assets/docs/guides/build-your-wiki.md +99 -0
- package/agent-assets/docs/guides/explore-with-trace-and-connect.md +169 -0
- package/agent-assets/docs/guides/maintain-wiki-health.md +168 -0
- package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +192 -0
- package/agent-assets/docs/guides/pause-the-agent.md +10 -3
- package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +156 -0
- package/agent-assets/docs/reference/cli-commands.md +24 -1
- package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +96 -0
- package/agent-assets/docs/troubleshooting/wiki-write-failed.md +82 -0
- package/agent-assets/skills/context/SKILL.md +288 -17
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +2 -2
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +3 -3
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +6 -6
- package/agent-assets/skills/external-services/SKILL.md +5 -3
- package/agent-assets/skills/external-services/SKILL.native.claude.md +49 -58
- package/agent-assets/skills/external-services/SKILL.native.codex.md +50 -58
- package/agent-assets/skills/external-services/SKILL.native.gemini.md +53 -56
- package/agent-assets/skills/mail/SKILL.md +5 -5
- package/agent-assets/skills/mail/SKILL.native.claude.md +57 -65
- package/agent-assets/skills/mail/SKILL.native.codex.md +73 -75
- package/agent-assets/skills/mail/SKILL.native.gemini.md +80 -75
- package/agent-assets/skills/management-task-register/SKILL.md +3 -3
- package/agent-assets/skills/notion/SKILL.native.claude.md +78 -82
- package/agent-assets/skills/notion/SKILL.native.codex.md +78 -80
- package/agent-assets/skills/notion/SKILL.native.gemini.md +91 -90
- package/agent-assets/skills/observations/SKILL.md +104 -14
- package/agent-assets/skills/roadmap/SKILL.md +19 -0
- package/agent-assets/skills/schedule/SKILL.md +44 -3
- package/agent-assets/skills/today/SKILL.md +25 -5
- package/agent-assets/skills/travel-time/SKILL.md +9 -0
- package/agent-assets/skills/wiki/wiki-ask/SKILL.md +32 -0
- package/agent-assets/skills/wiki/wiki-compile/SKILL.md +126 -0
- package/agent-assets/skills/wiki/wiki-connect/SKILL.md +75 -0
- package/agent-assets/skills/wiki/wiki-graduate/SKILL.md +45 -0
- package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +182 -0
- package/agent-assets/skills/wiki/wiki-lint/SKILL.md +90 -0
- package/agent-assets/skills/wiki/wiki-trace/SKILL.md +72 -0
- package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +145 -0
- package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +28 -9
- package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +26 -9
- package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +51 -24
- package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +46 -16
- package/agent-assets/task-flows/_partials/notion-acquire.notion.md +29 -9
- package/agent-assets/task-flows/message.received.dm.md +35 -2
- package/agent-assets/task-flows/message.received.dm.native.claude.md +25 -26
- package/agent-assets/task-flows/message.received.dm.native.codex.md +30 -24
- package/agent-assets/task-flows/message.received.dm.native.gemini.md +36 -36
- package/agent-assets/task-flows/message.received.dm_first.md +43 -4
- package/agent-assets/task-flows/message.received.dm_first.native.claude.md +20 -20
- package/agent-assets/task-flows/message.received.dm_first.native.codex.md +22 -19
- package/agent-assets/task-flows/message.received.dm_first.native.gemini.md +28 -24
- package/agent-assets/task-flows/routine.fetch_window.md +51 -36
- package/agent-assets/task-flows/routine.morning_routine.md +12 -3
- package/agent-assets/task-flows/routine.morning_routine_initial.md +22 -1
- package/agent-assets/task-flows/scheduled.dm.md +477 -0
- package/agent-assets/task-flows/wiki.ask.md +11 -0
- package/agent-assets/task-flows/wiki.compile.md +28 -0
- package/agent-assets/task-flows/wiki.connect.md +12 -0
- package/agent-assets/task-flows/wiki.ingest_url.md +35 -0
- package/agent-assets/task-flows/wiki.lint.md +13 -0
- package/agent-assets/task-flows/wiki.trace.md +13 -0
- package/agent-assets/wiki-seeds/schemas/output.md +12 -0
- package/agent-assets/wiki-seeds/schemas/raw.md +13 -0
- package/agent-assets/wiki-seeds/schemas/wiki.md +12 -0
- package/agent-assets/wiki-seeds/taxonomy.md +13 -0
- package/package.json +21 -41
|
@@ -78,6 +78,7 @@ content rules.
|
|
|
78
78
|
|
|
79
79
|
- starts with `morning briefing` → see `## Morning briefing` below
|
|
80
80
|
- starts with `profile_interview:` → see `## Profile interview` below
|
|
81
|
+
- starts with `confirm:` → see `## Confirmation follow-up` below
|
|
81
82
|
- (future sub-flows added here)
|
|
82
83
|
|
|
83
84
|
If no sub-flow matches:
|
|
@@ -148,6 +149,16 @@ the daily greeting.
|
|
|
148
149
|
to your own backend's native Gmail MCP tools — that connector
|
|
149
150
|
reads a different account than the user's delegated one.
|
|
150
151
|
<!-- /mode:delegated-cross:gmail -->
|
|
152
|
+
<!-- mode:native:gmail -->
|
|
153
|
+
Non-Gmail accounts: use the `mail` skill as in direct mode.
|
|
154
|
+
Gmail accounts: the `/api/mail/*` per-account gate returns 410
|
|
155
|
+
`{"error":"integration_native"}` — use your session backend's
|
|
156
|
+
native Gmail MCP tool with a "10 most recent inbox" query
|
|
157
|
+
(`q=in:inbox`, limit/maxResults `10`). The materialized `mail`
|
|
158
|
+
skill body (`SKILL.native.<session-backend>.md`) lists the
|
|
159
|
+
per-backend tool names. The daemon does not proxy in native mode;
|
|
160
|
+
do NOT call `/api/integrations/gmail/exec` (also returns 410).
|
|
161
|
+
<!-- /mode:native:gmail -->
|
|
151
162
|
<!-- mode:disabled:gmail -->
|
|
152
163
|
Gmail is disabled — skip Gmail accounts entirely. Continue with
|
|
153
164
|
the remaining accounts (iCloud / Outlook / Yahoo / IMAP) via the
|
|
@@ -391,3 +402,469 @@ preserve any other entries byte-for-byte, PATCH `mode=replace`. Without
|
|
|
391
402
|
this transition, the DM-handler queue-flip (Operation 4) will see
|
|
392
403
|
`state=scheduled` and treat the user's reply as unrelated, leaving the
|
|
393
404
|
row open.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Confirmation follow-up
|
|
409
|
+
|
|
410
|
+
Triggered by `{event_data[task]}` starting with `confirm:`. The DM
|
|
411
|
+
handler scheduled this row because a gate (e.g. project-creation, a
|
|
412
|
+
managed-task duplicate, a long-horizon ambiguity) was triggered during
|
|
413
|
+
an earlier DM but could not be asked then — either the conversation
|
|
414
|
+
topic was incompatible, or the user's reply was already long, or the
|
|
415
|
+
universal "no topic-pivoting trailing question" rule in
|
|
416
|
+
`message.received.dm{,_first}.md` suppressed the inline ask.
|
|
417
|
+
|
|
418
|
+
The full `taskContext` schema is documented in
|
|
419
|
+
`docs/design/appendices/dm-conversational-flow.md` §B1. The fields
|
|
420
|
+
this sub-flow reads at fire time are:
|
|
421
|
+
|
|
422
|
+
- `confirm_id` — opaque per-row identifier; logged on abort / fire
|
|
423
|
+
- `confirm_dedup_key` (required) — stable topic key (`<gate>:<topic>`)
|
|
424
|
+
- `confirm_hint` — agent-internal English brief of what to ask
|
|
425
|
+
- `confirm_recent_window_hours` (default 24) — DM-history scan horizon
|
|
426
|
+
- `confirm_attempt` (default 1) / `confirm_max_attempts` (default 2)
|
|
427
|
+
— retry accounting (see Step 3)
|
|
428
|
+
- `confirm_defer_count` (default 0) / `confirm_max_defers` (default 3)
|
|
429
|
+
— active-conversation-interlock deferrals (see Step 1 check 1)
|
|
430
|
+
- `confirm_decline_marker` (optional, `{path, section, match}`) —
|
|
431
|
+
file + section + match string that, when present in the named
|
|
432
|
+
context file, signals the user already declined
|
|
433
|
+
- `confirm_slot` (optional, `{path, section?, anchor?}`) — file slot
|
|
434
|
+
that, when filled, means the answer already landed via a different
|
|
435
|
+
path
|
|
436
|
+
|
|
437
|
+
### Step 1 — Fire-time abort or defer
|
|
438
|
+
|
|
439
|
+
Four checks, run in order. **The first positive result terminates
|
|
440
|
+
Step 1** — either abort silent or self-defer; checks after a positive
|
|
441
|
+
are skipped.
|
|
442
|
+
|
|
443
|
+
#### Check 1 — Active-conversation interlock
|
|
444
|
+
|
|
445
|
+
Inspect `<recent_dm_messages window="60min">`:
|
|
446
|
+
|
|
447
|
+
- **state=very-recent** (inbound user DM in the last 5 min):
|
|
448
|
+
**self-defer.** The user is mid-thread. Firing now violates Goal 1
|
|
449
|
+
("don't break the conversation thread") even with a Variant-B
|
|
450
|
+
bridge. POST a replacement schedule row at
|
|
451
|
+
`<current_time> + 15 min` with the SAME `confirm_dedup_key`,
|
|
452
|
+
`confirm_attempt` unchanged, `confirm_defer_count += 1`, and all
|
|
453
|
+
other `taskContext` fields inherited:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
curl -s -X POST http://localhost:8321/api/schedule \
|
|
457
|
+
-H 'Content-Type: application/json' \
|
|
458
|
+
-d @- <<JSON
|
|
459
|
+
{
|
|
460
|
+
"time": "<current_time + 15min, ISO 8601 with offset>",
|
|
461
|
+
"taskType": "dm_session",
|
|
462
|
+
"description": "confirm:<topic> — <hint>",
|
|
463
|
+
"model": "sonnet",
|
|
464
|
+
"taskContext": {
|
|
465
|
+
"scheduledBy": "scheduled_dm.confirm_followup.self_defer",
|
|
466
|
+
"sub_flow": "confirm",
|
|
467
|
+
"confirm_id": "<new short id>",
|
|
468
|
+
"confirm_dedup_key": "<inherited>",
|
|
469
|
+
"confirm_hint": "<inherited>",
|
|
470
|
+
"confirm_recent_window_hours": <inherited>,
|
|
471
|
+
"confirm_attempt": <inherited unchanged>,
|
|
472
|
+
"confirm_max_attempts": <inherited>,
|
|
473
|
+
"confirm_defer_count": <prior + 1>,
|
|
474
|
+
"confirm_max_defers": <inherited>,
|
|
475
|
+
"confirm_decline_marker": <inherited>,
|
|
476
|
+
"confirm_slot": <inherited>,
|
|
477
|
+
"importance": "low"
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
JSON
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
If `confirm_defer_count` after increment would **exceed**
|
|
484
|
+
`confirm_max_defers` (default 3, max total ~45 min delay), do NOT
|
|
485
|
+
re-schedule. Instead fall through to checks 2-4 below and let one
|
|
486
|
+
of them decide whether to fire or abort. The conversation has been
|
|
487
|
+
continuously hot for ~45 min; further deferral is unlikely to find
|
|
488
|
+
a better moment, and at this point the universal Goal-1-outranks-
|
|
489
|
+
Goal-3 rule means we accept Variant-B framing rather than letting
|
|
490
|
+
the confirm starve forever.
|
|
491
|
+
|
|
492
|
+
Log:
|
|
493
|
+
```
|
|
494
|
+
- HH:MM [dm_session] confirm:<topic> deferred (defer=N): user mid-thread
|
|
495
|
+
```
|
|
496
|
+
Then end the turn with NO assistant text.
|
|
497
|
+
|
|
498
|
+
- **state=active** (last 30 min, not last 5 min): **proceed** to
|
|
499
|
+
check 2. The conversational weave (Variant B) framing in this
|
|
500
|
+
task flow handles the on-the-fly bridge.
|
|
501
|
+
|
|
502
|
+
- **state=asleep**: **proceed** to check 2. Variant A applies.
|
|
503
|
+
|
|
504
|
+
#### Check 2 — Decline-marker probe (when `confirm_decline_marker` is set)
|
|
505
|
+
|
|
506
|
+
If `taskContext.confirm_decline_marker` is set, the user may have
|
|
507
|
+
previously said "no" to this exact intent. Read the file and grep the
|
|
508
|
+
named section for the `match` string:
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
curl -sS -w '\n%{http_code}' "http://localhost:8321/api/context/<confirm_decline_marker.path>"
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
A `404` status means the file has not yet been created → no marker
|
|
515
|
+
can exist → continue to Check 3. On `200`, parse the body and look
|
|
516
|
+
under the `<confirm_decline_marker.section>` heading: if any line in
|
|
517
|
+
that section contains `<confirm_decline_marker.match>` as a
|
|
518
|
+
substring, the marker is present → **abort silent** with reason
|
|
519
|
+
`decline-marker`.
|
|
520
|
+
|
|
521
|
+
#### Check 3 — Slot-filled probe (when `confirm_slot` is set)
|
|
522
|
+
|
|
523
|
+
If `taskContext.confirm_slot` is set, the gate's durable state may
|
|
524
|
+
have been written via a different path since this confirm was
|
|
525
|
+
scheduled. Probe:
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
curl -s "http://localhost:8321/api/profile-questions/slot-filled?path=<confirm_slot.path>§ion=<confirm_slot.section?>&anchor=<confirm_slot.anchor?>"
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
(The endpoint is profile-questions-named but generic — see
|
|
532
|
+
`packages/daemon/src/core/profile-questions/slot-filled.ts`.)
|
|
533
|
+
|
|
534
|
+
**Abort silent** with reason `slot-filled` when EITHER:
|
|
535
|
+
|
|
536
|
+
- `filled: true` — the named section / anchor has a substantive
|
|
537
|
+
bullet. This is the standard case (e.g. user-profile slot already
|
|
538
|
+
landed via a separate write), OR
|
|
539
|
+
- `fileExists: true` AND `confirm_slot.section` is null/omitted
|
|
540
|
+
AND `confirm_slot.anchor` is null/omitted — i.e. the gate
|
|
541
|
+
encoded "the file's mere existence is the answer". This covers
|
|
542
|
+
project-creation, where the durable state is "a
|
|
543
|
+
`projects/<slug>.md` file with frontmatter + H1 exists" rather
|
|
544
|
+
than "a specific section is populated". The endpoint reports
|
|
545
|
+
`filled: false` for a fresh frontmatter+H1 file (zero substantive
|
|
546
|
+
bullets), so a `filled`-only check would let the confirm fire
|
|
547
|
+
even though the project was already created — `fileExists` is
|
|
548
|
+
the correct signal in the no-section/no-anchor case.
|
|
549
|
+
|
|
550
|
+
Otherwise (file does not exist, or filled=false with a section
|
|
551
|
+
or anchor specified) continue to Check 4.
|
|
552
|
+
|
|
553
|
+
#### Check 4 — DM-history scan
|
|
554
|
+
|
|
555
|
+
Read `<recent_dm_conversation>` (last 20 turns) AND
|
|
556
|
+
`<recent_dm_messages window="60min">`. Judge whether the user
|
|
557
|
+
already answered the question described in
|
|
558
|
+
`taskContext.confirm_hint`. Three answer shapes count as "answered":
|
|
559
|
+
|
|
560
|
+
- **Affirmative resolution** — user wrote a sentence that lets the
|
|
561
|
+
gate complete its write. Examples: *"yeah, track it as
|
|
562
|
+
la-pm-masters"*, *"sounds good"*, *"go ahead"*, *"please do"*.
|
|
563
|
+
Abort silent with reason `already answered (yes) in DM`.
|
|
564
|
+
- **Negative resolution** — user wrote a clear decline. Examples:
|
|
565
|
+
*"no"*, *"don't bother"*, *"later"*, *"skip it"*, *"drop it"*.
|
|
566
|
+
Abort silent with reason `already answered (no) in DM`. AND if
|
|
567
|
+
`taskContext.confirm_decline_marker` is set, write the marker now
|
|
568
|
+
(see §"Decline-marker write" below) so subsequent re-fires of the
|
|
569
|
+
same gate see the declined state.
|
|
570
|
+
- **Volunteered answer** — user wrote the underlying fact without
|
|
571
|
+
prompting (e.g. *"I changed my mind about LA — heading back to
|
|
572
|
+
Tokyo"*, or supplied the value the gate would have asked for).
|
|
573
|
+
The gate's write-side picks this up. Abort silent with reason
|
|
574
|
+
`already answered (volunteered) in DM`.
|
|
575
|
+
|
|
576
|
+
Does NOT count as "answered" (fire the DM):
|
|
577
|
+
- bare re-mention without action: *"still thinking about LA PM"*
|
|
578
|
+
- status updates on the topic without consent/decline: *"LA
|
|
579
|
+
classes started"*, *"midterm was hard"*
|
|
580
|
+
- non-answer continuations: *"hmm"*, *"not sure"*
|
|
581
|
+
|
|
582
|
+
The examples above are English for prompt clarity only; recognise
|
|
583
|
+
the same shapes in any language the user writes in.
|
|
584
|
+
|
|
585
|
+
**Bias conservative on ambiguous shapes, strict on explicit "yes" /
|
|
586
|
+
"no".** A redundant ask is recoverable; a missed confirmation can
|
|
587
|
+
leave a project / roadmap entry unwritten. When the DM-history
|
|
588
|
+
evidence is genuinely ambiguous, fire the DM (fall through to
|
|
589
|
+
Step 2).
|
|
590
|
+
|
|
591
|
+
#### On abort
|
|
592
|
+
|
|
593
|
+
1. Append one line to today.md `## Agent Log` via the `today` skill
|
|
594
|
+
(PATCH `mode: "append"`, `section: "agent_log"`):
|
|
595
|
+
```
|
|
596
|
+
- HH:MM [dm_session] confirm:<topic> aborted: <reason>
|
|
597
|
+
```
|
|
598
|
+
Where `<reason>` is one of `interlock-skip`, `decline-marker`,
|
|
599
|
+
`slot-filled`, `already answered (yes|no|volunteered) in DM`.
|
|
600
|
+
2. End the turn with **NO assistant text**. `shouldNotify` is
|
|
601
|
+
unconditional for `scheduled.dm` — an empty turn means no DM is
|
|
602
|
+
sent. Do NOT emit a placeholder string.
|
|
603
|
+
3. Step 2 and Step 3 are skipped.
|
|
604
|
+
|
|
605
|
+
#### On self-defer (Check 1 only)
|
|
606
|
+
|
|
607
|
+
Same as abort (no DM, no Step 2 / Step 3 execution) — the replacement
|
|
608
|
+
schedule row is the recovery path.
|
|
609
|
+
|
|
610
|
+
#### Decline-marker write (helper for Check 4 "no" branch and evaluator)
|
|
611
|
+
|
|
612
|
+
When Check 4 detects a "no" (or the evaluator branch in Step 2 fires
|
|
613
|
+
on silence) and `taskContext.confirm_decline_marker` is set, write
|
|
614
|
+
the marker before ending the turn. Three cases — file missing
|
|
615
|
+
entirely, file present but section missing, both present — are
|
|
616
|
+
handled in one read-then-branch sequence:
|
|
617
|
+
|
|
618
|
+
1. GET the file, capturing the status code:
|
|
619
|
+
```bash
|
|
620
|
+
resp=$(curl -sS -w '\n%{http_code}' "http://localhost:8321/api/context/<confirm_decline_marker.path>")
|
|
621
|
+
status=$(printf '%s\n' "$resp" | tail -n1)
|
|
622
|
+
body=$(printf '%s\n' "$resp" | sed '$d')
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
`<confirm_decline_marker.path>` is the value from `taskContext`
|
|
626
|
+
(e.g. `agent/journal.md`). The endpoint accepts the path with or
|
|
627
|
+
without the `.md` suffix.
|
|
628
|
+
|
|
629
|
+
2. Branch on status + section presence:
|
|
630
|
+
- **status=404 (file missing).** Some marker paths
|
|
631
|
+
(`agent/journal`) support `PUT` for first-write creation via the
|
|
632
|
+
daemon's CREATE_ONLY_PUT allowlist. PUT a minimal file
|
|
633
|
+
containing an H1, the section header, and the new marker line:
|
|
634
|
+
```bash
|
|
635
|
+
curl -s -X PUT "http://localhost:8321/api/context/<confirm_decline_marker.path>" \
|
|
636
|
+
-H 'Content-Type: application/json' \
|
|
637
|
+
-d "$(jq -n --arg m '- <YYYY-MM-DD> [<confirm_dedup_key>] user declined (DM fire-time scan)' \
|
|
638
|
+
--arg s '<confirm_decline_marker.section as Title Case heading>' \
|
|
639
|
+
'{content: "# Agent Journal\n\n## \($s)\n\($m)\n"}')"
|
|
640
|
+
```
|
|
641
|
+
If the PUT returns 403 (`forbidden`), the path is not on the
|
|
642
|
+
create-only allowlist — fall through to an `append_to_file`
|
|
643
|
+
PATCH (which will fail with 404, surfacing the design gap so
|
|
644
|
+
the operator can fix it).
|
|
645
|
+
- **status=200 AND `body` contains `## <section title>`.**
|
|
646
|
+
Append a bullet to the existing section:
|
|
647
|
+
```bash
|
|
648
|
+
curl -s -X PATCH "http://localhost:8321/api/context/<confirm_decline_marker.path>" \
|
|
649
|
+
-H 'Content-Type: application/json' \
|
|
650
|
+
-d '{"section":"<section snake_case>","mode":"append","content":"- <YYYY-MM-DD> [<confirm_dedup_key>] user declined (DM fire-time scan)"}'
|
|
651
|
+
```
|
|
652
|
+
- **status=200 AND section heading missing.** Use
|
|
653
|
+
`mode: "append_to_file"` and include the header in the content:
|
|
654
|
+
```bash
|
|
655
|
+
curl -s -X PATCH "http://localhost:8321/api/context/<confirm_decline_marker.path>" \
|
|
656
|
+
-H 'Content-Type: application/json' \
|
|
657
|
+
-d '{"mode":"append_to_file","content":"\n## <Section Title>\n- <YYYY-MM-DD> [<confirm_dedup_key>] user declined (DM fire-time scan)\n"}'
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
The marker is one short line; do not paraphrase the user's words.
|
|
661
|
+
Lifetime: append-only, no rotation — the gate that opted in can
|
|
662
|
+
remove the line later if the user explicitly revisits ("OK now let's
|
|
663
|
+
start that LA project after all"), but the confirm sub-flow itself
|
|
664
|
+
never deletes markers.
|
|
665
|
+
|
|
666
|
+
**Duplicate-line tolerance.** Both this helper and the gate's
|
|
667
|
+
reply-branch Decline path (e.g. `context` skill §"Reply branches")
|
|
668
|
+
can in principle write the same `[<confirm_dedup_key>]` line if a
|
|
669
|
+
narrow race slips past `runWithSessionGates`. Do NOT add a defensive
|
|
670
|
+
"check before write" guard. The pre-check readers (e.g. Step 1
|
|
671
|
+
Check 2 here; the gate's Step 1 decline-marker pre-check) all match
|
|
672
|
+
on the `[<confirm_dedup_key>]` substring, so duplicate lines do not
|
|
673
|
+
break the dedup contract — they are cosmetic only.
|
|
674
|
+
|
|
675
|
+
### Step 2 — Compose the confirmation (or close the chain silently)
|
|
676
|
+
|
|
677
|
+
#### Evaluator branch — chain-close on silence
|
|
678
|
+
|
|
679
|
+
If `taskContext.confirm_attempt > taskContext.confirm_max_attempts`,
|
|
680
|
+
this row is a **decline-on-silence evaluator** (see Step 3). Step 1's
|
|
681
|
+
four checks already established that the user has not replied. Do
|
|
682
|
+
NOT compose a DM. Instead:
|
|
683
|
+
|
|
684
|
+
1. Write the decline marker described in §"Decline-marker write"
|
|
685
|
+
above, with marker text:
|
|
686
|
+
```
|
|
687
|
+
- <YYYY-MM-DD> [<confirm_dedup_key>] silence-after-<confirm_max_attempts>-asks
|
|
688
|
+
```
|
|
689
|
+
2. Append one line to today.md `## Agent Log`:
|
|
690
|
+
```
|
|
691
|
+
- HH:MM [dm_session] confirm:<topic> chain closed: silent decline
|
|
692
|
+
```
|
|
693
|
+
3. End the turn with **NO assistant text**. The chain is now closed;
|
|
694
|
+
Step 3 below is skipped for the evaluator branch.
|
|
695
|
+
|
|
696
|
+
#### Compose branch — emit a single short DM
|
|
697
|
+
|
|
698
|
+
`taskContext.confirm_attempt <= taskContext.confirm_max_attempts`.
|
|
699
|
+
Compose a single short DM in persona voice that asks the question
|
|
700
|
+
from `taskContext.confirm_hint`. The hint is agent-internal English
|
|
701
|
+
(Policy A); the rendered DM follows `<output_language_policy>` and
|
|
702
|
+
the persona / Character voice rules at the top of this file.
|
|
703
|
+
|
|
704
|
+
Hard rules:
|
|
705
|
+
|
|
706
|
+
- **One question, one sentence** unless the topic genuinely needs
|
|
707
|
+
more context. End with the question; do NOT layer a second topic.
|
|
708
|
+
- **Do NOT mention** the schedule, the queue, the gate that fired
|
|
709
|
+
it, the word "confirm" / "confirmation", `taskContext`, IDs, or
|
|
710
|
+
any internal mechanism. The user sees a natural DM, not a queue
|
|
711
|
+
entry.
|
|
712
|
+
- **Conversation-state framing applies.** If state=active or
|
|
713
|
+
very-recent (Check 1 returned "proceed"), use Variant B — no
|
|
714
|
+
greeting, acknowledge the interruption briefly, hand the floor
|
|
715
|
+
back at the end. If state=asleep, use Variant A — persona
|
|
716
|
+
greeting opener is fine.
|
|
717
|
+
- **Softened re-check on retries.** If `confirm_attempt > 1`, this
|
|
718
|
+
is a re-check after silence, NOT a re-issue of the same question.
|
|
719
|
+
Phrase it as a check-in with a soft exit ("...or skip?", "...or
|
|
720
|
+
did this change?", "...or want me to leave it open?"). The user
|
|
721
|
+
must feel acknowledged, not pestered.
|
|
722
|
+
|
|
723
|
+
Examples (English source; render per `<output_language_policy>` and
|
|
724
|
+
persona — these phrasings are STRUCTURAL):
|
|
725
|
+
|
|
726
|
+
- Initial (`confirm_attempt=1`):
|
|
727
|
+
- hint: `create project "la-pm-masters"? (origin: DM said they moved to LA and started a PM master's)` →
|
|
728
|
+
*"Should I track 'LA PM master's' as a project so I can keep the syllabus / deadlines in one place?"*
|
|
729
|
+
- hint: `ambiguous: trip to Tokyo "next month" — date 5/15?` →
|
|
730
|
+
*"Was the Tokyo trip 5/15, or are you still picking the date?"*
|
|
731
|
+
- Softened re-check (`confirm_attempt=2`):
|
|
732
|
+
- same first hint →
|
|
733
|
+
*"Still on for tracking the LA PM master's as its own project, or skip for now?"*
|
|
734
|
+
- same second hint →
|
|
735
|
+
*"Did the Tokyo date settle, or want me to leave it open?"*
|
|
736
|
+
|
|
737
|
+
### Step 3 — Schedule the chain successor
|
|
738
|
+
|
|
739
|
+
This step runs only on the **compose branch** of Step 2 (a DM was
|
|
740
|
+
emitted). The evaluator branch already closed the chain in Step 2;
|
|
741
|
+
Step 3 is skipped in that case.
|
|
742
|
+
|
|
743
|
+
After Step 2 emits the DM text (which the daemon will dispatch as
|
|
744
|
+
this turn's final assistant text), schedule a successor row based on
|
|
745
|
+
the current attempt counter. Inherit all unchanged `taskContext`
|
|
746
|
+
fields from this row.
|
|
747
|
+
|
|
748
|
+
**Quiet-hours discipline.** The literal `<current_time> + 24h` may
|
|
749
|
+
land inside the user's quiet hours (default 22:00-08:00, configurable
|
|
750
|
+
via `runtime_settings.quietHoursStart/End`). The schedule skill's
|
|
751
|
+
"Time discipline" section forbids non-`critical` rows in quiet hours,
|
|
752
|
+
and the scheduler rejects them. Pick a target time that:
|
|
753
|
+
|
|
754
|
+
1. Is at least 24h after `<current_time>` (the §B6 minimum-interval
|
|
755
|
+
contract), and
|
|
756
|
+
2. Falls outside the user's quiet hours.
|
|
757
|
+
|
|
758
|
+
The simplest pattern: take `<current_time> + 24h` and, if that
|
|
759
|
+
clock-time is inside quiet hours, roll forward to quiet-hours-end
|
|
760
|
+
on that day. For a 23:30 initial fire with quiet hours starting at
|
|
761
|
+
22:00, this yields a 08:00 successor 24h+8.5h later — slightly more
|
|
762
|
+
than 24h, still within the spirit of "next agent-day". Do not roll
|
|
763
|
+
*backward* to fit before quiet hours; that violates the 24h
|
|
764
|
+
minimum.
|
|
765
|
+
|
|
766
|
+
#### Case A — `confirm_attempt < confirm_max_attempts`
|
|
767
|
+
|
|
768
|
+
Schedule a **softened retry** at `<current_time> + 24h`:
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
curl -s -X POST http://localhost:8321/api/schedule \
|
|
772
|
+
-H 'Content-Type: application/json' \
|
|
773
|
+
-d @- <<JSON
|
|
774
|
+
{
|
|
775
|
+
"time": "<current_time + 24h, ISO 8601 with offset>",
|
|
776
|
+
"taskType": "dm_session",
|
|
777
|
+
"description": "confirm:<topic> — <hint, softened paraphrase>",
|
|
778
|
+
"model": "sonnet",
|
|
779
|
+
"taskContext": {
|
|
780
|
+
"scheduledBy": "scheduled_dm.confirm_followup.retry",
|
|
781
|
+
"sub_flow": "confirm",
|
|
782
|
+
"confirm_id": "<new short id>",
|
|
783
|
+
"confirm_dedup_key": "<inherited unchanged>",
|
|
784
|
+
"confirm_hint": "<softened English brief — e.g. 'still on for tracking LA PM master's, or skip?'>",
|
|
785
|
+
"confirm_recent_window_hours": <inherited>,
|
|
786
|
+
"confirm_attempt": <prior + 1>,
|
|
787
|
+
"confirm_max_attempts": <inherited>,
|
|
788
|
+
"confirm_defer_count": 0,
|
|
789
|
+
"confirm_max_defers": <inherited>,
|
|
790
|
+
"confirm_decline_marker": <inherited>,
|
|
791
|
+
"confirm_slot": <inherited>,
|
|
792
|
+
"importance": "low"
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
JSON
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
The successor's `confirm_hint` SHOULD be softened by the composing
|
|
799
|
+
session — the next fire's Step 2 reads the hint as written, so a
|
|
800
|
+
gentler hint produces a gentler DM. Reset `confirm_defer_count` to 0
|
|
801
|
+
on a retry (defers are per-fire, not per-chain).
|
|
802
|
+
|
|
803
|
+
#### Case B — `confirm_attempt == confirm_max_attempts`
|
|
804
|
+
|
|
805
|
+
Schedule a single **decline-on-silence evaluator** at
|
|
806
|
+
`<current_time> + 24h` with `confirm_attempt = confirm_max_attempts + 1`
|
|
807
|
+
(sentinel). At the evaluator's fire time, Step 1 runs as usual; if
|
|
808
|
+
all four checks pass (user still has not replied), Step 2's
|
|
809
|
+
evaluator branch silently writes the decline marker and ends —
|
|
810
|
+
no DM, no further successor.
|
|
811
|
+
|
|
812
|
+
```bash
|
|
813
|
+
curl -s -X POST http://localhost:8321/api/schedule \
|
|
814
|
+
-H 'Content-Type: application/json' \
|
|
815
|
+
-d @- <<JSON
|
|
816
|
+
{
|
|
817
|
+
"time": "<current_time + 24h, ISO 8601 with offset>",
|
|
818
|
+
"taskType": "dm_session",
|
|
819
|
+
"description": "confirm:<topic> — silence-evaluator",
|
|
820
|
+
"model": "sonnet",
|
|
821
|
+
"taskContext": {
|
|
822
|
+
"scheduledBy": "scheduled_dm.confirm_followup.evaluator",
|
|
823
|
+
"sub_flow": "confirm",
|
|
824
|
+
"confirm_id": "<new short id>",
|
|
825
|
+
"confirm_dedup_key": "<inherited unchanged>",
|
|
826
|
+
"confirm_hint": "<inherited>",
|
|
827
|
+
"confirm_recent_window_hours": <inherited>,
|
|
828
|
+
"confirm_attempt": <confirm_max_attempts + 1>,
|
|
829
|
+
"confirm_max_attempts": <inherited>,
|
|
830
|
+
"confirm_defer_count": 0,
|
|
831
|
+
"confirm_max_defers": <inherited>,
|
|
832
|
+
"confirm_decline_marker": <inherited>,
|
|
833
|
+
"confirm_slot": <inherited>,
|
|
834
|
+
"importance": "low"
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
JSON
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
#### Bookkeeping (silent — never visible to the user)
|
|
841
|
+
|
|
842
|
+
After scheduling the successor (Case A or B), append one line to
|
|
843
|
+
today.md `## Agent Log`:
|
|
844
|
+
|
|
845
|
+
```
|
|
846
|
+
- HH:MM [dm_session] confirm:<topic> sent (attempt=N/max=M); successor scheduled <case>
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
(Use `case=retry` for Case A and `case=evaluator` for Case B.)
|
|
850
|
+
|
|
851
|
+
### Notes — invariants this sub-flow upholds
|
|
852
|
+
|
|
853
|
+
- **Goal 1 (thread preservation).** Check 1's self-defer keeps a
|
|
854
|
+
hot thread intact even though the confirm has been waiting.
|
|
855
|
+
When defers exhaust, Goal 1 still wins: Variant-B framing softens
|
|
856
|
+
the entry rather than firing a cold opener.
|
|
857
|
+
- **Goal 2 (confirmations happen naturally).** Step 2's persona
|
|
858
|
+
voice + state-aware framing means the user experiences the DM as
|
|
859
|
+
a check-in, not a queue ping.
|
|
860
|
+
- **Goal 3 (never ask twice).** Checks 2-4 dedup against all
|
|
861
|
+
observable answer surfaces (declined, slot-filled, replied in
|
|
862
|
+
DM). Step 3's chained-fire model caps the chain at
|
|
863
|
+
`confirm_max_attempts + 1` fires (default 3), of which only
|
|
864
|
+
`confirm_max_attempts` (default 2) send DMs. The minimum
|
|
865
|
+
inter-fire interval is 24h — no same-day re-asks.
|
|
866
|
+
- **Schedule row IS the queue.** No new table, no
|
|
867
|
+
`pending-confirmations.md`. All chain state lives in
|
|
868
|
+
`taskContext`; cross-path cancellation is the gate's
|
|
869
|
+
responsibility (see the gate's reply-branch contract, e.g. the
|
|
870
|
+
`context` skill's Project DM-intent detection §"Reply branches").
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Answer from the wiki
|
|
4
|
+
|
|
5
|
+
Read `<wiki_command>` for the question. Follow the `wiki-ask` skill:
|
|
6
|
+
|
|
7
|
+
1. Search `20_wiki/` for relevant notes.
|
|
8
|
+
2. Verify against source links or `10_raw/` only when needed.
|
|
9
|
+
3. Write one `30_outputs/<YYYY-MM-DD>-<slug>.md` answer through the Wiki API with `x-process-key: wiki.ask`.
|
|
10
|
+
4. Keep the final assistant response concise; the durable answer belongs in `30_outputs/`.
|
|
11
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Compile wiki notes
|
|
4
|
+
|
|
5
|
+
A `!compile` (or approved `!compile full`) landed here. Read `<wiki_command>` for `data.mode` — `"incremental"` (compile only `10_raw/` notes touched since the last compile) or `"full"` (compile every raw). Read `<wiki_workspace>` for the destination workspace.
|
|
6
|
+
|
|
7
|
+
You succeed if and only if every wiki note you claim to have created came back from the daemon's Wiki API as `{"ok":true,"path":"20_wiki/<slug>.md"}`. The vault is on disk and there is no other path to write it.
|
|
8
|
+
|
|
9
|
+
### Critical: the only write surface is the Wiki API via `curl`
|
|
10
|
+
|
|
11
|
+
- `Write` and `Edit` tools are **stripped from this session's allow-list**. The SDK denies them silently under `dontAsk` ("Permission to use Write has been denied …"). They cannot be made to work via path rewriting; do not try.
|
|
12
|
+
- `Bash(find ...)`, `Bash(ls ...)`, `Bash(cat ...)`, `Bash(grep ...)`, `Bash(wc ...)` and every other shell utility are also silently denied. Only `Bash(curl *)` and `Bash(jq *)` are on the allow-list. Enumerate raw notes via `GET /api/wiki/<workspace>/index`, NOT by walking `{{vault_path}}` from disk.
|
|
13
|
+
- The `Bash(curl *)` allow-rule is prefix-matched against the full command. Wrappers — `echo '{...}' | curl …`, `cat <<JSON | curl …`, `bash -c "curl …"`, `( curl … )`, `var=… curl …`, chained `curl … ; curl …` — are silently denied (no output, no `PA_API_ERROR`). The reverse, `curl … -d @- <<'JSON' … JSON` on the same line, IS allowed because the command still starts with `curl`; the shim reads stdin via `-d @-`.
|
|
14
|
+
|
|
15
|
+
### Procedure
|
|
16
|
+
|
|
17
|
+
1. **Baseline (incremental only).** Read `20_wiki/_index.md` (or the most recent `wiki.compile` entry in `log.md`) to recover the prior `compiled_at` ISO timestamp. If the workspace has never been compiled, compile every raw.
|
|
18
|
+
2. **Enumerate raw notes** via `GET /api/wiki/<workspace>/index`, then filter with `jq` for `path` under `10_raw/` and (incremental) `mtime > <baseline>`.
|
|
19
|
+
3. **Read existing wiki + taxonomy** so synthesis can de-duplicate and use canonical slugs.
|
|
20
|
+
4. **For each topic**, synthesize a root-level `20_wiki/<slug>.md` note (one note per coherent topic — merge multiple raws when they cover the same thing). `POST` for a new slug, `PATCH mode: "replace"` for an existing one (read-before-write).
|
|
21
|
+
5. **Append `20_wiki/_index.md`** (`PATCH mode: "append"`) with one bullet per added or updated note.
|
|
22
|
+
6. **Append `log.md`** (`PATCH mode: "append"`) with one summary line: `[<ISO>] wiki.compile (<mode>): compiled <N> notes from <M> raws — added <A>, updated <B>, unchanged <C>`.
|
|
23
|
+
|
|
24
|
+
The `wiki-compile` skill carries the canonical curl shapes (including the multi-KB heredoc body shape), the per-error recovery table, and the slug rules. The `wiki-vault-rules` skill carries the body-quoting cheat-sheet and the full layer/endpoint reference.
|
|
25
|
+
|
|
26
|
+
Do NOT modify `00_inbox/` or existing `10_raw/` notes. Do NOT call `/api/send-message`, `/api/whatsapp/send`, `/api/notify-user`, or any other "send" endpoint — those routes do not exist. Your final assistant text IS the delivery channel; the daemon forwards it to the bang's reply target automatically.
|
|
27
|
+
|
|
28
|
+
End with the single-line completion DM from the skill (Success / Partial / Failure).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Bridge two domains in the wiki
|
|
4
|
+
|
|
5
|
+
Read `<wiki_command>` for `topic_a` and `topic_b`. Follow the `wiki-connect` skill:
|
|
6
|
+
|
|
7
|
+
1. Search each topic independently and read enough matches to characterise each domain. Disambiguate string matches against `90_meta/taxonomy.md`.
|
|
8
|
+
2. Surface bridges in four buckets — shared terminology, common references, structural analogies, and bridging concept candidates. Cite every bridge with at least one wiki path from each side. A bridge that can only cite one side belongs in the candidates list, not in the others.
|
|
9
|
+
3. Write one connection report to `30_outputs/<YYYY-MM-DD>-connect-<slug-a>--<slug-b>.md` through the Wiki API with `x-process-key: wiki.connect`. Use the canonical slugs from `90_meta/taxonomy.md` when available.
|
|
10
|
+
4. Append a one-line `log.md` entry referencing the output filename and both topics.
|
|
11
|
+
|
|
12
|
+
If no real bridges exist, write the report anyway with empty sections marked `_(none)_` and a `## Summary` that names that directly — a "no connection" finding is still useful. Do not create new wiki notes from this flow; the bridging concept candidates section is a proposal for `wiki.compile` to pick up later. End with a short internal summary only.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Ingest URL into the wiki
|
|
4
|
+
|
|
5
|
+
A single `!ingest` call landed here. Read `<wiki_command>` for the target `url` and `<wiki_workspace>` for the destination workspace.
|
|
6
|
+
|
|
7
|
+
You succeed if and only if you POST a new file to `/api/wiki/<workspace>/files/10_raw/<slug>.md` and the daemon responds with `{"ok":true,"path":"10_raw/<slug>.md"}`. There is no other definition of success. The vault file is created by that POST and nothing else — `Write` tool / shell redirection / other endpoints do not put a file in the vault.
|
|
8
|
+
|
|
9
|
+
### Critical: the Bash command MUST start with literal `curl`
|
|
10
|
+
|
|
11
|
+
The `Bash(curl *)` allow-list is prefix-matched. Wrappers (`echo '{...}' | curl …`, `cat <<JSON | curl … -d @-`, `bash -c "curl …"`, parentheses, chained `curl … ; curl …`) are silently denied under `dontAsk` — you get no error, no `PA_API_ERROR`, just an empty response. If a Bash call returns nothing, rewrite it to start with `curl`.
|
|
12
|
+
|
|
13
|
+
Article bodies are typically multi-KB — use a heredoc redirected directly into curl (the command still starts with `curl`):
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
curl http://localhost:8321/api/wiki/<workspace>/files/10_raw/<slug>.md \
|
|
17
|
+
-X POST \
|
|
18
|
+
-H 'content-type: application/json' \
|
|
19
|
+
-H 'x-process-key: wiki.ingest_url' \
|
|
20
|
+
-d @- <<'JSON'
|
|
21
|
+
{"content":"---\n…frontmatter…\n---\n\n# Title\n\n## Source extracts\n\n…"}
|
|
22
|
+
JSON
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The shim reads stdin when `-d @-` is passed, so the heredoc body lands as the JSON payload. Inside `<<'JSON'` (single-quoted marker) the body is verbatim — no shell escaping, only JSON escapes (`\"`, `\\`, `\n`). For short bodies (a few hundred bytes) inline `-d '<json>'` is fine.
|
|
26
|
+
|
|
27
|
+
### Procedure
|
|
28
|
+
|
|
29
|
+
1. Fetch the URL with the per-backend primitive (WebFetch on Claude, curl on Codex, web_fetch on Gemini).
|
|
30
|
+
2. POST one new note at `10_raw/<slug>.md` via the daemon Wiki API with `-H 'x-process-key: wiki.ingest_url'`. Path is EXACTLY `10_raw/<slug>.md` — no nested folders like `10_raw/articles/...`.
|
|
31
|
+
3. **Inspect the curl response.** Only `{"ok":true,"path":"10_raw/<slug>.md"}` counts as success. Anything else (4xx, 5xx, missing fields, hallucinated endpoint like `/api/send-message`, no response) means the file was NOT created — PATCH `log.md` with the failure reason and emit the failure DM.
|
|
32
|
+
|
|
33
|
+
The `wiki-ingest` skill carries the full curl shapes, slug rules, error-code recovery table, and completion-DM format.
|
|
34
|
+
|
|
35
|
+
End the turn with the single-line completion DM defined in the skill. The path you cite in the success DM must be byte-identical to the `path` field the daemon returned. Do not fabricate a path. Do not claim success without seeing `{"ok":true,...}`. The daemon forwards your final assistant text to the user — you must NOT also call `/api/send-message`, `/api/whatsapp/send`, `/api/notify-user`, `/api/dm`, or any other "send" endpoint; those do not exist.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Audit wiki health
|
|
4
|
+
|
|
5
|
+
Read `<wiki_command>` for the target workspace. Follow the `wiki-lint` skill:
|
|
6
|
+
|
|
7
|
+
1. Inventory the workspace via `GET /api/wiki/{{workspace_name}}/index` and read `90_meta/schemas/*` for the current schema.
|
|
8
|
+
2. Run every check the skill enumerates (orphans, broken wikilinks, missing frontmatter, stale content, term inconsistencies, taxonomy candidates, index drift). Empty findings are still reported.
|
|
9
|
+
3. Write exactly one health report to `90_meta/health/<YYYY-MM-DD>.md` through the Wiki API with `x-process-key: wiki.lint`. The report must include the `## Action items` and `## Summary` sections in the exact order documented by the skill.
|
|
10
|
+
4. If — and only if — there are taxonomy candidates, append a `# Candidates` section to `90_meta/taxonomy.md` with `mode: "append"`. The owner reviews this before any promotion happens; do not edit the existing `## Topics` section.
|
|
11
|
+
5. Append a concise summary line to `log.md`.
|
|
12
|
+
|
|
13
|
+
Do not modify content layers (`10_raw/`, `20_wiki/`, `30_outputs/`). End with a short internal summary only.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{context}
|
|
2
|
+
|
|
3
|
+
## Task: Trace an idea's evolution across the wiki
|
|
4
|
+
|
|
5
|
+
Read `<wiki_command>` for the `topic`. Follow the `wiki-trace` skill:
|
|
6
|
+
|
|
7
|
+
1. Search across all layers (`10_raw/`, `20_wiki/`, `30_outputs/`) and read the matches that look load-bearing. Use `90_meta/taxonomy.md` to canonicalise the topic slug.
|
|
8
|
+
2. Order findings chronologically using the most authoritative date available (asserted dates → output filename dates → file `mtime`). Mark any date that came from `mtime` as "discovered on" rather than "happened on".
|
|
9
|
+
3. Group into two to five phases of stable framing. For each phase, name the dominant question, the new evidence, and what changed compared to the previous phase. Cite every claim with a wiki path.
|
|
10
|
+
4. Write one timeline report to `30_outputs/<YYYY-MM-DD>-trace-<slug>.md` through the Wiki API with `x-process-key: wiki.trace`. Follow the section order documented by the skill.
|
|
11
|
+
5. Append a one-line `log.md` entry referencing the output filename and the topic.
|
|
12
|
+
|
|
13
|
+
If the wiki has fewer than two distinct sources on the topic, keep the report short and say so directly in `## Summary` — do not pad it with speculation. End with a short internal summary only.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Raw Note Schema
|
|
2
|
+
|
|
3
|
+
Raw notes live under `10_raw/` and preserve source facts before synthesis.
|
|
4
|
+
|
|
5
|
+
## Required Shape
|
|
6
|
+
|
|
7
|
+
- Source URL
|
|
8
|
+
- Retrieved timestamp
|
|
9
|
+
- Source title when available
|
|
10
|
+
- Extracted facts
|
|
11
|
+
- Quotes or snippets only when they are short and necessary
|
|
12
|
+
- Open questions
|
|
13
|
+
|