@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.
Files changed (218) hide show
  1. package/README.md +41 -11
  2. package/agent-assets/agent-profiles/background-task.md +53 -0
  3. package/agent-assets/agent-profiles/conversational.md +1 -0
  4. package/agent-assets/agent-profiles/routine-fetch-window.md +14 -75
  5. package/agent-assets/agent-profiles/routine.md +1 -1
  6. package/agent-assets/agents/{hourly-check → activity-scan}/agent.md +22 -17
  7. package/agent-assets/agents/monthly-review/agent.md +6 -5
  8. package/agent-assets/docs/concepts/agent-day.md +6 -7
  9. package/agent-assets/docs/concepts/auth-health.md +23 -20
  10. package/agent-assets/docs/concepts/backends-and-tiers.md +13 -9
  11. package/agent-assets/docs/concepts/costs-and-quotas.md +14 -12
  12. package/agent-assets/docs/concepts/delegated-mode.md +18 -17
  13. package/agent-assets/docs/concepts/memory-model.md +16 -9
  14. package/agent-assets/docs/concepts/observations.md +24 -20
  15. package/agent-assets/docs/concepts/process-keys.md +10 -9
  16. package/agent-assets/docs/concepts/routines.md +34 -31
  17. package/agent-assets/docs/concepts/safety-and-execution.md +11 -7
  18. package/agent-assets/docs/concepts/safety-model.md +39 -25
  19. package/agent-assets/docs/concepts/skills.md +12 -10
  20. package/agent-assets/docs/features/integrations/browser-history.md +23 -18
  21. package/agent-assets/docs/features/integrations/calendar.md +28 -17
  22. package/agent-assets/docs/features/integrations/git.md +13 -11
  23. package/agent-assets/docs/features/integrations/github.md +22 -14
  24. package/agent-assets/docs/features/integrations/mail.md +25 -22
  25. package/agent-assets/docs/features/integrations/notion.md +35 -11
  26. package/agent-assets/docs/features/integrations/obsidian.md +8 -8
  27. package/agent-assets/docs/features/lifestyle/git.md +27 -23
  28. package/agent-assets/docs/features/lifestyle/reading.md +20 -11
  29. package/agent-assets/docs/features/lifestyle/receipts.md +11 -10
  30. package/agent-assets/docs/features/lifestyle/travel-bookings.md +4 -3
  31. package/agent-assets/docs/features/memory-files/agent-journal.md +53 -26
  32. package/agent-assets/docs/features/memory-files/agent-lessons.md +178 -0
  33. package/agent-assets/docs/features/memory-files/projects.md +11 -8
  34. package/agent-assets/docs/features/memory-files/roadmap.md +17 -14
  35. package/agent-assets/docs/features/memory-files/schedule.md +6 -3
  36. package/agent-assets/docs/features/memory-files/today.md +10 -7
  37. package/agent-assets/docs/features/memory-files/user-profile.md +14 -9
  38. package/agent-assets/docs/features/messaging/bang-commands.md +21 -6
  39. package/agent-assets/docs/features/messaging/overview.md +17 -14
  40. package/agent-assets/docs/features/messaging/telegram.md +10 -9
  41. package/agent-assets/docs/features/operations/activity-and-conversations.md +6 -5
  42. package/agent-assets/docs/features/operations/approvals.md +6 -5
  43. package/agent-assets/docs/features/operations/browser-tasks.md +184 -0
  44. package/agent-assets/docs/features/operations/cost-tracking.md +11 -1
  45. package/agent-assets/docs/features/operations/managed-chromium.md +4 -2
  46. package/agent-assets/docs/features/operations/notifications.md +11 -1
  47. package/agent-assets/docs/features/operations/quiet-hours.md +41 -11
  48. package/agent-assets/docs/features/operations/schedule-approaching.md +2 -2
  49. package/agent-assets/docs/features/routines/activity-scan.md +220 -0
  50. package/agent-assets/docs/features/routines/custom-routines.md +82 -134
  51. package/agent-assets/docs/features/routines/evening-review.md +23 -13
  52. package/agent-assets/docs/features/routines/morning-routine.md +7 -5
  53. package/agent-assets/docs/features/routines/weekly-review.md +24 -3
  54. package/agent-assets/docs/features/wiki/commands.md +4 -4
  55. package/agent-assets/docs/features/wiki/cost-and-approval.md +4 -3
  56. package/agent-assets/docs/features/wiki/dashboard.md +7 -6
  57. package/agent-assets/docs/features/wiki/overview.md +3 -3
  58. package/agent-assets/docs/features/wiki/search.md +5 -5
  59. package/agent-assets/docs/features/wiki/workspaces.md +2 -2
  60. package/agent-assets/docs/getting-started/01-what-is-this.md +3 -3
  61. package/agent-assets/docs/getting-started/02-first-steps.md +5 -3
  62. package/agent-assets/docs/getting-started/04-first-day.md +27 -30
  63. package/agent-assets/docs/glossary.md +8 -8
  64. package/agent-assets/docs/guides/add-a-custom-routine.md +122 -68
  65. package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +2 -2
  66. package/agent-assets/docs/guides/connect-a-new-mail-account.md +4 -2
  67. package/agent-assets/docs/guides/explore-with-trace-and-connect.md +5 -4
  68. package/agent-assets/docs/guides/install-and-run.md +2 -2
  69. package/agent-assets/docs/guides/maintain-wiki-health.md +2 -2
  70. package/agent-assets/docs/guides/pause-the-agent.md +27 -21
  71. package/agent-assets/docs/guides/reinstall-cleanly.md +2 -0
  72. package/agent-assets/docs/guides/setup-wizard.md +12 -6
  73. package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +6 -6
  74. package/agent-assets/docs/reference/api.md +26 -5
  75. package/agent-assets/docs/reference/cli-commands.md +3 -3
  76. package/agent-assets/docs/reference/config.md +51 -24
  77. package/agent-assets/docs/reference/disallowed-tools.md +6 -4
  78. package/agent-assets/docs/reference/keyboard-shortcuts.md +2 -2
  79. package/agent-assets/docs/reference/knowledge-layout.md +25 -12
  80. package/agent-assets/docs/reference/process-keys.md +9 -9
  81. package/agent-assets/docs/reference/skills.md +10 -6
  82. package/agent-assets/docs/troubleshooting/auth-failed.md +9 -8
  83. package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +16 -9
  84. package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +2 -2
  85. package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +32 -16
  86. package/agent-assets/docs/troubleshooting/observation-not-detected.md +26 -24
  87. package/agent-assets/docs/troubleshooting/quota-exhausted.md +7 -6
  88. package/agent-assets/docs/troubleshooting/wiki-write-failed.md +3 -3
  89. package/agent-assets/skills/agent-actions/SKILL.md +23 -39
  90. package/agent-assets/skills/agent-create/SKILL.md +26 -6
  91. package/agent-assets/skills/attach/SKILL.md +8 -27
  92. package/agent-assets/skills/background-task/SKILL.md +184 -0
  93. package/agent-assets/skills/background-task-reply/SKILL.md +100 -0
  94. package/agent-assets/skills/browser-history/SKILL.md +60 -29
  95. package/agent-assets/skills/browser-history-respond/SKILL.md +6 -1
  96. package/agent-assets/skills/browser-task/SKILL.md +33 -31
  97. package/agent-assets/skills/context/SKILL.md +26 -34
  98. package/agent-assets/skills/context/curation.json +12 -12
  99. package/agent-assets/skills/context/references/api.md +22 -20
  100. package/agent-assets/skills/context/references/required-frontmatter.md +10 -9
  101. package/agent-assets/skills/context/references/snapshot-files.md +16 -15
  102. package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +5 -5
  103. package/agent-assets/skills/context/seeds/frontmatter-requirements.seed.json +3 -3
  104. package/agent-assets/skills/docs-search/SKILL.md +19 -31
  105. package/agent-assets/skills/external-services/SKILL.delegated.claude.md +8 -95
  106. package/agent-assets/skills/external-services/SKILL.delegated.codex.md +8 -94
  107. package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +8 -94
  108. package/agent-assets/skills/external-services/SKILL.native.claude.md +15 -9
  109. package/agent-assets/skills/external-services/SKILL.native.codex.md +11 -5
  110. package/agent-assets/skills/external-services/SKILL.native.gemini.md +11 -5
  111. package/agent-assets/skills/external-services/references/exec-errors.md +32 -0
  112. package/agent-assets/skills/external-services/references/skills-crud.md +5 -5
  113. package/agent-assets/skills/gmail-lifestyle/SKILL.md +3 -2
  114. package/agent-assets/skills/gmail-lifestyle/references/receipts-api.md +4 -0
  115. package/agent-assets/skills/gmail-lifestyle/references/travel-bookings-api.md +9 -0
  116. package/agent-assets/skills/mail/SKILL.delegated.claude.md +13 -25
  117. package/agent-assets/skills/mail/SKILL.delegated.codex.md +3 -2
  118. package/agent-assets/skills/mail/SKILL.delegated.gemini.md +3 -2
  119. package/agent-assets/skills/mail/SKILL.md +12 -20
  120. package/agent-assets/skills/mail/SKILL.native.claude.md +24 -16
  121. package/agent-assets/skills/mail/SKILL.native.codex.md +16 -9
  122. package/agent-assets/skills/mail/SKILL.native.gemini.md +12 -6
  123. package/agent-assets/skills/mail/references/api.md +6 -1
  124. package/agent-assets/skills/mail/references/examples.md +2 -1
  125. package/agent-assets/skills/managed-tasks/SKILL.md +44 -77
  126. package/agent-assets/skills/managed-tasks/references/errors.md +25 -14
  127. package/agent-assets/skills/managed-tasks/references/output-path.md +33 -17
  128. package/agent-assets/skills/managed-tasks/references/recurrence-rule.md +26 -16
  129. package/agent-assets/skills/management-policy/SKILL.md +36 -28
  130. package/agent-assets/skills/management-policy/curation.json +1 -1
  131. package/agent-assets/skills/management-policy/references/policy-workflow.md +30 -18
  132. package/agent-assets/skills/notify/SKILL.md +16 -13
  133. package/agent-assets/skills/notify/references/priority.md +42 -26
  134. package/agent-assets/skills/notion/SKILL.delegated.claude.md +1 -1
  135. package/agent-assets/skills/notion/SKILL.delegated.codex.md +1 -1
  136. package/agent-assets/skills/notion/SKILL.delegated.gemini.md +1 -1
  137. package/agent-assets/skills/notion/SKILL.md +18 -18
  138. package/agent-assets/skills/notion/SKILL.native.claude.md +4 -4
  139. package/agent-assets/skills/notion/SKILL.native.codex.md +3 -3
  140. package/agent-assets/skills/notion/SKILL.native.gemini.md +3 -3
  141. package/agent-assets/skills/observations/SKILL.md +9 -24
  142. package/agent-assets/skills/observations/references/fetch-fallback.md +22 -0
  143. package/agent-assets/skills/project-doc/SKILL.md +9 -6
  144. package/agent-assets/skills/project-doc/curation.json +3 -3
  145. package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +2 -2
  146. package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +3 -3
  147. package/agent-assets/skills/reading/SKILL.md +8 -42
  148. package/agent-assets/skills/reading/references/reading-taste.md +5 -5
  149. package/agent-assets/skills/roadmap/SKILL.md +3 -19
  150. package/agent-assets/skills/roadmap/references/api.md +23 -8
  151. package/agent-assets/skills/roadmap/references/horizon-tags.md +11 -0
  152. package/agent-assets/skills/roadmap/references/migration.md +8 -6
  153. package/agent-assets/skills/roadmap/references/retention.md +18 -0
  154. package/agent-assets/skills/schedule/SKILL.md +20 -28
  155. package/agent-assets/skills/schedule/references/importance.md +23 -0
  156. package/agent-assets/skills/schedule/references/recurrence-rule.md +26 -16
  157. package/agent-assets/skills/scheduled-managed-task/SKILL.md +46 -46
  158. package/agent-assets/skills/today/SKILL.md +38 -81
  159. package/agent-assets/skills/today/references/agent-plan-lifecycle.md +9 -4
  160. package/agent-assets/skills/today/references/agent-plan-revision.md +28 -0
  161. package/agent-assets/skills/today/references/today-skeleton.md +66 -0
  162. package/agent-assets/skills/today/seeds/agent-notes-flavors.seed.json +1 -1
  163. package/agent-assets/skills/today/seeds/section-shape.seed.json +6 -6
  164. package/agent-assets/skills/user-interview/SKILL.md +15 -90
  165. package/agent-assets/skills/user-interview/references/op-briefing.md +1 -1
  166. package/agent-assets/skills/user-interview/references/op-dm-handler.md +88 -0
  167. package/agent-assets/skills/user-interview/references/op-morning.md +2 -2
  168. package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +1 -1
  169. package/agent-assets/skills/user-profile/SKILL.md +16 -26
  170. package/agent-assets/skills/user-profile/curation.json +3 -3
  171. package/agent-assets/skills/user-profile/references/character-preferences.md +3 -3
  172. package/agent-assets/skills/wiki/wiki-ask/SKILL.md +1 -1
  173. package/agent-assets/skills/wiki/wiki-compile/SKILL.md +5 -4
  174. package/agent-assets/skills/wiki/wiki-connect/SKILL.md +32 -5
  175. package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +6 -50
  176. package/agent-assets/skills/wiki/wiki-ingest/references/curl-errors.md +58 -0
  177. package/agent-assets/skills/wiki/wiki-lint/SKILL.md +20 -14
  178. package/agent-assets/skills/wiki/wiki-trace/SKILL.md +10 -5
  179. package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +2 -0
  180. package/agent-assets/system-prompts/routine-research-cluster-update.md +71 -0
  181. package/agent-assets/task-flows/_partials/feedback-capture.md +30 -0
  182. package/agent-assets/task-flows/_partials/notion-acquire.notion.md +47 -21
  183. package/agent-assets/task-flows/background_task.md +81 -0
  184. package/agent-assets/task-flows/git.local_ahead.stale.md +1 -1
  185. package/agent-assets/task-flows/git.push.detected.md +1 -1
  186. package/agent-assets/task-flows/git.tag.created.md +1 -1
  187. package/agent-assets/task-flows/github.assigned.md +1 -1
  188. package/agent-assets/task-flows/github.pull_request.review_requested.md +2 -2
  189. package/agent-assets/task-flows/github.security_alert.md +1 -1
  190. package/agent-assets/task-flows/message.received.dm.md +11 -3
  191. package/agent-assets/task-flows/message.received.dm_first.md +8 -2
  192. package/agent-assets/task-flows/{routine.hourly_check.md → routine.activity_scan.md} +31 -23
  193. package/agent-assets/task-flows/{routine.hourly_check.triage.md → routine.activity_scan.triage.md} +3 -3
  194. package/agent-assets/task-flows/routine.evening_review.md +80 -0
  195. package/agent-assets/task-flows/routine.monthly_review.md +81 -8
  196. package/agent-assets/task-flows/routine.research_cluster_update.md +33 -19
  197. package/agent-assets/task-flows/routine.roadmap_refresh.md +2 -2
  198. package/agent-assets/task-flows/routine.today_refresh.md +1 -1
  199. package/agent-assets/task-flows/routine.weekly_review.md +124 -4
  200. package/agent-assets/task-flows/schedule.approaching.md +2 -2
  201. package/agent-assets/task-flows/scheduled.dm.md +77 -1
  202. package/agent-assets/task-flows/scheduled.task.md +7 -1
  203. package/agent-assets/task-flows/wiki.trace.md +1 -1
  204. package/agent-assets/templates/_manifest.json +2 -2
  205. package/agent-assets/templates/knowledge/dossiers/_index.md +1 -1
  206. package/agent-assets/templates/knowledge/dossiers/{hourly.md → activity-scan.md} +1 -1
  207. package/agent-assets/templates/policies/journal-format.md +1 -1
  208. package/agent-assets/templates/policies/mcp.md +1 -1
  209. package/agent-assets/templates/policies/routines/_index.md +1 -1
  210. package/agent-assets/templates/policies/routines/{hourly.md → activity-scan.md} +5 -5
  211. package/bin/aitne.mjs +45 -11
  212. package/package.json +6 -5
  213. package/scripts/commands/doctor.mjs +11 -2
  214. package/scripts/lib/process-identity.d.mts +46 -0
  215. package/scripts/lib/process-identity.mjs +193 -0
  216. package/scripts/lib/read-api-token.mjs +1 -1
  217. package/scripts/start.mjs +14 -4
  218. package/agent-assets/docs/features/routines/hourly-check.md +0 -205
@@ -155,6 +155,16 @@ workflow; the skill owns the file contract.
155
155
  prioritization call this week
156
156
  - Concrete system improvement ideas (tighter silence gates, prompt
157
157
  adjustments, missing context features)
158
+
159
+ Ground this bucket in the `<self_performance>` block when it is
160
+ present in your context — it carries the objective 7-day evidence
161
+ (per-routine run/failure/cost rows, fetch-window empty-run rates per
162
+ integration, activity-scan gate stage distribution, per-type notification
163
+ reaction rates, lesson-store byte pressure, and any applied
164
+ self-tuning changes in `<tuning_ledger>`). Cite its numbers instead
165
+ of impressions ("gmail pre-pass 78% empty over 40 runs", not "mail
166
+ fetching feels wasteful"), and do not re-derive any of them by
167
+ querying APIs.
158
168
  6. Anything that fits the agent-internal bucket MUST NOT land in the
159
169
  user-facing file or notification. When in doubt about a line item: "would
160
170
  the user act on this, or is it a note about how the agent is doing?" →
@@ -307,19 +317,53 @@ workflow; the skill owns the file contract.
307
317
  prompt tweak / schedule adjustment / filter rule. "Improve the filter"
308
318
  is not testable; "Add Saturday to Weekend day-type default" is)
309
319
  ### Metrics (agent side)
310
- - Agent plan rows completed: N
311
- - Did-not-fire / failed rows: N
312
- - Observations reviewed / ignored: N / N
320
+ - Routine runs (7d): N total / N failed (prev week: N / N)
321
+ - Spend (7d): $X (prev week: $Y); top cost: <action_type> $Z
322
+ - Notifications (7d): N sent / N ignored (prev week sent: N)
313
323
  ```
324
+ **The Metrics numbers are copied, never counted.** The
325
+ `<self_performance>` block in your context is daemon-computed over
326
+ `agent_actions` / `notification_log` (SELF_TUNING_REVIEW_CYCLE_DESIGN.md
327
+ §3.1): take total/failed runs, spend, and the prev-week trend from
328
+ `<totals>`, the top-cost line from the first `<a>` row of `<actions>`,
329
+ and sent/ignored from `<totals>`'s `notif_*` attributes. Do not recount
330
+ via API queries, do not estimate from memory, do not "verify" the block
331
+ by re-querying — that re-spends the tokens this block exists to save.
332
+ If the block is absent (fresh install, prep failure), write the single
333
+ line `- metrics unavailable this week` instead of the three lines;
334
+ never reconstruct the numbers by hand.
314
335
  **Hard limits for this block** (the rollup will warn if exceeded):
315
336
  - Total section budget: ≤ 4000 bytes (~1000 tokens)
316
337
  - Bullet caps: What worked ≤ 5, What slipped ≤ 5, Improvement ideas ≤ 3
317
- - Metrics section: exactly 3 numeric lines, no commentary
338
+ - Metrics section: exactly 3 numeric lines copied from
339
+ `<self_performance>` (or the single unavailable-line fallback),
340
+ no commentary
318
341
  If you have more than 5 notable items in one subsection, keep only the
319
342
  top 5 by actionable impact and drop the rest. Do not try to fit
320
343
  everything — the monthly review synthesizes across weeks and surfaces
321
344
  recurring items anyway.
322
345
 
346
+ For each concrete, actionable bullet in `### System improvement ideas`,
347
+ also record a structured self-critique signal:
348
+
349
+ ```
350
+ POST /api/feedback
351
+ {
352
+ "source": "self_critique",
353
+ "summary": "<the specific testable improvement, max 280 chars>",
354
+ "valence": "neutral",
355
+ "kind": "do-more",
356
+ "scope_type": "agent",
357
+ "action_kind": "agent_execution",
358
+ "evidence": { "excerpt": "weekly_review YYYY-Www system improvement idea" }
359
+ }
360
+ ```
361
+
362
+ Post only concrete improvement ideas. Do not post every retrospective
363
+ sentence, metrics row, or vague wish. If an idea is clearly about one
364
+ named Agent Definition's output, use `scope_type: "agent_slug"` and
365
+ `scope_ref` with that slug; otherwise keep `scope_type: "agent"`.
366
+
323
367
  If `journal/agent.md` does not yet exist (GET returns 404), PUT a minimal
324
368
  file with just `# Agent Journal\n\n` as header and your new section below
325
369
  it, in a single call. Do not abort the review.
@@ -331,6 +375,82 @@ workflow; the skill owns the file contract.
331
375
  earlier one within 24 hours. Do not spend tokens trying to locate and
332
376
  overwrite the old section in place.
333
377
 
378
+ ### Phase 3c: Tuning verdicts (only when `<tuning_recommendations>` is present)
379
+
380
+ 9a. If your context contains a `<tuning_recommendations>` block, judge each
381
+ `<r>` row and submit verdicts. If the block is absent, skip this phase
382
+ silently — never invent recommendations, never call the endpoint without
383
+ a block.
384
+
385
+ The block is daemon-generated (SELF_TUNING_REVIEW_CYCLE_DESIGN.md §3.2):
386
+ each row proposes one bounded change (`current` → `proposed`) to a cost
387
+ knob, backed by 14-day telemetry in `evidence`. Your job is the one
388
+ thing the rule table cannot do — apply context the numbers don't show.
389
+ For each row pick exactly one verdict:
390
+ - `apply` — the evidence matches your understanding of the period and
391
+ the change is sensible. Example: mail pre-passes really were mostly
392
+ empty, nothing unusual about the week.
393
+ - `reject` — the numbers have a context explanation the rule can't
394
+ see. Example: notifications were ignored because the user was
395
+ traveling, not because the type is noise; a schedule failed because
396
+ an integration was temporarily down and is now fixed.
397
+ - `defer` — plausible but one more week of data would settle it.
398
+ Every verdict needs a one-line reason (max 280 chars) grounded in this
399
+ week's context — the reason is the record the owner reads during the
400
+ shadow period, so "looks fine" is not a reason.
401
+
402
+ A row that already carries a `verdict` attribute was judged by an
403
+ earlier run of this same cycle (same-day re-run) — do not re-judge or
404
+ re-submit it; verdict only the rows without one. If every row already
405
+ has a verdict, skip step 9b entirely.
406
+
407
+ 9b. Submit ALL verdicts in a single call:
408
+
409
+ ```
410
+ POST /api/tuning/verdicts
411
+ {
412
+ "cycleId": "<the block's cycle attribute>",
413
+ "verdicts": [
414
+ { "id": "<r id verbatim>", "verdict": "apply", "reason": "..." },
415
+ { "id": "<r id verbatim>", "verdict": "reject", "reason": "..." }
416
+ ]
417
+ }
418
+ ```
419
+
420
+ Hard rules:
421
+ - Use the `id` values from the block **verbatim** — the endpoint
422
+ accepts only the ids the daemon generated this cycle and 400s on
423
+ anything else. Do not edit keys, values, or propose your own
424
+ changes through this endpoint.
425
+ - The block's `mode` attribute tells you what an `apply` verdict
426
+ does. `mode="shadow"`: verdicts are recorded, nothing is applied —
427
+ the response carries `shadow: true` and manual application stays
428
+ the owner's call. `mode="live"`: the daemon applies config-knob
429
+ `apply` verdicts immediately through its bounded config chokepoint,
430
+ DMs the owner one line per applied change (with the
431
+ `!revert tuning` undo), and auto-reverts on measured regression —
432
+ so treat `apply` as a real action, not a vote. In BOTH modes, do
433
+ NOT call `PATCH /api/config` yourself for these knobs — the
434
+ endpoint is the only path that gets bounds, hysteresis, the
435
+ ledger, and auto-revert right.
436
+ - In live mode the response's `applied` array is the daemon's
437
+ receipt. R2 (`notification:<type>`) applies become lesson guidance
438
+ only; R4 (`recurring_schedules:<id>`) applies become an owner DM
439
+ suggestion — neither changes machine config.
440
+ - Do not post a separate `POST /api/feedback` for rejections — the
441
+ endpoint records the `self_critique` signal server-side from your
442
+ reason.
443
+ - A 409 `cycle_expired` / `no_pending_cycle` means the block is stale
444
+ (e.g. a re-run after a new cycle was generated): drop the step,
445
+ note it under journal/agent.md "What slipped on my side", move on.
446
+ - Never mention recommendations, verdicts, or tuning in the
447
+ user-facing weekly file or the Phase 4 notification — this is agent
448
+ mechanics, bound by the same audience rule as Phase 3b. In
449
+ journal/agent.md, record at most a single count line (e.g.
450
+ "2 tuning changes applied this week") — the daemon already DM'd
451
+ each change individually, so per-change detail here would
452
+ double-notify.
453
+
334
454
  ### Phase 4: Notify (user-facing only)
335
455
  10. The notification is a brief, warm end-of-week touchpoint for the USER
336
456
  — not a report of Phases 1–3. Never mention journal/weekly/YYYY-Www.md,
@@ -54,11 +54,11 @@ the user could not see by glancing at their calendar app.
54
54
  `calendar:*` is treated as a literal asterisk character and
55
55
  matches zero rows.
56
56
 
57
- 2. **`pending=false`** — `routine.hourly_check` consumes
57
+ 2. **`pending=false`** — `routine.activity_scan` consumes
58
58
  `actor=user` observations every hour, and calendar mutations
59
59
  are tagged `actor='user'` (`calendar-poller.ts:210-212`). A
60
60
  `pending=true` query would miss any reschedule older than the
61
- latest hourly tick.
61
+ latest activity-scan tick.
62
62
 
63
63
  3. **`since=<UTC_24H_AGO>`** — pass the timestamp 24 hours before
64
64
  the `utc=` attribute on the `<current_time>` block in your
@@ -25,6 +25,27 @@ Task: {event_data[task]}
25
25
  - `<task_origin>` — what triggered this run (recurring schedule id,
26
26
  source)
27
27
 
28
+ ## Agent Plan close-out (plan-backed firings)
29
+
30
+ When this firing matches a pending `## Agent Plan` row in <today>
31
+ (typically a `→wake` row the Morning Routine registered — match HH:MM
32
+ + action text), run these gates BEFORE composing, then close the loop
33
+ per the today skill's Agent Plan lifecycle:
34
+
35
+ 1. **Day-type filter** — if the row's `[category]` focus is `off` on
36
+ line 2 of <today>, do not send the DM: end with empty output (the
37
+ delivery path drops zero-length turns) and close the loop with
38
+ outcome `skipped (focus off)`.
39
+ 2. **Premise check** — if the row references a calendar event that
40
+ <calendar_today> positively shows gone or moved, skip the same way
41
+ with outcome `skipped (premise gone)`. Missing or unfetchable
42
+ calendar data is NOT evidence — proceed normally.
43
+ 3. **Close the loop** — append the Agent Log entry, then flip the row
44
+ to `[x]` (annotate skips / failures per the lifecycle).
45
+
46
+ Recurring briefings and confirm sub-flows with no matching row skip
47
+ this section silently.
48
+
28
49
  ## Conversation-state framing (universal — every dm_session)
29
50
 
30
51
  Detect state from `<recent_dm_messages>`:
@@ -77,6 +98,7 @@ prefix matching. Find the matching sub-flow below and follow its
77
98
  content rules.
78
99
 
79
100
  - starts with `morning briefing` → see `## Morning briefing` below
101
+ - starts with `task delivery:` → see `## Task delivery` below
80
102
  - starts with `profile_interview:` → see `## Profile interview` below
81
103
  - starts with `confirm:` → see `## Confirmation follow-up` below
82
104
  - (future sub-flows added here)
@@ -98,6 +120,55 @@ user verbatim — defeating the skip.
98
120
 
99
121
  ---
100
122
 
123
+ ## Task delivery
124
+
125
+ Triggered by `{event_data[task]}` starting with `task delivery:`.
126
+
127
+ Your final assistant turn IS the DM that delivers a background task
128
+ artifact. The daemon has already decided that the owner is active in
129
+ conversation, so weave this into the current thread instead of writing a
130
+ standalone report.
131
+
132
+ Read `<task_context>` → `task_delivery`:
133
+
134
+ - `deliveryType: "task_result"` means a task finished. Use `draft` for
135
+ the compact owner-facing summary and `report` as the fidelity source.
136
+ - `deliveryType: "task_clarification"` means the task is blocked on an
137
+ answer. Ask the question naturally and briefly; if there is useful
138
+ `contextSummary`, include only what helps the owner answer.
139
+ - `title` is the human task label. Use it only when it helps orient the
140
+ owner.
141
+ - `assets` is the list of files the task produced for the owner (each has
142
+ a `filename`, a `kind` like `screenshot` / `pdf` / `slides` / `image`,
143
+ and sometimes a `label`). **When `assets` is present, the daemon attaches
144
+ those files to THIS message automatically** — you do not upload anything.
145
+ Reference them naturally so the attachment makes sense (e.g. "I've
146
+ attached the confirmation screenshots" or "the slide deck is attached").
147
+ When `assets` is absent or empty, do not mention or imply any file.
148
+ - IDs and other internal fields are for daemon routing and audit. Do not
149
+ expose filenames-as-paths, keys, or IDs in user-facing text.
150
+
151
+ Delivery rules:
152
+
153
+ 1. Use the conversational state from `<recent_dm_messages>` and
154
+ `<recent_dm_conversation>` to write a short interruption-preface when
155
+ the owner is mid-topic. If the recent topic is clear, acknowledge it
156
+ lightly and hand the floor back after the task note.
157
+ 2. Preserve factual fidelity. Do not invent findings, counts, URLs, or
158
+ decisions not present in `report` / `draft`. Do not claim a file is
159
+ attached unless it appears in `assets`.
160
+ 3. Do not mention implementation details such as task IDs,
161
+ `task.delivery`, `scheduled.dm`, artifacts, metadata, API routes,
162
+ context blocks, or background runners.
163
+ 4. Keep the message compact. For long reports, summarize the decision
164
+ points and offer to pull details if the owner asks. If the owner later
165
+ asks for a file again, you can re-send it from the task detail in a
166
+ normal turn (the artifact API exposes the asset list).
167
+ 5. End with exactly the message to send. Do not perform follow-up work in
168
+ this turn.
169
+
170
+ ---
171
+
101
172
  ## Morning briefing
102
173
 
103
174
  Triggered by `{event_data[task]}` starting with `morning briefing`.
@@ -168,6 +239,7 @@ the daily greeting.
168
239
  - Calendar updates: events in today→+7d window with updated_at
169
240
  >= today 04:00
170
241
  - Pending observations: `GET /api/observations?pending=true&actor=user`
242
+ - Filed background results (§10.5): `GET /api/background-task?state=completed&notify=false&sinceHours=24` — background tasks the user started that finished without clearing the bar to ping (a `silent` task, or an `if_significant` task whose criteria weren't met). Each row carries a `title` and a one-line `significance`. These were deliberately not surfaced when they finished; the briefing is where they get a quiet mention so nothing is silently dropped. Empty list → nothing to mention.
171
243
  4. **At-risk items** — schedule conflicts, missing prep for known
172
244
  events, unanswered RSVPs. Derive by cross-referencing 1+2+3.
173
245
 
@@ -190,6 +262,7 @@ Overnight:
190
262
  - (mail) summary
191
263
  - (calendar) summary
192
264
  - (dm) summary
265
+ - (filed) N background results: <title> (<significance>), …
193
266
 
194
267
  At-risk:
195
268
  - conflict / prep gap
@@ -270,7 +343,10 @@ voice carries the whole message.
270
343
  - Maximum ~25 lines total (briefing fits one mobile screen).
271
344
  - Schedule list: cap 8, append `...and N more` if over.
272
345
  - Tasks list: cap 10, append `...and N more` if over.
273
- - Overnight: cap 5 per category (mail / dm / calendar).
346
+ - Overnight: cap 5 per category (mail / dm / calendar / filed). For
347
+ `(filed)`, lead with the count and name at most 3 by title; on a
348
+ long-quiet day a single line ("N background results filed quietly")
349
+ is enough — never let filed results crowd out the day's actual shape.
274
350
  - No internal names ("Morning Routine", "Agent Plan",
275
351
  "scheduled.dm", "state/today.md") in user-facing text.
276
352
  - Forbidden openers across all variants: "Morning briefing —",
@@ -116,6 +116,12 @@ confirmation.
116
116
  ### Step 3: Execute (only if not skipped)
117
117
  5. Execute the task. Use Daemon API (curl) as needed.
118
118
  Use <today> for day state and <calendar_today> for live calendar events.
119
+ Premise check first: if the task references a calendar event, confirm
120
+ it still exists at the expected time in <calendar_today>. Skip only on
121
+ positive evidence — the event is absent or moved while sibling events
122
+ show the data is live. Then do NOT execute; proceed to Step 4 with
123
+ outcome `skipped (premise gone)`. Missing or unfetchable calendar
124
+ data is NOT evidence — execute normally.
119
125
  If the task description is unclear or lacks critical details (who, what,
120
126
  when, why), do NOT guess — log `ambiguous task — skipped` to Agent Log
121
127
  and proceed to Step 4 with outcome `skipped (ambiguous)`.
@@ -125,7 +131,7 @@ confirmation.
125
131
  `- HH:MM [agent_plan] <action summary> — <outcome>`
126
132
  Outcome taxonomy: DM sent / notify sent / check-in scheduled /
127
133
  skipped (focus off) / skipped (quiet hours) / skipped (user in meeting) /
128
- skipped (ambiguous) / failed: <reason>.
134
+ skipped (premise gone) / skipped (ambiguous) / failed: <reason>.
129
135
  7. If Step 1 found a matching Agent Plan row, flip it to `- [x]` via the
130
136
  lifecycle recipe in the context skill (GET → edit body → PATCH
131
137
  replace section=agent_plan). Annotate per the skill's outcome table:
@@ -8,6 +8,6 @@ Read `<wiki_command>` for the `topic`. Follow the `wiki-trace` skill:
8
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
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
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.
11
+ 5. The daemon auto-appends the `log.md` entry on the successful write in step 4 — no manual log step is needed.
12
12
 
13
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.
@@ -14,7 +14,7 @@
14
14
  "journal/agent.md": { "version": 1 },
15
15
  "knowledge/dossiers/_index.md": { "version": 1 },
16
16
  "knowledge/dossiers/evening.md": { "version": 1 },
17
- "knowledge/dossiers/hourly.md": { "version": 1 },
17
+ "knowledge/dossiers/activity-scan.md": { "version": 1 },
18
18
  "knowledge/dossiers/monthly.md": { "version": 1 },
19
19
  "knowledge/dossiers/morning.md": { "version": 1 },
20
20
  "knowledge/dossiers/roadmap.md": { "version": 1 },
@@ -29,7 +29,7 @@
29
29
  "policies/redaction.md": { "version": 1 },
30
30
  "policies/routines/_index.md": { "version": 1 },
31
31
  "policies/routines/evening.md": { "version": 1 },
32
- "policies/routines/hourly.md": { "version": 1 },
32
+ "policies/routines/activity-scan.md": { "version": 1 },
33
33
  "policies/routines/monthly.md": { "version": 1 },
34
34
  "policies/routines/morning.md": { "version": 1 },
35
35
  "policies/routines/weekly.md": { "version": 1 },
@@ -14,7 +14,7 @@ Injected into prompts through the root-level context-index.md catalog.
14
14
 
15
15
  | File | Process key |
16
16
  |---|---|
17
- | `hourly.md` | `routine.hourly_check` |
17
+ | `activity-scan.md` | `routine.activity_scan` |
18
18
  | `morning.md` | `routine.morning_routine`, `routine.morning_routine_today` |
19
19
  | `evening.md` | `routine.evening_review` |
20
20
  | `weekly.md` | `routine.weekly_review` |
@@ -4,7 +4,7 @@ owner: agent
4
4
  updated: 2026-04-17
5
5
  template_version: 1
6
6
  ---
7
- # Hourly Check Dossier
7
+ # Activity Scan Dossier
8
8
 
9
9
  ## Standing checklist
10
10
 
@@ -23,7 +23,7 @@ voice, and content all belong to the user.
23
23
 
24
24
  Agent-side bookkeeping (action counts, internal anomalies, audit
25
25
  trail) lives in `journal/agent.md` — not here. If you find yourself
26
- about to log "the agent ran N tools today" or "the hourly check
26
+ about to log "the agent ran N tools today" or "the activity scan
27
27
  fired M times", that belongs in the agent-side log instead. Filter
28
28
  it out.
29
29
 
@@ -17,7 +17,7 @@ This file governs how the agent uses attached Model Context Protocol
17
17
  issue, a posted message, an edited doc).
18
18
  - Failures are loggable events. On repeated MCP call failures, the agent
19
19
  appends to `journal/agent.md` and surfaces the pattern at the next
20
- hourly check.
20
+ activity scan.
21
21
  - Scope to the active task. MCP calls unrelated to the current flow's
22
22
  stated goal are skipped.
23
23
 
@@ -12,7 +12,7 @@ I've added later via DM). All checks are treated equally.
12
12
 
13
13
  | File | Cadence | Process key |
14
14
  |---|---|---|
15
- | `hourly.md` | every hour | `routine.hourly_check` |
15
+ | `activity-scan.md` | every 2 h (default) | `routine.activity_scan` |
16
16
  | `morning.md` | 04:00 daily | `routine.morning_routine` |
17
17
  | `evening.md` | evening | `routine.evening_review` |
18
18
  | `weekly.md` | Friday | `routine.weekly_review` |
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  type: rule
3
- slug: hourly
3
+ slug: activity-scan
4
4
  owner: shared
5
5
  updated: 2026-04-17
6
6
  template_version: 1
7
7
  ---
8
- # Hourly Check
8
+ # Activity Scan
9
9
 
10
- The daemon fires `routine.hourly_check` at the top of every hour. This
11
- file is injected verbatim via `policy-files.ts`. Each `### <label>` block
10
+ The daemon fires `routine.activity_scan` every interval (default: every
11
+ 2 hours) within active hours. This file is injected verbatim via `policy-files.ts`. Each `### <label>` block
12
12
  is one check. All checks are equal — the agent runs them in order,
13
13
  skipping any whose preconditions are not met.
14
14
 
@@ -26,5 +26,5 @@ skipping any whose preconditions are not met.
26
26
 
27
27
  ## Skip conditions (applied before any check)
28
28
  - Morning routine still in progress (runtime_state flag)
29
- - Hourly check already running (atomic flag in runtime_state)
29
+ - Activity scan already running (atomic flag in runtime_state)
30
30
  - No check has a firing precondition AND pending observations < 2
package/bin/aitne.mjs CHANGED
@@ -17,6 +17,12 @@ import {
17
17
  resolveApiPort,
18
18
  resolveDashboardPort,
19
19
  } from "../scripts/lib/ports.mjs";
20
+ import {
21
+ classifyPid,
22
+ parsePidMeta,
23
+ readProcessStartToken,
24
+ serializePidMeta,
25
+ } from "../scripts/lib/process-identity.mjs";
20
26
 
21
27
  const IS_WINDOWS = process.platform === "win32";
22
28
 
@@ -98,18 +104,25 @@ function rotateLogFile(logFile) {
98
104
  try { fs.renameSync(logFile, rotated); } catch { /* ignore */ }
99
105
  }
100
106
 
101
- function readPid(pidFile) {
107
+ function readPidMeta(pidFile) {
102
108
  try {
103
- const content = fs.readFileSync(pidFile, "utf8").trim();
104
- const pid = parseInt(content, 10);
105
- return Number.isFinite(pid) ? pid : null;
109
+ return parsePidMeta(fs.readFileSync(pidFile, "utf8"));
106
110
  } catch {
107
111
  return null;
108
112
  }
109
113
  }
110
114
 
115
+ /**
116
+ * Persist the PID plus a start-identity token so a later `start`/`stop`/`status`
117
+ * can tell *our* process from a recycled PID after an unclean shutdown. Line 1
118
+ * stays the bare PID so an older aitne still reads the file. If the OS
119
+ * start-time read fails we write just the bare PID and degrade to the legacy
120
+ * unverified-but-trusted behavior. See process-lifecycle-2 in
121
+ * CROSS_PLATFORM_REAUDIT_2026-06.md.
122
+ */
111
123
  function writePid(pidFile, pid) {
112
- fs.writeFileSync(pidFile, String(pid) + "\n");
124
+ const startToken = readProcessStartToken(pid);
125
+ fs.writeFileSync(pidFile, serializePidMeta({ pid, startToken }));
113
126
  }
114
127
 
115
128
  function removePid(pidFile) {
@@ -186,11 +199,25 @@ function nextSpawnArgs(dashboardDir, nextBin, userArgs) {
186
199
  return userArgs;
187
200
  }
188
201
 
202
+ /**
203
+ * Resolve the live PID recorded in `pidFile`, or null. This is the single
204
+ * chokepoint every command (start/stop/status, plus open/uninstall/doctor via
205
+ * ctx.helpers) funnels through, so identity reconciliation here fixes them all
206
+ * at once. A recycled PID (start-time token mismatch) classifies `stale` → the
207
+ * pidfile is removed and null returned, so `start` won't false-"Already
208
+ * running" and `stop` won't kill an unrelated tree. `running-unverified`
209
+ * (legacy file with no token, or an OS start-time read failure) degrades to the
210
+ * pre-fix bare-PID behavior — no regression; a legacy file self-heals on the
211
+ * next writePid. verifyStartup() deliberately does NOT route through here: it
212
+ * checks the freshly-spawned in-memory pid via isAlive + health, preserving its
213
+ * "alive but health not responding = hung" branch.
214
+ */
189
215
  function getRunningPid(pidFile) {
190
- const pid = readPid(pidFile);
191
- if (pid == null) return null;
192
- if (!isAlive(pid)) { removePid(pidFile); return null; }
193
- return pid;
216
+ const meta = readPidMeta(pidFile);
217
+ if (!meta || meta.pid == null) return null;
218
+ const verdict = classifyPid(meta, { readToken: readProcessStartToken, isAlive });
219
+ if (verdict === "stale") { removePid(pidFile); return null; }
220
+ return meta.pid;
194
221
  }
195
222
 
196
223
  /**
@@ -314,7 +341,14 @@ async function cmdLogRunner(args) {
314
341
  }
315
342
  };
316
343
 
317
- const child = spawn(spec.command, spec.args, {
344
+ // Under shell:true on Windows, cmd.exe re-parses the line and does NOT
345
+ // auto-quote the command, so a spaced install path (C:\\Users\\First Last\\...)
346
+ // would split at the space. Double-quote the command so it stays one token.
347
+ // POSIX is byte-identical: spec.shell is never true off Windows (the `.cmd`
348
+ // predicate at the call site is gated on IS_WINDOWS). Args here are static
349
+ // literals (start --port <n>) with no metacharacters, so they need no escaping.
350
+ const runCommand = spec.shell === true ? `"${spec.command}"` : spec.command;
351
+ const child = spawn(runCommand, spec.args, {
318
352
  cwd: spec.cwd,
319
353
  env: process.env,
320
354
  stdio: ["ignore", "pipe", "pipe"],
@@ -427,7 +461,7 @@ async function cmdStart(args = []) {
427
461
  // cmd.exe and are kept only as a last fallback.
428
462
  const nextBin = resolveNextBin(dashboardDir);
429
463
  const dashArgs = nextSpawnArgs(dashboardDir, nextBin, [
430
- "start", "--port", String(DASHBOARD_PORT),
464
+ "start", "--port", String(DASHBOARD_PORT), "--hostname", "127.0.0.1",
431
465
  ]);
432
466
  const dashboard = spawnLoggedService({
433
467
  command: nextBin,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aitne-sh/aitne",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Aitne — a local-first, proactive personal AI agent. A long-running TypeScript daemon is the nervous system; Claude Code (or Codex / Gemini CLI) is the brain. All persistent memory lives in local Markdown files.",
5
5
  "keywords": [
6
6
  "ai",
@@ -43,9 +43,9 @@
43
43
  "README.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@aitne/daemon": "0.1.9",
47
- "@aitne/dashboard": "0.1.9",
48
- "@aitne/shared": "0.1.9"
46
+ "@aitne/daemon": "0.1.11",
47
+ "@aitne/dashboard": "0.1.11",
48
+ "@aitne/shared": "0.1.11"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@typescript-eslint/eslint-plugin": "^8.58.1",
@@ -72,9 +72,10 @@
72
72
  "dev": "node bin/aitne.mjs dev",
73
73
  "doctor": "node bin/aitne.mjs doctor",
74
74
  "audit": "node bin/aitne.mjs audit",
75
- "test": "node scripts/check-redaction-coverage.mjs && vitest run --coverage",
75
+ "test": "node scripts/check-redaction-coverage.mjs && node scripts/check-dashboard-colors.mjs && vitest run --coverage",
76
76
  "test:watch": "vitest",
77
77
  "check:redaction": "node scripts/check-redaction-coverage.mjs",
78
+ "check:colors": "node scripts/check-dashboard-colors.mjs",
78
79
  "check:vault-paths": "node scripts/check-vault-path-drift.mjs",
79
80
  "lint": "turbo run lint",
80
81
  "typecheck:tests": "turbo run typecheck:tests",
@@ -12,7 +12,9 @@
12
12
  import { execFileSync } from "node:child_process";
13
13
  import fs from "node:fs";
14
14
  import net from "node:net";
15
+ import os from "node:os";
15
16
  import path from "node:path";
17
+ import { pathToFileURL } from "node:url";
16
18
 
17
19
  export async function run(args, ctx) {
18
20
  if (args.includes("--help") || args.includes("-h")) {
@@ -164,7 +166,13 @@ async function checkSecretStore(ctx) {
164
166
  return { status: "pass", label: "Secret store", detail: "libsecret (`secret-tool`) reachable" };
165
167
  } catch {
166
168
  const hasMaster = !!process.env.PA_MASTER_PASSWORD;
167
- const keyfile = path.join(ctx.DATA_DIR, "secrets", ".master-key");
169
+ // The daemon's secret clients hardcode ~/.personal-agent/secrets and do
170
+ // NOT honor PA_DATA_DIR (secret-client-file.ts:99,209 — homedir-hardcoded;
171
+ // createSecretClient passes no dir). Probe the same homedir-anchored path
172
+ // so this diagnostic agrees with where keys are actually read. If the
173
+ // daemon is ever changed to honor PA_DATA_DIR for secrets, revert this and
174
+ // fix at the factory (secret-client-factory.ts) instead.
175
+ const keyfile = path.join(os.homedir(), ".personal-agent", "secrets", ".master-key");
168
176
  const hasKeyfile = fs.existsSync(keyfile);
169
177
  if (hasMaster || hasKeyfile) {
170
178
  return {
@@ -371,7 +379,8 @@ async function checkRepositoryGithubLinkDrift(dataDir) {
371
379
  },
372
380
  ];
373
381
  }
374
- Database = (await import(found)).default ?? (await import(found));
382
+ const mod = await import(pathToFileURL(found).href);
383
+ Database = mod.default ?? mod;
375
384
  } catch (err) {
376
385
  return [
377
386
  {
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Type declarations for the plain-ESM launcher module `process-identity.mjs`.
3
+ *
4
+ * `process-identity.mjs` is hand-written JavaScript (it must run before the
5
+ * TypeScript build, from `bin/aitne.mjs`), so it carries no inferred types.
6
+ * This sidecar lets the `packages/shared/src/process-identity.test.ts` peer
7
+ * test typecheck the import under `strict`. Mirrors the `ports.d.mts`
8
+ * precedent. Keep these signatures in lockstep with the `.mjs` exports.
9
+ */
10
+
11
+ /** Parsed pidfile contents. `startToken` is null for a legacy (tokenless) file. */
12
+ export interface PidMeta {
13
+ pid: number;
14
+ startToken: string | null;
15
+ }
16
+
17
+ /** Injectable OS shims for {@link readProcessStartToken} (tests only). */
18
+ export interface ReadTokenDeps {
19
+ platform?: NodeJS.Platform;
20
+ execFileSync?: (command: string, args?: readonly string[], options?: unknown) => string | Buffer;
21
+ readFileSync?: (path: string, encoding: string) => string;
22
+ }
23
+
24
+ /** Liveness + start-time reader injected into {@link classifyPid}. */
25
+ export interface ClassifyDeps {
26
+ readToken: (pid: number) => string | null;
27
+ isAlive: (pid: number) => boolean;
28
+ }
29
+
30
+ export type PidClassification = "stale" | "running-ours" | "running-unverified";
31
+
32
+ export function serializePidMeta(input: { pid: number; startToken?: string | null }): string;
33
+
34
+ export function parsePidMeta(content: string): PidMeta | null;
35
+
36
+ export function parseLinuxStat(statContent: string): string | null;
37
+
38
+ export function readProcessStartToken(
39
+ pid: number | null | undefined,
40
+ deps?: ReadTokenDeps,
41
+ ): string | null;
42
+
43
+ export function classifyPid(
44
+ meta: { pid?: number | null; startToken?: string | null } | null | undefined,
45
+ deps: ClassifyDeps,
46
+ ): PidClassification;