@aitne-sh/aitne 0.1.9 → 0.1.11
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 +41 -11
- package/agent-assets/agent-profiles/background-task.md +53 -0
- package/agent-assets/agent-profiles/conversational.md +1 -0
- package/agent-assets/agent-profiles/routine-fetch-window.md +14 -75
- package/agent-assets/agent-profiles/routine.md +1 -1
- package/agent-assets/agents/{hourly-check → activity-scan}/agent.md +22 -17
- package/agent-assets/agents/monthly-review/agent.md +6 -5
- package/agent-assets/docs/concepts/agent-day.md +6 -7
- package/agent-assets/docs/concepts/auth-health.md +23 -20
- package/agent-assets/docs/concepts/backends-and-tiers.md +13 -9
- package/agent-assets/docs/concepts/costs-and-quotas.md +14 -12
- package/agent-assets/docs/concepts/delegated-mode.md +18 -17
- package/agent-assets/docs/concepts/memory-model.md +16 -9
- package/agent-assets/docs/concepts/observations.md +24 -20
- package/agent-assets/docs/concepts/process-keys.md +10 -9
- package/agent-assets/docs/concepts/routines.md +34 -31
- package/agent-assets/docs/concepts/safety-and-execution.md +11 -7
- package/agent-assets/docs/concepts/safety-model.md +39 -25
- package/agent-assets/docs/concepts/skills.md +12 -10
- package/agent-assets/docs/features/integrations/browser-history.md +23 -18
- package/agent-assets/docs/features/integrations/calendar.md +28 -17
- package/agent-assets/docs/features/integrations/git.md +13 -11
- package/agent-assets/docs/features/integrations/github.md +22 -14
- package/agent-assets/docs/features/integrations/mail.md +25 -22
- package/agent-assets/docs/features/integrations/notion.md +35 -11
- package/agent-assets/docs/features/integrations/obsidian.md +8 -8
- package/agent-assets/docs/features/lifestyle/git.md +27 -23
- package/agent-assets/docs/features/lifestyle/reading.md +20 -11
- package/agent-assets/docs/features/lifestyle/receipts.md +11 -10
- package/agent-assets/docs/features/lifestyle/travel-bookings.md +4 -3
- package/agent-assets/docs/features/memory-files/agent-journal.md +53 -26
- package/agent-assets/docs/features/memory-files/agent-lessons.md +178 -0
- package/agent-assets/docs/features/memory-files/projects.md +11 -8
- package/agent-assets/docs/features/memory-files/roadmap.md +17 -14
- package/agent-assets/docs/features/memory-files/schedule.md +6 -3
- package/agent-assets/docs/features/memory-files/today.md +10 -7
- package/agent-assets/docs/features/memory-files/user-profile.md +14 -9
- package/agent-assets/docs/features/messaging/bang-commands.md +21 -6
- package/agent-assets/docs/features/messaging/overview.md +17 -14
- package/agent-assets/docs/features/messaging/telegram.md +10 -9
- package/agent-assets/docs/features/operations/activity-and-conversations.md +6 -5
- package/agent-assets/docs/features/operations/approvals.md +6 -5
- package/agent-assets/docs/features/operations/browser-tasks.md +184 -0
- package/agent-assets/docs/features/operations/cost-tracking.md +11 -1
- package/agent-assets/docs/features/operations/managed-chromium.md +4 -2
- package/agent-assets/docs/features/operations/notifications.md +11 -1
- package/agent-assets/docs/features/operations/quiet-hours.md +41 -11
- package/agent-assets/docs/features/operations/schedule-approaching.md +2 -2
- package/agent-assets/docs/features/routines/activity-scan.md +220 -0
- package/agent-assets/docs/features/routines/custom-routines.md +82 -134
- package/agent-assets/docs/features/routines/evening-review.md +23 -13
- package/agent-assets/docs/features/routines/morning-routine.md +7 -5
- package/agent-assets/docs/features/routines/weekly-review.md +24 -3
- package/agent-assets/docs/features/wiki/commands.md +4 -4
- package/agent-assets/docs/features/wiki/cost-and-approval.md +4 -3
- package/agent-assets/docs/features/wiki/dashboard.md +7 -6
- package/agent-assets/docs/features/wiki/overview.md +3 -3
- package/agent-assets/docs/features/wiki/search.md +5 -5
- package/agent-assets/docs/features/wiki/workspaces.md +2 -2
- package/agent-assets/docs/getting-started/01-what-is-this.md +3 -3
- package/agent-assets/docs/getting-started/02-first-steps.md +5 -3
- package/agent-assets/docs/getting-started/04-first-day.md +27 -30
- package/agent-assets/docs/glossary.md +8 -8
- package/agent-assets/docs/guides/add-a-custom-routine.md +122 -68
- package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +2 -2
- package/agent-assets/docs/guides/connect-a-new-mail-account.md +4 -2
- package/agent-assets/docs/guides/explore-with-trace-and-connect.md +5 -4
- package/agent-assets/docs/guides/install-and-run.md +2 -2
- package/agent-assets/docs/guides/maintain-wiki-health.md +2 -2
- package/agent-assets/docs/guides/pause-the-agent.md +27 -21
- package/agent-assets/docs/guides/reinstall-cleanly.md +2 -0
- package/agent-assets/docs/guides/setup-wizard.md +12 -6
- package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +6 -6
- package/agent-assets/docs/reference/api.md +26 -5
- package/agent-assets/docs/reference/cli-commands.md +3 -3
- package/agent-assets/docs/reference/config.md +51 -24
- package/agent-assets/docs/reference/disallowed-tools.md +6 -4
- package/agent-assets/docs/reference/keyboard-shortcuts.md +2 -2
- package/agent-assets/docs/reference/knowledge-layout.md +25 -12
- package/agent-assets/docs/reference/process-keys.md +9 -9
- package/agent-assets/docs/reference/skills.md +10 -6
- package/agent-assets/docs/troubleshooting/auth-failed.md +9 -8
- package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +16 -9
- package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +2 -2
- package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +32 -16
- package/agent-assets/docs/troubleshooting/observation-not-detected.md +26 -24
- package/agent-assets/docs/troubleshooting/quota-exhausted.md +7 -6
- package/agent-assets/docs/troubleshooting/wiki-write-failed.md +3 -3
- package/agent-assets/skills/agent-actions/SKILL.md +23 -39
- package/agent-assets/skills/agent-create/SKILL.md +26 -6
- package/agent-assets/skills/attach/SKILL.md +8 -27
- package/agent-assets/skills/background-task/SKILL.md +184 -0
- package/agent-assets/skills/background-task-reply/SKILL.md +100 -0
- package/agent-assets/skills/browser-history/SKILL.md +60 -29
- package/agent-assets/skills/browser-history-respond/SKILL.md +6 -1
- package/agent-assets/skills/browser-task/SKILL.md +33 -31
- package/agent-assets/skills/context/SKILL.md +26 -34
- package/agent-assets/skills/context/curation.json +12 -12
- package/agent-assets/skills/context/references/api.md +22 -20
- package/agent-assets/skills/context/references/required-frontmatter.md +10 -9
- package/agent-assets/skills/context/references/snapshot-files.md +16 -15
- package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +5 -5
- package/agent-assets/skills/context/seeds/frontmatter-requirements.seed.json +3 -3
- package/agent-assets/skills/docs-search/SKILL.md +19 -31
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +8 -95
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +8 -94
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +8 -94
- package/agent-assets/skills/external-services/SKILL.native.claude.md +15 -9
- package/agent-assets/skills/external-services/SKILL.native.codex.md +11 -5
- package/agent-assets/skills/external-services/SKILL.native.gemini.md +11 -5
- package/agent-assets/skills/external-services/references/exec-errors.md +32 -0
- package/agent-assets/skills/external-services/references/skills-crud.md +5 -5
- package/agent-assets/skills/gmail-lifestyle/SKILL.md +3 -2
- package/agent-assets/skills/gmail-lifestyle/references/receipts-api.md +4 -0
- package/agent-assets/skills/gmail-lifestyle/references/travel-bookings-api.md +9 -0
- package/agent-assets/skills/mail/SKILL.delegated.claude.md +13 -25
- package/agent-assets/skills/mail/SKILL.delegated.codex.md +3 -2
- package/agent-assets/skills/mail/SKILL.delegated.gemini.md +3 -2
- package/agent-assets/skills/mail/SKILL.md +12 -20
- package/agent-assets/skills/mail/SKILL.native.claude.md +24 -16
- package/agent-assets/skills/mail/SKILL.native.codex.md +16 -9
- package/agent-assets/skills/mail/SKILL.native.gemini.md +12 -6
- package/agent-assets/skills/mail/references/api.md +6 -1
- package/agent-assets/skills/mail/references/examples.md +2 -1
- package/agent-assets/skills/managed-tasks/SKILL.md +44 -77
- package/agent-assets/skills/managed-tasks/references/errors.md +25 -14
- package/agent-assets/skills/managed-tasks/references/output-path.md +33 -17
- package/agent-assets/skills/managed-tasks/references/recurrence-rule.md +26 -16
- package/agent-assets/skills/management-policy/SKILL.md +36 -28
- package/agent-assets/skills/management-policy/curation.json +1 -1
- package/agent-assets/skills/management-policy/references/policy-workflow.md +30 -18
- package/agent-assets/skills/notify/SKILL.md +16 -13
- package/agent-assets/skills/notify/references/priority.md +42 -26
- package/agent-assets/skills/notion/SKILL.delegated.claude.md +1 -1
- package/agent-assets/skills/notion/SKILL.delegated.codex.md +1 -1
- package/agent-assets/skills/notion/SKILL.delegated.gemini.md +1 -1
- package/agent-assets/skills/notion/SKILL.md +18 -18
- package/agent-assets/skills/notion/SKILL.native.claude.md +4 -4
- package/agent-assets/skills/notion/SKILL.native.codex.md +3 -3
- package/agent-assets/skills/notion/SKILL.native.gemini.md +3 -3
- package/agent-assets/skills/observations/SKILL.md +9 -24
- package/agent-assets/skills/observations/references/fetch-fallback.md +22 -0
- package/agent-assets/skills/project-doc/SKILL.md +9 -6
- package/agent-assets/skills/project-doc/curation.json +3 -3
- package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +2 -2
- package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +3 -3
- package/agent-assets/skills/reading/SKILL.md +8 -42
- package/agent-assets/skills/reading/references/reading-taste.md +5 -5
- package/agent-assets/skills/roadmap/SKILL.md +3 -19
- package/agent-assets/skills/roadmap/references/api.md +23 -8
- package/agent-assets/skills/roadmap/references/horizon-tags.md +11 -0
- package/agent-assets/skills/roadmap/references/migration.md +8 -6
- package/agent-assets/skills/roadmap/references/retention.md +18 -0
- package/agent-assets/skills/schedule/SKILL.md +20 -28
- package/agent-assets/skills/schedule/references/importance.md +23 -0
- package/agent-assets/skills/schedule/references/recurrence-rule.md +26 -16
- package/agent-assets/skills/scheduled-managed-task/SKILL.md +46 -46
- package/agent-assets/skills/today/SKILL.md +38 -81
- package/agent-assets/skills/today/references/agent-plan-lifecycle.md +9 -4
- package/agent-assets/skills/today/references/agent-plan-revision.md +28 -0
- package/agent-assets/skills/today/references/today-skeleton.md +66 -0
- package/agent-assets/skills/today/seeds/agent-notes-flavors.seed.json +1 -1
- package/agent-assets/skills/today/seeds/section-shape.seed.json +6 -6
- package/agent-assets/skills/user-interview/SKILL.md +15 -90
- package/agent-assets/skills/user-interview/references/op-briefing.md +1 -1
- package/agent-assets/skills/user-interview/references/op-dm-handler.md +88 -0
- package/agent-assets/skills/user-interview/references/op-morning.md +2 -2
- package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +1 -1
- package/agent-assets/skills/user-profile/SKILL.md +16 -26
- package/agent-assets/skills/user-profile/curation.json +3 -3
- package/agent-assets/skills/user-profile/references/character-preferences.md +3 -3
- package/agent-assets/skills/wiki/wiki-ask/SKILL.md +1 -1
- package/agent-assets/skills/wiki/wiki-compile/SKILL.md +5 -4
- package/agent-assets/skills/wiki/wiki-connect/SKILL.md +32 -5
- package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +6 -50
- package/agent-assets/skills/wiki/wiki-ingest/references/curl-errors.md +58 -0
- package/agent-assets/skills/wiki/wiki-lint/SKILL.md +20 -14
- package/agent-assets/skills/wiki/wiki-trace/SKILL.md +10 -5
- package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +2 -0
- package/agent-assets/system-prompts/routine-research-cluster-update.md +71 -0
- package/agent-assets/task-flows/_partials/feedback-capture.md +30 -0
- package/agent-assets/task-flows/_partials/notion-acquire.notion.md +47 -21
- package/agent-assets/task-flows/background_task.md +81 -0
- package/agent-assets/task-flows/git.local_ahead.stale.md +1 -1
- package/agent-assets/task-flows/git.push.detected.md +1 -1
- package/agent-assets/task-flows/git.tag.created.md +1 -1
- package/agent-assets/task-flows/github.assigned.md +1 -1
- package/agent-assets/task-flows/github.pull_request.review_requested.md +2 -2
- package/agent-assets/task-flows/github.security_alert.md +1 -1
- package/agent-assets/task-flows/message.received.dm.md +11 -3
- package/agent-assets/task-flows/message.received.dm_first.md +8 -2
- package/agent-assets/task-flows/{routine.hourly_check.md → routine.activity_scan.md} +31 -23
- package/agent-assets/task-flows/{routine.hourly_check.triage.md → routine.activity_scan.triage.md} +3 -3
- package/agent-assets/task-flows/routine.evening_review.md +80 -0
- package/agent-assets/task-flows/routine.monthly_review.md +81 -8
- package/agent-assets/task-flows/routine.research_cluster_update.md +33 -19
- package/agent-assets/task-flows/routine.roadmap_refresh.md +2 -2
- package/agent-assets/task-flows/routine.today_refresh.md +1 -1
- package/agent-assets/task-flows/routine.weekly_review.md +124 -4
- package/agent-assets/task-flows/schedule.approaching.md +2 -2
- package/agent-assets/task-flows/scheduled.dm.md +77 -1
- package/agent-assets/task-flows/scheduled.task.md +7 -1
- package/agent-assets/task-flows/wiki.trace.md +1 -1
- package/agent-assets/templates/_manifest.json +2 -2
- package/agent-assets/templates/knowledge/dossiers/_index.md +1 -1
- package/agent-assets/templates/knowledge/dossiers/{hourly.md → activity-scan.md} +1 -1
- package/agent-assets/templates/policies/journal-format.md +1 -1
- package/agent-assets/templates/policies/mcp.md +1 -1
- package/agent-assets/templates/policies/routines/_index.md +1 -1
- package/agent-assets/templates/policies/routines/{hourly.md → activity-scan.md} +5 -5
- package/bin/aitne.mjs +45 -11
- package/package.json +6 -5
- package/scripts/commands/doctor.mjs +11 -2
- package/scripts/lib/process-identity.d.mts +46 -0
- package/scripts/lib/process-identity.mjs +193 -0
- package/scripts/lib/read-api-token.mjs +1 -1
- package/scripts/start.mjs +14 -4
- package/agent-assets/docs/features/routines/hourly-check.md +0 -205
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: user-interview
|
|
3
|
-
description:
|
|
3
|
+
description: Use during morning routine Step 7.5, DM replies, the morning briefing, and the evening sweep to manage the profile-interview queue at state/profile-questions.md — pick a latent question, weave it into a natural reply, tick when answered, fallback-promote stale rows.
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash(curl *)
|
|
6
6
|
- Read
|
|
@@ -94,7 +94,7 @@ Before scheduling or asking, every callsite SHOULD verify the target
|
|
|
94
94
|
slot is genuinely empty:
|
|
95
95
|
|
|
96
96
|
```bash
|
|
97
|
-
curl -s "http://localhost:8321/api/profile-questions/slot-filled?path=
|
|
97
|
+
curl -s "http://localhost:8321/api/profile-questions/slot-filled?path=identity/profile.md§ion=Identity&anchor=Name"
|
|
98
98
|
# → {"filled":true|false,"sectionPresent":true|false,"fileExists":true|false,...}
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -109,59 +109,16 @@ the op-morning reference below.
|
|
|
109
109
|
|
|
110
110
|
{{> ref:op-morning }}
|
|
111
111
|
|
|
112
|
-
##
|
|
112
|
+
## Operations 2 & 4 — DM-handler weave and answer capture
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
`message.received.dm.md` /
|
|
116
|
-
composing the reply
|
|
114
|
+
DM-handler-only. Operation 2 (latent opportunity check) runs AFTER the
|
|
115
|
+
standard "Capture user info" block in `message.received.dm.md` /
|
|
116
|
+
`message.received.dm_first.md`, BEFORE composing the reply; Operation 4
|
|
117
|
+
(answer capture) runs after Operation 2's opportunity check. The
|
|
118
|
+
slot-filled pre-check, naturalness rules, two PATCHes, and the "one DM =
|
|
119
|
+
one tick" rationale are in the op-dm-handler reference below.
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
1. GET agent/profile-questions.md ## In Progress.
|
|
120
|
-
2. If no entry has state=latent, skip — return to the normal reply path.
|
|
121
|
-
2.5 Slot-filled pre-check (MANDATORY before any weaving decision).
|
|
122
|
-
GET /api/profile-questions/slot-filled?path=<target>§ion=<section?>&anchor=<anchor?>
|
|
123
|
-
for the latent row's target. If `filled: true`, the slot was filled
|
|
124
|
-
between morning routine and now (the user may have volunteered the
|
|
125
|
-
answer in a previous DM, or the sweep that runs at 17:50 hasn't
|
|
126
|
-
caught up yet). Resolve the row instead of weaving:
|
|
127
|
-
- Tick the matching ## Pending row [ ] → [x] (read-rebuild + replace).
|
|
128
|
-
- Remove the entry from ## In Progress.
|
|
129
|
-
- Append `- [x] <today> → <id> (reconciled:opportunity)` to ## Answered.
|
|
130
|
-
- Remove the matching `Profile question (latent): <id>` line from
|
|
131
|
-
today.md ## Agent Notes.
|
|
132
|
-
Return to the normal reply path — DO NOT weave a question. The user
|
|
133
|
-
has effectively already answered it.
|
|
134
|
-
3. Otherwise (slot still empty), judge whether the inbound DM is a
|
|
135
|
-
natural moment to ask the question. The criteria:
|
|
136
|
-
- Topic match. The user's message touches the question's domain
|
|
137
|
-
(work questions when the user mentions a meeting, code, deadline;
|
|
138
|
-
personal questions when the user discusses lifestyle, hobbies,
|
|
139
|
-
weekend plans; identity / location questions when the user makes
|
|
140
|
-
a general greeting on day 1 or asks for time/weather).
|
|
141
|
-
- Length appropriateness. Your reply will be more than a one-liner;
|
|
142
|
-
there is room to weave a question without making the message look
|
|
143
|
-
forced.
|
|
144
|
-
- Mood appropriateness. The user is not venting / in crisis / asking
|
|
145
|
-
a single short factual question.
|
|
146
|
-
4. If yes:
|
|
147
|
-
a. Compose the reply with the question woven in NATURALLY. Do NOT
|
|
148
|
-
make a separate paragraph or "By the way, …" preamble. The
|
|
149
|
-
question should feel like a side comment, not an interview cue.
|
|
150
|
-
b. After the reply is ready (final assistant text already includes
|
|
151
|
-
the question), issue **two PATCH replaces** (separate calls —
|
|
152
|
-
they target different files):
|
|
153
|
-
- `PATCH /api/context/state/profile-questions` section=in_progress
|
|
154
|
-
— flip the entry to
|
|
155
|
-
`state=asked :: since=<unchanged> :: asked_at=<current_time>`
|
|
156
|
-
(preserve the original `since=` date).
|
|
157
|
-
- `PATCH /api/context/state/today` section=agent_notes — replace the
|
|
158
|
-
parenthetical from `(latent)` to `(asked HH:MM)` and append
|
|
159
|
-
`(asked HH:MM)` to the same line; preserve every other Agent
|
|
160
|
-
Notes line byte-for-byte.
|
|
161
|
-
5. If no, leave the latent entry untouched. Return to the normal reply
|
|
162
|
-
path. The opportunity will come (or the evening sweep will eventually
|
|
163
|
-
promote to a fallback scheduled DM if it doesn't).
|
|
164
|
-
```
|
|
121
|
+
{{> ref:op-dm-handler }}
|
|
165
122
|
|
|
166
123
|
## Operation 3 — Latent piggyback (morning briefing composition)
|
|
167
124
|
|
|
@@ -172,35 +129,6 @@ op-briefing reference below.
|
|
|
172
129
|
|
|
173
130
|
{{> ref:op-briefing }}
|
|
174
131
|
|
|
175
|
-
## Operation 4 — Capture the answer (DM handler queue reconcile)
|
|
176
|
-
|
|
177
|
-
Run this AFTER "Capture user info" and Operation 2's opportunity check,
|
|
178
|
-
BEFORE composing the reply text.
|
|
179
|
-
|
|
180
|
-
```
|
|
181
|
-
1. GET agent/profile-questions.md ## In Progress.
|
|
182
|
-
2. If an entry has state=asked AND (now − asked_at) < 24h:
|
|
183
|
-
a. Tick the matching ## Pending row [ ] → [x] via PATCH replace
|
|
184
|
-
(read-rebuild full Pending body, change just that one line).
|
|
185
|
-
b. Remove the entry from ## In Progress (PATCH replace).
|
|
186
|
-
c. Append `- [x] <today> → <id> (DM)` to ## Answered.
|
|
187
|
-
d. Remove the matching today.md ## Agent Notes line — match by
|
|
188
|
-
the `Profile question (` prefix and the `: <id>` id segment;
|
|
189
|
-
works for both `(asked HH:MM)` and `(latent)` parenthetical
|
|
190
|
-
states (PATCH replace, read-rebuild — preserve every other line
|
|
191
|
-
byte-for-byte). Without this the line lingers in today.md
|
|
192
|
-
until tomorrow's PUT-replace and confuses the user.
|
|
193
|
-
3. If state=latent or state=scheduled, leave the entry alone — this
|
|
194
|
-
inbound DM is by definition unrelated to a question the user has
|
|
195
|
-
not been asked.
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
The "one DM after fire = one tick" rule is intentional. Trying to detect
|
|
199
|
-
"did the user ACTUALLY answer?" is unreliable and would re-ask forever
|
|
200
|
-
on partial answers. The 7-day `last_attempted` cooldown means an
|
|
201
|
-
unresolved fact will surface again later through the natural-volunteering
|
|
202
|
-
path or the next opportunity.
|
|
203
|
-
|
|
204
132
|
{{> ref:sweep-and-fallback }}
|
|
205
133
|
|
|
206
134
|
## Today.md surfacing — Agent Notes flavor
|
|
@@ -258,20 +186,17 @@ those bullets and the system degrades to Layer-4-only protection
|
|
|
258
186
|
curl -s http://localhost:8321/api/context/state/profile-questions
|
|
259
187
|
|
|
260
188
|
# Slot-filled probe
|
|
261
|
-
curl -s "http://localhost:8321/api/profile-questions/slot-filled?path=
|
|
189
|
+
curl -s "http://localhost:8321/api/profile-questions/slot-filled?path=identity/profile.md§ion=Identity&anchor=Name"
|
|
262
190
|
|
|
263
191
|
# Section-level edit (queue file uses the standard context API)
|
|
264
192
|
curl -s -X PATCH http://localhost:8321/api/context/state/profile-questions \
|
|
265
193
|
-H 'Content-Type: application/json' \
|
|
266
194
|
-d '{"section": "in_progress", "mode": "replace", "content": "- name :: state=latent"}'
|
|
267
195
|
|
|
268
|
-
# Fallback DM scheduling (Operation 5B only)
|
|
269
|
-
#
|
|
270
|
-
#
|
|
271
|
-
# `profile_interview:<id>` prefix triggers
|
|
272
|
-
curl -s -X POST http://localhost:8321/api/schedule \
|
|
273
|
-
-H 'Content-Type: application/json' \
|
|
274
|
-
-d '{"time":"<ISO>","taskType":"dm_session","prompt":"profile_interview:<id> — run the scheduled.dm ## Profile interview sub-flow (Operation 6): fire-time slot-filled abort check, then compose one short natural DM around <hint>.","description":"profile_interview:<id> — <hint>","tier":"medium","taskContext":{"scheduledBy":"user_profile_sweep_fallback","queueId":"<id>","importance":"low"}}'
|
|
196
|
+
# Fallback DM scheduling (Operation 5B only) — see the canonical
|
|
197
|
+
# POST /api/schedule example in references/sweep-and-fallback.md Op 5B.
|
|
198
|
+
# `prompt` is REQUIRED (the wake-up session has NO memory); `description`
|
|
199
|
+
# carries the `profile_interview:<id>` prefix that triggers Operation 6.
|
|
275
200
|
```
|
|
276
201
|
|
|
277
202
|
The PATCH `section` argument is snake_case of the heading: `pending`,
|
|
@@ -12,7 +12,7 @@ composes; it is one of the few naturally-occurring opportunities to
|
|
|
12
12
|
slip in a question without surfacing a cold standalone DM.
|
|
13
13
|
|
|
14
14
|
```
|
|
15
|
-
1. GET
|
|
15
|
+
1. GET state/profile-questions.md ## In Progress.
|
|
16
16
|
2. If no entry has state=latent, skip.
|
|
17
17
|
2.5 Slot-filled pre-check (MANDATORY). Same recipe as Operation 2
|
|
18
18
|
step 2.5: GET /api/profile-questions/slot-filled. If
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: op-dm-handler
|
|
4
|
+
description: Operations 2 and 4 — the DM-handler latent-opportunity weave and the answer-capture queue reconcile. Slot-filled pre-check, naturalness rules, two PATCHes, the "one DM = one tick" rationale.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Operation 2 — Latent opportunity check (DM handler)
|
|
8
|
+
|
|
9
|
+
Run this AFTER the standard "Capture user info" block in
|
|
10
|
+
`message.received.dm.md` / `message.received.dm_first.md`, BEFORE
|
|
11
|
+
composing the reply.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
1. GET state/profile-questions.md ## In Progress.
|
|
15
|
+
2. If no entry has state=latent, skip — return to the normal reply path.
|
|
16
|
+
2.5 Slot-filled pre-check (MANDATORY before any weaving decision).
|
|
17
|
+
GET /api/profile-questions/slot-filled?path=<target>§ion=<section?>&anchor=<anchor?>
|
|
18
|
+
for the latent row's target. If `filled: true`, the slot was filled
|
|
19
|
+
between morning routine and now (the user may have volunteered the
|
|
20
|
+
answer in a previous DM, or the sweep that runs at 17:50 hasn't
|
|
21
|
+
caught up yet). Resolve the row instead of weaving:
|
|
22
|
+
- Tick the matching ## Pending row [ ] → [x] (read-rebuild + replace).
|
|
23
|
+
- Remove the entry from ## In Progress.
|
|
24
|
+
- Append `- [x] <today> → <id> (reconciled:opportunity)` to ## Answered.
|
|
25
|
+
- Remove the matching `Profile question (latent): <id>` line from
|
|
26
|
+
today.md ## Agent Notes.
|
|
27
|
+
Return to the normal reply path — DO NOT weave a question. The user
|
|
28
|
+
has effectively already answered it.
|
|
29
|
+
3. Otherwise (slot still empty), judge whether the inbound DM is a
|
|
30
|
+
natural moment to ask the question. The criteria:
|
|
31
|
+
- Topic match. The user's message touches the question's domain
|
|
32
|
+
(work questions when the user mentions a meeting, code, deadline;
|
|
33
|
+
personal questions when the user discusses lifestyle, hobbies,
|
|
34
|
+
weekend plans; identity / location questions when the user makes
|
|
35
|
+
a general greeting on day 1 or asks for time/weather).
|
|
36
|
+
- Length appropriateness. Your reply will be more than a one-liner;
|
|
37
|
+
there is room to weave a question without making the message look
|
|
38
|
+
forced.
|
|
39
|
+
- Mood appropriateness. The user is not venting / in crisis / asking
|
|
40
|
+
a single short factual question.
|
|
41
|
+
4. If yes:
|
|
42
|
+
a. Compose the reply with the question woven in NATURALLY. Do NOT
|
|
43
|
+
make a separate paragraph or "By the way, …" preamble. The
|
|
44
|
+
question should feel like a side comment, not an interview cue.
|
|
45
|
+
b. After the reply is ready (final assistant text already includes
|
|
46
|
+
the question), issue **two PATCH replaces** (separate calls —
|
|
47
|
+
they target different files):
|
|
48
|
+
- `PATCH /api/context/state/profile-questions` section=in_progress
|
|
49
|
+
— flip the entry to
|
|
50
|
+
`state=asked :: since=<unchanged> :: asked_at=<current_time>`
|
|
51
|
+
(preserve the original `since=` date).
|
|
52
|
+
- `PATCH /api/context/state/today` section=agent_notes — replace the
|
|
53
|
+
parenthetical from `(latent)` to `(asked HH:MM)` and append
|
|
54
|
+
`(asked HH:MM)` to the same line; preserve every other Agent
|
|
55
|
+
Notes line byte-for-byte.
|
|
56
|
+
5. If no, leave the latent entry untouched. Return to the normal reply
|
|
57
|
+
path. The opportunity will come (or the evening sweep will eventually
|
|
58
|
+
promote to a fallback scheduled DM if it doesn't).
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
# Operation 4 — Capture the answer (DM handler queue reconcile)
|
|
62
|
+
|
|
63
|
+
Run this AFTER "Capture user info" and Operation 2's opportunity check,
|
|
64
|
+
BEFORE composing the reply text.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
1. GET state/profile-questions.md ## In Progress.
|
|
68
|
+
2. If an entry has state=asked AND (now − asked_at) < 24h:
|
|
69
|
+
a. Tick the matching ## Pending row [ ] → [x] via PATCH replace
|
|
70
|
+
(read-rebuild full Pending body, change just that one line).
|
|
71
|
+
b. Remove the entry from ## In Progress (PATCH replace).
|
|
72
|
+
c. Append `- [x] <today> → <id> (DM)` to ## Answered.
|
|
73
|
+
d. Remove the matching today.md ## Agent Notes line — match by
|
|
74
|
+
the `Profile question (` prefix and the `: <id>` id segment;
|
|
75
|
+
works for both `(asked HH:MM)` and `(latent)` parenthetical
|
|
76
|
+
states (PATCH replace, read-rebuild — preserve every other line
|
|
77
|
+
byte-for-byte). Without this the line lingers in today.md
|
|
78
|
+
until tomorrow's PUT-replace and confuses the user.
|
|
79
|
+
3. If state=latent or state=scheduled, leave the entry alone — this
|
|
80
|
+
inbound DM is by definition unrelated to a question the user has
|
|
81
|
+
not been asked.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The "one DM after fire = one tick" rule is intentional. Trying to detect
|
|
85
|
+
"did the user ACTUALLY answer?" is unreliable and would re-ask forever
|
|
86
|
+
on partial answers. The 7-day `last_attempted` cooldown means an
|
|
87
|
+
unresolved fact will surface again later through the natural-volunteering
|
|
88
|
+
path or the next opportunity.
|
|
@@ -8,11 +8,11 @@ description: Operation 1 — pick a profile-interview question during Morning Ro
|
|
|
8
8
|
|
|
9
9
|
Run this only inside `routine.morning_routine` (and its split
|
|
10
10
|
variants `routine.morning_routine_today`). DM handlers, scheduled.dm
|
|
11
|
-
briefings, and
|
|
11
|
+
briefings, and activity scans do not run this operation — they use
|
|
12
12
|
Operation 2 / 3 / 4 instead.
|
|
13
13
|
|
|
14
14
|
```
|
|
15
|
-
1. GET
|
|
15
|
+
1. GET state/profile-questions.md.
|
|
16
16
|
2. Skip the entire step if any of:
|
|
17
17
|
- ## In Progress is non-empty.
|
|
18
18
|
- ## Pending is empty.
|
|
@@ -79,7 +79,7 @@ Triggered when a `dm_session` task description starts with
|
|
|
79
79
|
5B) where 3 days passed without a natural opportunity.
|
|
80
80
|
|
|
81
81
|
```
|
|
82
|
-
1. Fire-time abort. GET
|
|
82
|
+
1. Fire-time abort. GET state/profile-questions.md and the row's
|
|
83
83
|
target_path. Call /api/profile-questions/slot-filled. If the slot is
|
|
84
84
|
filled per the heuristic OR the matching Pending row is no longer
|
|
85
85
|
`[ ]`:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: user-profile
|
|
3
|
-
description: Record user facts — identity, people, work, expertise, habits, goals, tendencies. Top-level →
|
|
3
|
+
description: Record user facts — identity, people, work, expertise, habits, goals, tendencies. Top-level → identity/profile.md; detail → identity/<topic>.md. Tone/style/voice/language are NOT facts — route to PATCH /api/config/character. Same turn as reply. Skip dupes. Never notify.
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash(curl *)
|
|
6
6
|
- Read
|
|
@@ -8,11 +8,11 @@ allowed-tools:
|
|
|
8
8
|
|
|
9
9
|
# User Profile Update Guide
|
|
10
10
|
|
|
11
|
-
Output language: `identity/profile.md` and `
|
|
11
|
+
Output language: `identity/profile.md` and `identity/*.md` are Policy B — see `<output_language_policy>`. Template H2 headers stay English skeleton; the facts under them are in `<settings primary_language>`. Preserve user-customized headers verbatim.
|
|
12
12
|
|
|
13
13
|
`identity/profile.md` stores the user's identity, preferences, and learned behavioral patterns. It is injected into every agent session via `<user>` tags — keep it concise (target: under ~600 tokens total).
|
|
14
14
|
|
|
15
|
-
Detailed, dictionary-like background belongs under `
|
|
15
|
+
Detailed, dictionary-like background belongs under `identity/*.md`. Read `identity/_index.md` first, then fetch only the topic file you need.
|
|
16
16
|
|
|
17
17
|
## When to Update
|
|
18
18
|
|
|
@@ -37,34 +37,24 @@ Detailed, dictionary-like background belongs under `user/*.md`. Read `identity/_
|
|
|
37
37
|
- "user has been unusually curt over the last week" — a pattern inferred across multiple turns with no single user statement. Written to `profile.md ## Learned Context` by Evening Review Step 3a only; the DM handler and sweep do not write inferred patterns.
|
|
38
38
|
- "my sister just had a baby" → `identity/people.md ## Family`. If the section doesn't exist yet (fresh topic file with only the H1), the PATCH returns `section_not_found` — retry with `mode: "append_to_file"` and include `"\n## Family\n- <bullet>"` in `content`. The next write to that section succeeds normally.
|
|
39
39
|
|
|
40
|
-
The decision rule (profile.md vs `
|
|
40
|
+
The decision rule (profile.md vs `identity/<topic>.md` tie-breakers, `section_not_found` → `append_to_file` first-write fallback, and the read-before-write `curl` recipe) is documented in full in this skill — see §"Section ownership", §"File schema", and §"Worked example" below.
|
|
41
41
|
|
|
42
42
|
## Section ownership
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|---|---|---|
|
|
46
|
-
| Identity | Explicit statement | DM handler, sweep |
|
|
47
|
-
| Work Pattern | Explicit statement | DM handler, sweep |
|
|
48
|
-
| Platforms | Explicit statement | Setup, explicit change |
|
|
49
|
-
| Expertise | Explicit statement (summary) | DM handler, sweep |
|
|
50
|
-
| Notification Preferences | Explicit statement | DM handler, sweep |
|
|
51
|
-
| Learned Context | Stated preferences (DM) + Raw Signals graduation (evening) | DM handler, sweep, Evening Review 3a |
|
|
52
|
-
| Raw Signals | Behavioral detection | SignalDetector only |
|
|
53
|
-
| `user/<topic>.md` (people / work / expertise / personal / goals) | Any detail-heavy fact per the capture decision rule in the DM task-flow | DM handler, `routine.user_profile_sweep` |
|
|
44
|
+
Per-section trigger → destination → writer is in the auto-curated **When-to-update routing** block below. Writer notes layered on top:
|
|
54
45
|
|
|
55
|
-
"DM handler"
|
|
46
|
+
- "DM handler" covers both `message.received.dm` and `message.received.dm_first`. "Sweep" is `routine.user_profile_sweep` (fires 03:50 and 17:50 local; see its task-flow). Evening Review Step 3a is an additional writer to Learned Context only, synthesizing entries from Raw Signals graduation.
|
|
47
|
+
- **Do not write to Raw Signals from other events — that section is `SignalDetector`'s alone.**
|
|
56
48
|
|
|
57
|
-
|
|
49
|
+
## identity/profile.md vs identity/<topic>
|
|
58
50
|
|
|
59
|
-
|
|
51
|
+
**identity/profile.md** — injected every session: Identity, Work Pattern, Platforms, Expertise summary, Notification Preferences, Learned Context.
|
|
60
52
|
|
|
61
|
-
**
|
|
62
|
-
|
|
63
|
-
**user/*.md** — dictionary-like (`people` | `work` | `expertise` | `goals` | `personal`), too detailed for every session. Read `_index.md` first → fetch only the relevant topic.
|
|
53
|
+
**identity/*.md** — dictionary-like (`people` | `work` | `expertise` | `goals` | `personal`), too detailed for every session. Read `identity/_index.md` first → fetch only the relevant topic. Per-topic ownership is in the auto-curated **Knowledge map** block below.
|
|
64
54
|
|
|
65
55
|
## File schema
|
|
66
56
|
|
|
67
|
-
All `
|
|
57
|
+
All `identity/*.md` files must keep YAML frontmatter with `type: user`,
|
|
68
58
|
`owner: shared`, and `updated: YYYY-MM-DD`, followed by an H1. When using
|
|
69
59
|
section-level PATCH, preserve the existing frontmatter. When doing a
|
|
70
60
|
full-file PUT, update `updated` to today's date.
|
|
@@ -106,7 +96,7 @@ If the user says "I don't want work notifications on weekends", paraphrase into
|
|
|
106
96
|
preferences are NOT profile content.** Route them to the `character`
|
|
107
97
|
runtime-config field via `PATCH /api/config/character` (narrow
|
|
108
98
|
endpoint, 1000-char cap, read-before-write). Never write tone /
|
|
109
|
-
style preferences into `identity/profile.md` or any `
|
|
99
|
+
style preferences into `identity/profile.md` or any `identity/*.md`.
|
|
110
100
|
|
|
111
101
|
Full recipe — triggers, merge rules, endpoint note, cap-handling, and
|
|
112
102
|
where the value ends up — is in the character-preferences reference
|
|
@@ -120,7 +110,7 @@ See _safety.md "Common Patterns" for the general rule. Section name in PATCH is
|
|
|
120
110
|
|
|
121
111
|
### Worked example
|
|
122
112
|
|
|
123
|
-
User: `"I want to read 20 books this year."` → GET
|
|
113
|
+
User: `"I want to read 20 books this year."` → GET identity/profile.md (or topic file), merge new bullet into the right section. For a top-level goal summary bullet:
|
|
124
114
|
```bash
|
|
125
115
|
curl -s -X PATCH http://localhost:8321/api/context/identity/profile \
|
|
126
116
|
-H 'Content-Type: application/json' \
|
|
@@ -130,7 +120,7 @@ For a full-section replace, GET first, merge with existing bullets, then PATCH w
|
|
|
130
120
|
|
|
131
121
|
**WRONG** (erases existing bullets): `curl -s -X PATCH ... -d '{"section": "learned_context", "mode": "replace", "content": "- [2026-04-23] Reading goal: ..."}'` when the section already held other bullets.
|
|
132
122
|
|
|
133
|
-
For writes to `
|
|
123
|
+
For writes to `identity/<topic>.md` (people / work / expertise / personal / goals), the same decision rule applies — §"Routing edge cases" above documents the `section_not_found` → `append_to_file` first-write fallback (with a worked `curl` example against `identity/people.md`). The read-before-write rule applies identically when merging into an existing `identity/<topic>.md` section.
|
|
134
124
|
|
|
135
125
|
## Learned Context entry format
|
|
136
126
|
|
|
@@ -150,7 +140,7 @@ Review can prune entries older than 30 days:
|
|
|
150
140
|
- **Silent updates.** Never notify the user about profile changes.
|
|
151
141
|
- **Keep concise.** 2–5 bullets per section max. Consolidate similar bullets.
|
|
152
142
|
- **No duplicates.** Scan before adding. Prefer refining an existing bullet.
|
|
153
|
-
- **Total budget ~600 tokens** for
|
|
143
|
+
- **Total budget ~600 tokens** for identity/profile.md. Consolidate aggressively.
|
|
154
144
|
- **Don't write verbatim user messages.** Paraphrase into stable preference statements.
|
|
155
145
|
|
|
156
146
|
## Initial Setup
|
|
@@ -166,7 +156,7 @@ Populate `identity/profile.md` (Identity, Work Pattern, Platforms, Expertise sum
|
|
|
166
156
|
The generic GET / PATCH surface (modes, fields, error envelopes) is
|
|
167
157
|
documented in the **context** skill `references/api.md`. user-profile
|
|
168
158
|
writes target the two paths `/api/context/identity/profile` (the injected
|
|
169
|
-
summary file) and `/api/context/
|
|
159
|
+
summary file) and `/api/context/identity/:topic` (one of `people` /
|
|
170
160
|
`work` / `expertise` / `personal` / `goals`).
|
|
171
161
|
|
|
172
162
|
Two user-profile-specific notes layered on top of the generic surface:
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"kind": "knowledge_layout",
|
|
7
7
|
"anchor": "<!-- CURATION:knowledge_layout id=\"topic-files\" -->",
|
|
8
8
|
"human_label": "Topic file layout",
|
|
9
|
-
"description": "Which
|
|
10
|
-
"scope_paths": ["identity/profile.md", "
|
|
9
|
+
"description": "Which identity/* file owns which kind of fact",
|
|
10
|
+
"scope_paths": ["identity/profile.md", "identity/*.md"]
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"id": "routing-table",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"anchor": "<!-- CURATION:routing_table id=\"routing-table\" -->",
|
|
16
16
|
"human_label": "When-to-update routing rules",
|
|
17
17
|
"description": "Trigger phrases mapped to destination file, section, and write mode",
|
|
18
|
-
"scope_paths": ["
|
|
18
|
+
"scope_paths": ["identity/*.md"]
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"id": "learned-context-format",
|
|
@@ -10,7 +10,7 @@ description: Tone / style / voice / language preferences are agent directives
|
|
|
10
10
|
are NOT profile content** — they are agent directives, not user facts.
|
|
11
11
|
Route them to the `character` runtime-config field via `PATCH
|
|
12
12
|
/api/config/character` (see `docs/design/15-character.md`), never to
|
|
13
|
-
`identity/profile.md` or any `
|
|
13
|
+
`identity/profile.md` or any `identity/*.md`.
|
|
14
14
|
|
|
15
15
|
## Triggers
|
|
16
16
|
|
|
@@ -78,6 +78,6 @@ uniformly — no separate injection per backend.
|
|
|
78
78
|
## What does NOT belong here
|
|
79
79
|
|
|
80
80
|
Facts about the user — identity, role, expertise, hobbies, people,
|
|
81
|
-
goals — go to `identity/profile.md` or `
|
|
81
|
+
goals — go to `identity/profile.md` or `identity/<topic>.md`, not to
|
|
82
82
|
`character`. The split is: `character` says *how* the agent speaks;
|
|
83
|
-
`
|
|
83
|
+
`identity/*` says *who the user is*.
|
|
@@ -9,7 +9,7 @@ allowed-tools:
|
|
|
9
9
|
|
|
10
10
|
You run under process key `wiki.ask`.
|
|
11
11
|
|
|
12
|
-
Read `<wiki_command>` for the user's `question`. Search and read relevant `20_wiki/` notes first; read `10_raw/` only when the wiki notes need source verification.
|
|
12
|
+
Read `<wiki_command>` for the user's `question`. Search and read relevant `20_wiki/` notes first (see wiki-vault-rules for `/search` and `/index`); read `10_raw/` only when the wiki notes need source verification.
|
|
13
13
|
|
|
14
14
|
Write the answer to:
|
|
15
15
|
|
|
@@ -26,7 +26,7 @@ Therefore:
|
|
|
26
26
|
| Method | Path | Purpose |
|
|
27
27
|
|---|---|---|
|
|
28
28
|
| `GET` | `/api/wiki/{{workspace_name}}/index` | List every file in the workspace with `path`/`mtime`/`sizeBytes`. Primary enumeration tool. |
|
|
29
|
-
| `GET` | `/api/wiki/{{workspace_name}}/search?q=<query>` |
|
|
29
|
+
| `GET` | `/api/wiki/{{workspace_name}}/search?q=<query>` | Duplicate detection. Defaults to FTS5 token matching; append `&kind=grep` for literal substring matches. |
|
|
30
30
|
| `GET` | `/api/wiki/{{workspace_name}}/files/<path>` | Read raw notes, existing wiki notes, taxonomy, log. |
|
|
31
31
|
| `POST` | `/api/wiki/{{workspace_name}}/files/20_wiki/<slug>.md` | Create a new wiki note. |
|
|
32
32
|
| `POST` | `/api/wiki/{{workspace_name}}/files/20_wiki/<slug>.md` | Rewrite an existing wiki note — re-POST to the same path overwrites in place (a `.snapshots/` backup is taken first). |
|
|
@@ -93,7 +93,7 @@ Inside `<<'JSON'` (single-quoted marker) the body is verbatim — only JSON's ow
|
|
|
93
93
|
## Anti-patterns (silent denials — never claim success after these)
|
|
94
94
|
|
|
95
95
|
- `Write` / `Edit` tools — **stripped from the session allow-list** for every `wiki.*` process key. The SDK denies them silently under `dontAsk` ("Permission to use Write has been denied …"). There is no path-rewrite that makes them work; use the Wiki API via curl. The agent that hit "Write denied → reported failure" is the canonical failure mode this section exists to prevent.
|
|
96
|
-
- `Bash(find ...)`, `Bash(ls ...)`, `Bash(cat ...)`, `Bash(grep ...)`, `Bash(wc ...)`, and every other shell utility — silently denied. Only `Bash(curl *)` and `Bash(jq *)` are on the allow-list. Enumerate via `GET /api/wiki/<ws>/index`, not from disk.
|
|
96
|
+
- `Bash(find ...)`, `Bash(ls ...)`, `Bash(cat ...)`, `Bash(grep ...)`, `Bash(wc ...)`, and every other shell utility — silently denied. Only `Bash(curl *)` and `Bash(jq *)` are on the allow-list (`jq` runs standalone or as `curl … | jq`). Enumerate via `GET /api/wiki/<ws>/index`, not from disk.
|
|
97
97
|
- `echo '{...}' | curl ...`, `cat <<JSON | curl ... -d @- JSON`, `bash -c "curl ..."`, `( curl ... )`, `var=... curl ...`, `curl ... ; curl ...` — Bash command does not start with `curl`; silently denied. The reverse — `curl ... -d @- <<'JSON' … JSON` on the same line — DOES start with `curl` and IS allowed (the heredoc redirects into curl's stdin).
|
|
98
98
|
- `curl ... -d @/some/path` — `@<filepath>` is blocked by the security hook and the shim. The only acceptable `@…` value is the literal stdin marker `@-`.
|
|
99
99
|
- `curl http://example.com/...` (non-loopback) — only `http://localhost:8321/api/*` is permitted.
|
|
@@ -104,10 +104,11 @@ Inside `<<'JSON'` (single-quoted marker) the body is verbatim — only JSON's ow
|
|
|
104
104
|
|
|
105
105
|
| Status | Body code | Cause | Recovery |
|
|
106
106
|
|---|---|---|---|
|
|
107
|
-
| 400 | `
|
|
107
|
+
| 400 | `invalid_json_body` | JSON body did not parse (checked first, before Zod) | Switch to the heredoc shape if you were inline-escaping a multi-KB body. |
|
|
108
|
+
| 400 | `invalid_body` | Body parsed but `content` is not a string (Zod rejection) | Ensure `content` is a JSON string. |
|
|
108
109
|
| 400 | `invalid_path` / `invalid_layer` | Slug shape or layer prefix rejected | Path must be exactly `20_wiki/<slug>.md`. Slug matches `^[a-z0-9][a-z0-9-]*$`. |
|
|
109
110
|
| 403 | `missing_process_key` | Header missing | Add `-H 'x-process-key: wiki.compile'`. |
|
|
110
|
-
| 403 | `wiki_write_denied` |
|
|
111
|
+
| 403 | `wiki_write_denied` | A non-`wiki.compile` key targeting the `20_wiki` layer. `_index.md` is a normal `20_wiki` file; `log.md` is its own append-only layer (PATCH-only). | Fix the target path. Use `wiki-graduate` for inbox-to-wiki promotion (same process key, different source layer). |
|
|
111
112
|
| 409 | `append_only` | POST to an existing `10_raw/` file or `log.md` (those two layers are create-only). Does NOT apply to `20_wiki/<slug>.md` — re-POSTing there overwrites in place. | For `log.md` use `PATCH mode: "append"`. `10_raw/` files cannot be overwritten by design. |
|
|
112
113
|
| 413 | — | Body exceeds 512 KB | Split the note or trim verbatim extracts. |
|
|
113
114
|
| 5xx | — | Daemon error | Append a failure line to `log.md`, classify the run as partial, do not retry inside the same turn. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wiki-connect
|
|
3
|
-
description:
|
|
3
|
+
description: Bridge two wiki domains on /connect A B — surface shared terms, common references, and structural analogies, then write a cited connection report to 30_outputs/. Runs under process key wiki.connect.
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash(curl *)
|
|
6
6
|
---
|
|
@@ -11,6 +11,16 @@ You run under process key `wiki.connect`.
|
|
|
11
11
|
|
|
12
12
|
Read `<wiki_command>` for the two topics — fields `topic_a` and `topic_b`. Your job is to find genuine bridges between the two domains using only what the wiki contains. Speculative analogies are out of scope; if there is no real overlap, say so plainly.
|
|
13
13
|
|
|
14
|
+
## Endpoints
|
|
15
|
+
|
|
16
|
+
Every request includes `-H 'x-process-key: wiki.connect'`. Body shapes:
|
|
17
|
+
|
|
18
|
+
| Method | Path | Body |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `GET` | `/api/wiki/{{workspace_name}}/search?q=<topic>` | — |
|
|
21
|
+
| `POST` | `/api/wiki/{{workspace_name}}/files/30_outputs/<file>.md` | `{"content":"<report-md>"}` |
|
|
22
|
+
| `PATCH` | `/api/wiki/{{workspace_name}}/files/log.md` | `{"mode":"append","content":"<line>\n"}` |
|
|
23
|
+
|
|
14
24
|
## Method
|
|
15
25
|
|
|
16
26
|
1. Search each topic independently:
|
|
@@ -30,11 +40,18 @@ Read `<wiki_command>` for the two topics — fields `topic_a` and `topic_b`. You
|
|
|
30
40
|
|
|
31
41
|
Write exactly one report:
|
|
32
42
|
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
```bash
|
|
44
|
+
curl http://localhost:8321/api/wiki/{{workspace_name}}/files/30_outputs/<YYYY-MM-DD>-connect-<slug>.md \
|
|
45
|
+
-X POST \
|
|
46
|
+
-H 'content-type: application/json' \
|
|
47
|
+
-H 'x-process-key: wiki.connect' \
|
|
48
|
+
-d @- <<'JSON'
|
|
49
|
+
{"content":"<report-md>"}
|
|
50
|
+
JSON
|
|
36
51
|
```
|
|
37
52
|
|
|
53
|
+
The body is `{"content":"<report-md>"}` — `wikiFilePostSchema` requires the `content` field. An empty body returns `400 invalid_json_body`; valid JSON missing `content` returns `400 invalid_body`. Always send the `content` field.
|
|
54
|
+
|
|
38
55
|
- `<YYYY-MM-DD>` is today's date.
|
|
39
56
|
- `<slug>` is `<slug-a>--<slug-b>` using the canonical slugs from `90_meta/taxonomy.md` when available, kebab-cased and joined by a double hyphen.
|
|
40
57
|
|
|
@@ -59,7 +76,17 @@ Report shape:
|
|
|
59
76
|
- proposed wiki slug, one-sentence rationale, suggested anchor notes
|
|
60
77
|
```
|
|
61
78
|
|
|
62
|
-
If no genuine bridges exist, write the report anyway with empty sections marked `_(none)_` and a `## Summary` that names that clearly — a "no connection" finding is still useful to the owner.
|
|
79
|
+
If no genuine bridges exist, write the report anyway with empty sections marked `_(none)_` and a `## Summary` that names that clearly — a "no connection" finding is still useful to the owner.
|
|
80
|
+
|
|
81
|
+
Then append a one-line `log.md` entry referencing the output filename and both topics. `log.md` is append-only — POST to an existing `log.md` returns `409 'Use PATCH to append log.md'`. Use PATCH:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
curl http://localhost:8321/api/wiki/{{workspace_name}}/files/log.md \
|
|
85
|
+
-X PATCH \
|
|
86
|
+
-H 'content-type: application/json' \
|
|
87
|
+
-H 'x-process-key: wiki.connect' \
|
|
88
|
+
-d '{"mode":"append","content":"[<ISO>] wiki.connect: <topic_a> ↔ <topic_b> → 30_outputs/<file>.md\n"}'
|
|
89
|
+
```
|
|
63
90
|
|
|
64
91
|
### Completion message (mandatory)
|
|
65
92
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wiki-ingest
|
|
3
|
-
description: Load for wiki.ingest_url.
|
|
3
|
+
description: Load for wiki.ingest_url. Use when ingesting one shared URL/article into the wiki raw layer (10_raw) via the daemon Wiki API. Carries the canonical curl invocation, the path / response contract, and the strict success-verification rule.
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- WebFetch
|
|
6
6
|
- Bash(curl *)
|
|
@@ -47,7 +47,7 @@ Do NOT call any other daemon endpoint. The daemon has **no** `/api/send-message`
|
|
|
47
47
|
- `## Source extracts` — verbatim or close-paraphrase quotes.
|
|
48
48
|
- `## Open questions` — anything you could not verify from the page.
|
|
49
49
|
4. **POST the note** via the canonical curl shape (next section). Inspect the response body.
|
|
50
|
-
5. **Verify**: the response body must be exactly `{"ok":true,"path":"10_raw/<slug>.md"}`. If anything else (4xx/5xx, missing `ok`, wrong path, no body, `PA_API_ERROR …` on stderr), treat it as failure. Follow the error table
|
|
50
|
+
5. **Verify**: the response body must be exactly `{"ok":true,"path":"10_raw/<slug>.md"}`. If anything else (4xx/5xx, missing `ok`, wrong path, no body, `PA_API_ERROR …` on stderr), treat it as failure. Follow the error->recovery table in "Curl mechanics" or PATCH `log.md` and emit the failure DM.
|
|
51
51
|
6. **Emit the completion DM** (last section). Success or failure, exactly one line, no extra prose.
|
|
52
52
|
|
|
53
53
|
## Path shape — exact, no nesting
|
|
@@ -119,59 +119,15 @@ curl http://localhost:8321/api/wiki/{{workspace_name}}/files/log.md \
|
|
|
119
119
|
-d '{"mode":"append","content":"[2026-05-13T05:08:00Z] wiki.ingest_url failed https://news.example.com/path/123 — fetch returned 403\n"}'
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
##
|
|
122
|
+
## Curl mechanics, anti-patterns, and error recovery
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
Body-quoting rules, the silent-denial anti-patterns, and the per-status error->recovery table live on demand:
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
| Need in `content` | Write in shell-arg |
|
|
129
|
-
|---|---|
|
|
130
|
-
| `"` | `\"` |
|
|
131
|
-
| `\` | `\\` |
|
|
132
|
-
| newline | `\n` |
|
|
133
|
-
| `'` | `'\''` (close-escape-reopen), or substitute `’` (U+2019) |
|
|
134
|
-
| `$`, backticks | leave as-is (single quotes suppress expansion) |
|
|
135
|
-
|
|
136
|
-
Keep the note compact — well under 512 KB. Curate 5-20 KB of the most informative extracts rather than dumping the whole page.
|
|
137
|
-
|
|
138
|
-
## Anti-patterns (silent denials / 4xx — never claim success after these)
|
|
139
|
-
|
|
140
|
-
- `WebFetch http://localhost:8321/...` — Claude WebFetch refuses loopback. Use curl.
|
|
141
|
-
- `echo '{...}' | curl ...`, `cat <<JSON | curl ... -d @- JSON ; …`, `bash -c "curl ..."` — Bash command does not start with `curl`; denied silently under `dontAsk`. (Heredoc redirected directly into curl on the same line — `curl ... -d @- <<'JSON' … JSON` — IS allowed because the command still starts with `curl`.)
|
|
142
|
-
- `curl ... -d @/tmp/body.json` — `@<path>` form is blocked by the security hook and by the shim.
|
|
143
|
-
- `curl http://example.com/...` (non-loopback) — security hook denies; only `http://localhost:8321/api/*` is permitted.
|
|
144
|
-
- POST to a non-existent path like `/api/send-message`, `/api/whatsapp/send`, `/api/notify-user`, `/api/dm`. These are NOT daemon routes; calls return 401/404 and DO NOT notify anyone.
|
|
145
|
-
- POST/PATCH to `/api/wiki/.../10_raw/<slug>.md` a second time — raw is create-only; the second call returns 409 and **does NOT** modify the file.
|
|
146
|
-
- `Write` / `Edit` tools — stripped from the session allow-list for every `wiki.*` process key. The SDK denies them silently under `dontAsk` (you'll see "Permission to use Write has been denied …"). There is no path-rewrite that makes them work; use the Wiki API via curl. `Bash(find ...)`, `Bash(ls ...)`, `Bash(cat ...)` and other shell utilities are also denied — only `Bash(curl *)` and `Bash(jq *)` are on the allow-list.
|
|
147
|
-
|
|
148
|
-
## Troubleshooting
|
|
149
|
-
|
|
150
|
-
Every non-2xx response causes the curl shim to write one line to stderr:
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
PA_API_ERROR {"method":"POST","path":"/api/wiki/...","status":<n>,"bodyPreview":"<json error>"}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Read `status` + `bodyPreview` and react:
|
|
157
|
-
|
|
158
|
-
| Status | Body code | Cause | Recovery |
|
|
159
|
-
|---|---|---|---|
|
|
160
|
-
| 200 | (response is `{"ok":true,"path":...}`) | Success | Emit the success DM. |
|
|
161
|
-
| 200 | (response missing `ok` or `path`) | Should not happen — but if it does, treat as failure | Emit failure DM. |
|
|
162
|
-
| 400 | `invalid_body` | JSON body did not parse / `content` not a string | Re-emit the body. For inline `-d` check your single-quote / `\n` / `\"` escapes. If the body was `@-` literally, the heredoc was missed — switch to the heredoc shape (`-d @- <<'JSON' … JSON` on the same line as curl). |
|
|
163
|
-
| 400 | `invalid_path` / `invalid_layer` | Slug or layer rejected | Path must be **exactly** `10_raw/<slug>.md`, slug matching `^[a-z0-9][a-z0-9-]*$`. No nested folders. |
|
|
164
|
-
| 403 | `missing_process_key` | Header missing | Add `-H 'x-process-key: wiki.ingest_url'` and retry. |
|
|
165
|
-
| 403 | `raw_write_denied` | Process key isn't `wiki.ingest_url` | Configuration error; emit failure DM, do not retry. |
|
|
166
|
-
| 409 | `append_only` | Slug already exists in `10_raw/` | Suffix the slug (`<slug>-2`), retry the POST **once**. If `-2` also 409, PATCH log.md and emit failure DM — do not loop further. |
|
|
167
|
-
| 413 | (body too large) | Article > 512 KB | Trim verbatim extracts; keep essentials. |
|
|
168
|
-
| 5xx | — | Daemon error | PATCH log.md and emit failure DM. Do not retry — the daemon will not heal mid-turn. |
|
|
169
|
-
|
|
170
|
-
If the Bash call returns to the prompt with **no stdout body and no `PA_API_ERROR`**, your command did not start with literal `curl` and was silently denied. Rewrite it as a flat, single-line curl invocation following the canonical shape above.
|
|
126
|
+
{{> ref:curl-errors }}
|
|
171
127
|
|
|
172
128
|
## Completion message (mandatory final assistant text)
|
|
173
129
|
|
|
174
|
-
Emit exactly one line as your final assistant message. The daemon forwards this verbatim to the channel the bang came from — no other delivery mechanism is needed and you must NOT try to "send" it through another endpoint.
|
|
130
|
+
Emit exactly one line as your final assistant message. The daemon forwards this verbatim to the channel the bang came from — no other delivery mechanism is needed and you must NOT try to "send" it through another endpoint (no /api/send-message etc.; see "Allowed endpoints").
|
|
175
131
|
|
|
176
132
|
- Success (only after seeing `{"ok":true,"path":"10_raw/<slug>.md"}`): `Ingested <url> → 10_raw/<slug>.md`
|
|
177
133
|
- Failure (any other outcome): `Failed <url> — <one-sentence reason>`
|