@aitne-sh/aitne 0.1.7 → 0.1.9
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 +256 -833
- package/agent-assets/agent-profiles/_safety.md +52 -20
- package/agent-assets/agent-profiles/browser-task.md +108 -0
- package/agent-assets/agent-profiles/conversational.md +3 -3
- package/agent-assets/agent-profiles/profile-importer.md +3 -3
- package/agent-assets/agent-profiles/routine-fetch-window.md +30 -19
- package/agent-assets/agent-profiles/routine.md +4 -3
- package/agent-assets/agents/context-index-reconcile/agent.md +52 -0
- package/agent-assets/agents/evening-review/agent.md +53 -0
- package/agent-assets/agents/hourly-check/agent.md +62 -0
- package/agent-assets/agents/monthly-review/agent.md +55 -0
- package/agent-assets/agents/morning-routine/agent.md +78 -0
- package/agent-assets/agents/roadmap-maintenance/agent.md +52 -0
- package/agent-assets/agents/skill-curation/agent.md +52 -0
- package/agent-assets/agents/user-profile-sweep-evening/agent.md +48 -0
- package/agent-assets/agents/user-profile-sweep-morning/agent.md +53 -0
- package/agent-assets/agents/weekly-review/agent.md +51 -0
- package/agent-assets/docs/concepts/agent-day.md +18 -11
- package/agent-assets/docs/concepts/auth-health.md +56 -10
- package/agent-assets/docs/concepts/backends-and-tiers.md +110 -41
- package/agent-assets/docs/concepts/costs-and-quotas.md +74 -19
- package/agent-assets/docs/concepts/delegated-mode.md +193 -75
- package/agent-assets/docs/concepts/memory-model.md +79 -34
- package/agent-assets/docs/concepts/observations.md +61 -11
- package/agent-assets/docs/concepts/process-keys.md +66 -17
- package/agent-assets/docs/concepts/routines.md +77 -32
- package/agent-assets/docs/concepts/safety-and-execution.md +50 -21
- package/agent-assets/docs/concepts/safety-model.md +62 -37
- package/agent-assets/docs/concepts/skills.md +38 -17
- package/agent-assets/docs/features/integrations/browser-history.md +195 -0
- package/agent-assets/docs/features/integrations/calendar.md +40 -30
- package/agent-assets/docs/features/integrations/git.md +20 -9
- package/agent-assets/docs/features/integrations/github.md +93 -35
- package/agent-assets/docs/features/integrations/mail.md +60 -17
- package/agent-assets/docs/features/integrations/notion.md +51 -11
- package/agent-assets/docs/features/integrations/obsidian.md +35 -7
- package/agent-assets/docs/features/lifestyle/git.md +45 -44
- package/agent-assets/docs/features/lifestyle/reading.md +50 -22
- package/agent-assets/docs/features/lifestyle/receipts.md +66 -21
- package/agent-assets/docs/features/lifestyle/travel-bookings.md +91 -14
- package/agent-assets/docs/features/memory-files/agent-journal.md +111 -50
- package/agent-assets/docs/features/memory-files/projects.md +75 -15
- package/agent-assets/docs/features/memory-files/roadmap.md +55 -10
- package/agent-assets/docs/features/memory-files/schedule.md +113 -70
- package/agent-assets/docs/features/memory-files/today.md +47 -21
- package/agent-assets/docs/features/memory-files/user-profile.md +67 -31
- package/agent-assets/docs/features/messaging/bang-commands.md +115 -28
- package/agent-assets/docs/features/messaging/dashboard-chat.md +43 -21
- package/agent-assets/docs/features/messaging/discord.md +46 -4
- package/agent-assets/docs/features/messaging/overview.md +40 -19
- package/agent-assets/docs/features/messaging/pairing-and-magic-phrase.md +94 -27
- package/agent-assets/docs/features/messaging/slack.md +79 -14
- package/agent-assets/docs/features/messaging/telegram.md +25 -6
- package/agent-assets/docs/features/messaging/whatsapp.md +79 -14
- package/agent-assets/docs/features/operations/activity-and-conversations.md +45 -16
- package/agent-assets/docs/features/operations/approvals.md +53 -15
- package/agent-assets/docs/features/operations/backend-routing.md +75 -16
- package/agent-assets/docs/features/operations/cost-tracking.md +90 -17
- package/agent-assets/docs/features/operations/managed-chromium.md +221 -0
- package/agent-assets/docs/features/operations/notifications.md +58 -11
- package/agent-assets/docs/features/operations/quiet-hours.md +63 -40
- package/agent-assets/docs/features/operations/schedule-approaching.md +59 -16
- package/agent-assets/docs/features/routines/custom-routines.md +97 -23
- package/agent-assets/docs/features/routines/evening-review.md +75 -22
- package/agent-assets/docs/features/routines/hourly-check.md +150 -30
- package/agent-assets/docs/features/routines/morning-routine.md +60 -33
- package/agent-assets/docs/features/routines/weekly-review.md +65 -20
- package/agent-assets/docs/features/wiki/commands.md +37 -16
- package/agent-assets/docs/features/wiki/cost-and-approval.md +240 -0
- package/agent-assets/docs/features/wiki/dashboard.md +255 -0
- package/agent-assets/docs/features/wiki/overview.md +80 -12
- package/agent-assets/docs/features/wiki/search.md +248 -0
- package/agent-assets/docs/features/wiki/workspaces.md +254 -0
- package/agent-assets/docs/getting-started/01-what-is-this.md +64 -32
- package/agent-assets/docs/getting-started/02-first-steps.md +28 -10
- package/agent-assets/docs/getting-started/03-what-can-this-do.md +42 -21
- package/agent-assets/docs/getting-started/04-first-day.md +52 -20
- package/agent-assets/docs/glossary.md +285 -21
- package/agent-assets/docs/guides/add-a-custom-routine.md +74 -22
- package/agent-assets/docs/guides/backup-and-restore.md +92 -14
- package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +62 -25
- package/agent-assets/docs/guides/build-your-wiki.md +33 -6
- package/agent-assets/docs/guides/change-which-model-handles-x.md +70 -9
- package/agent-assets/docs/guides/connect-a-new-mail-account.md +80 -15
- package/agent-assets/docs/guides/explore-with-trace-and-connect.md +32 -9
- package/agent-assets/docs/guides/import-knowledge-file.md +60 -39
- package/agent-assets/docs/guides/install-and-run.md +64 -19
- package/agent-assets/docs/guides/maintain-wiki-health.md +41 -10
- package/agent-assets/docs/guides/migrate-machines.md +86 -18
- package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +119 -59
- package/agent-assets/docs/guides/pause-the-agent.md +71 -22
- package/agent-assets/docs/guides/reinstall-cleanly.md +102 -17
- package/agent-assets/docs/guides/setup-wizard.md +126 -56
- package/agent-assets/docs/guides/switch-default-backend.md +72 -17
- package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +31 -10
- package/agent-assets/docs/reference/api.md +162 -23
- package/agent-assets/docs/reference/cli-commands.md +55 -15
- package/agent-assets/docs/reference/config.md +246 -39
- package/agent-assets/docs/reference/disallowed-tools.md +42 -10
- package/agent-assets/docs/reference/keyboard-shortcuts.md +47 -10
- package/agent-assets/docs/reference/knowledge-layout.md +620 -0
- package/agent-assets/docs/reference/process-keys.md +126 -20
- package/agent-assets/docs/reference/skills.md +62 -18
- package/agent-assets/docs/troubleshooting/auth-failed.md +53 -19
- package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +96 -22
- package/agent-assets/docs/troubleshooting/fallback-keeps-firing.md +94 -20
- package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +77 -22
- package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +87 -22
- package/agent-assets/docs/troubleshooting/observation-not-detected.md +85 -21
- package/agent-assets/docs/troubleshooting/quota-exhausted.md +36 -6
- package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +128 -51
- package/agent-assets/docs/troubleshooting/wiki-write-failed.md +33 -11
- package/agent-assets/optimizer-skills/drift-analysis/SKILL.md +1 -1
- package/agent-assets/optimizer-skills/knowledge-map/SKILL.md +1 -1
- package/agent-assets/optimizer-skills/skill-curation/SKILL.md +2 -2
- package/agent-assets/sandbox/linux/aitne-chromium.apparmor +91 -0
- package/agent-assets/sandbox/macos/aitne-chromium.sb +156 -0
- package/agent-assets/skills/agent-actions/SKILL.md +122 -0
- package/agent-assets/skills/agent-create/SKILL.md +149 -0
- package/agent-assets/skills/attach/SKILL.md +3 -4
- package/agent-assets/skills/browser-history/SKILL.md +198 -0
- package/agent-assets/skills/browser-history-respond/SKILL.md +106 -0
- package/agent-assets/skills/browser-task/SKILL.md +169 -0
- package/agent-assets/skills/context/SKILL.md +45 -463
- package/agent-assets/skills/context/curation.json +2 -2
- package/agent-assets/skills/context/references/api.md +232 -0
- package/agent-assets/skills/context/references/required-frontmatter.md +73 -0
- package/agent-assets/skills/context/references/snapshot-files.md +103 -0
- package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +4 -4
- package/agent-assets/skills/docs-search/SKILL.md +17 -16
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +14 -26
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +14 -26
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +14 -26
- package/agent-assets/skills/external-services/SKILL.md +9 -262
- package/agent-assets/skills/external-services/SKILL.native.claude.md +6 -7
- package/agent-assets/skills/external-services/SKILL.native.codex.md +8 -9
- package/agent-assets/skills/external-services/SKILL.native.gemini.md +5 -6
- package/agent-assets/skills/external-services/references/calendar-apple.md +97 -0
- package/agent-assets/skills/external-services/references/calendar-google.md +72 -0
- package/agent-assets/skills/external-services/references/calendar-outlook.md +36 -0
- package/agent-assets/skills/external-services/references/github.md +17 -0
- package/agent-assets/skills/external-services/references/obsidian.md +49 -0
- package/agent-assets/skills/external-services/references/skills-crud.md +27 -0
- package/agent-assets/skills/gmail-lifestyle/SKILL.md +151 -0
- package/agent-assets/skills/gmail-lifestyle/references/receipts-api.md +93 -0
- package/agent-assets/skills/gmail-lifestyle/references/travel-bookings-api.md +75 -0
- package/agent-assets/skills/mail/SKILL.delegated.claude.md +15 -6
- package/agent-assets/skills/mail/SKILL.delegated.codex.md +9 -5
- package/agent-assets/skills/mail/SKILL.delegated.gemini.md +9 -5
- package/agent-assets/skills/mail/SKILL.md +9 -114
- package/agent-assets/skills/mail/SKILL.native.claude.md +1 -1
- package/agent-assets/skills/mail/SKILL.native.codex.md +1 -1
- package/agent-assets/skills/mail/SKILL.native.gemini.md +1 -1
- package/agent-assets/skills/mail/references/api.md +110 -0
- package/agent-assets/skills/mail/references/examples.md +70 -0
- package/agent-assets/skills/mail/references/providers.md +8 -8
- package/agent-assets/skills/managed-tasks/SKILL.md +472 -0
- package/agent-assets/skills/managed-tasks/references/errors.md +73 -0
- package/agent-assets/skills/managed-tasks/references/output-path.md +75 -0
- package/agent-assets/skills/managed-tasks/references/recurrence-rule.md +86 -0
- package/agent-assets/skills/management-policy/SKILL.md +54 -125
- package/agent-assets/skills/management-policy/curation.json +1 -1
- package/agent-assets/skills/management-policy/references/policy-workflow.md +101 -0
- package/agent-assets/skills/management-policy/seeds/policy-file-shape.seed.json +1 -1
- package/agent-assets/skills/notify/SKILL.md +10 -82
- package/agent-assets/skills/notify/references/priority.md +65 -0
- package/agent-assets/skills/notion/SKILL.delegated.claude.md +2 -2
- package/agent-assets/skills/notion/SKILL.delegated.codex.md +2 -2
- package/agent-assets/skills/notion/SKILL.delegated.gemini.md +2 -2
- package/agent-assets/skills/notion/SKILL.md +6 -10
- package/agent-assets/skills/notion/SKILL.native.claude.md +11 -8
- package/agent-assets/skills/notion/SKILL.native.codex.md +10 -6
- package/agent-assets/skills/notion/SKILL.native.gemini.md +10 -6
- package/agent-assets/skills/observations/SKILL.md +25 -14
- package/agent-assets/skills/project-doc/SKILL.md +2 -6
- package/agent-assets/skills/project-doc/curation.json +3 -3
- package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +7 -4
- package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +3 -3
- package/agent-assets/skills/reading/SKILL.md +12 -2
- package/agent-assets/skills/reading/references/reading-taste.md +2 -2
- package/agent-assets/skills/roadmap/SKILL.md +43 -141
- package/agent-assets/skills/roadmap/curation.json +1 -1
- package/agent-assets/skills/roadmap/references/api.md +100 -0
- package/agent-assets/skills/roadmap/references/cross-check.md +80 -0
- package/agent-assets/skills/roadmap/references/migration.md +56 -0
- package/agent-assets/skills/roadmap/references/preparation-timeline.md +2 -2
- package/agent-assets/skills/roadmap/seeds/entry-types.seed.json +1 -1
- package/agent-assets/skills/schedule/SKILL.md +76 -104
- package/agent-assets/skills/schedule/references/batch.md +93 -0
- package/agent-assets/skills/schedule/references/errors.md +217 -0
- package/agent-assets/skills/schedule/references/model-selection.md +96 -0
- package/agent-assets/skills/schedule/references/recurrence-rule.md +86 -0
- package/agent-assets/skills/scheduled-managed-task/SKILL.md +59 -51
- package/agent-assets/skills/today/SKILL.md +32 -62
- package/agent-assets/skills/today/curation.json +3 -3
- package/agent-assets/skills/today/references/agent-plan-lifecycle.md +114 -0
- package/agent-assets/skills/today/seeds/section-shape.seed.json +1 -1
- package/agent-assets/skills/user-interview/SKILL.md +23 -67
- package/agent-assets/skills/user-interview/references/op-briefing.md +51 -0
- package/agent-assets/skills/user-interview/references/op-morning.md +59 -0
- package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +9 -1
- package/agent-assets/skills/user-profile/SKILL.md +54 -74
- package/agent-assets/skills/user-profile/curation.json +2 -2
- package/agent-assets/skills/user-profile/references/character-preferences.md +83 -0
- package/agent-assets/skills/user-profile/seeds/routing-table.seed.json +8 -8
- package/agent-assets/skills/user-profile/seeds/topic-files.seed.json +30 -2
- package/agent-assets/skills/wiki/wiki-ask/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-compile/SKILL.md +4 -5
- package/agent-assets/skills/wiki/wiki-connect/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-graduate/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-lint/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-trace/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +0 -1
- package/agent-assets/system-prompts/routine-fetch-window.md +78 -0
- package/agent-assets/system-prompts/skill-index-instruction.md +26 -0
- package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +20 -11
- package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +18 -9
- package/agent-assets/task-flows/_partials/capture-user-info.md +24 -0
- package/agent-assets/task-flows/_partials/confirm-subflow.md +68 -0
- package/agent-assets/task-flows/_partials/dm-intent.long-horizon.md +35 -0
- package/agent-assets/task-flows/_partials/dm-intent.project.md +391 -0
- package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +20 -11
- package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +18 -9
- package/agent-assets/task-flows/_partials/notion-acquire.notion.md +26 -15
- package/agent-assets/task-flows/browser_task.md +84 -0
- 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.workflow_run.failed.md +2 -2
- package/agent-assets/task-flows/knowledge.import.md +15 -15
- package/agent-assets/task-flows/message.received.dm.md +20 -17
- package/agent-assets/task-flows/message.received.dm_first.md +11 -15
- package/agent-assets/task-flows/routine.custom.md +6 -4
- package/agent-assets/task-flows/routine.evening_review.md +46 -170
- package/agent-assets/task-flows/routine.fetch_window.md +19 -14
- package/agent-assets/task-flows/routine.hourly_check.md +27 -15
- package/agent-assets/task-flows/routine.hourly_check.triage.md +1 -1
- package/agent-assets/task-flows/routine.monthly_review.md +67 -25
- package/agent-assets/task-flows/routine.morning_routine_journal.md +135 -0
- package/agent-assets/task-flows/routine.morning_routine_today.md +673 -0
- package/agent-assets/task-flows/routine.research_cluster_update.md +35 -0
- package/agent-assets/task-flows/routine.research_dispatch.md +38 -0
- package/agent-assets/task-flows/routine.research_offer_dm.md +125 -0
- package/agent-assets/task-flows/routine.research_wiki_summary.md +53 -0
- package/agent-assets/task-flows/routine.roadmap_refresh.md +68 -23
- package/agent-assets/task-flows/routine.today_refresh.md +4 -4
- package/agent-assets/task-flows/routine.user_profile_sweep.md +19 -20
- package/agent-assets/task-flows/routine.weekly_review.md +370 -86
- package/agent-assets/task-flows/schedule.approaching.md +0 -1
- package/agent-assets/task-flows/scheduled.dm.md +13 -13
- package/agent-assets/task-flows/scheduled.task.md +9 -9
- package/agent-assets/task-flows/setup.initial.md +171 -251
- package/agent-assets/task-flows/setup.update.md +2 -2
- package/agent-assets/task-flows/wiki.ingest_url.md +1 -1
- package/agent-assets/templates/README.md +27 -20
- package/agent-assets/templates/_index.md +42 -26
- package/agent-assets/templates/_manifest.json +34 -99
- package/agent-assets/templates/{user → identity}/_index.md +1 -1
- package/agent-assets/templates/identity/expertise.md +9 -0
- package/agent-assets/templates/identity/goals.md +9 -0
- package/agent-assets/templates/identity/people.md +13 -0
- package/agent-assets/templates/identity/personal.md +9 -0
- package/agent-assets/templates/{user → identity}/profile.md +2 -2
- package/agent-assets/templates/identity/work.md +9 -0
- package/agent-assets/templates/{dossiers → knowledge/dossiers}/_index.md +2 -2
- package/agent-assets/templates/{projects → plans/projects}/_active.base +1 -1
- package/agent-assets/templates/policies/_index.md +21 -0
- package/agent-assets/templates/{rules → policies}/journal-export.md +1 -1
- package/agent-assets/templates/policies/journal-format.md +168 -0
- package/agent-assets/templates/{rules/policies → policies/management-captures}/_index.md +2 -2
- package/agent-assets/templates/{rules → policies}/management.md +3 -3
- package/agent-assets/templates/{rules → policies}/mcp.md +1 -1
- package/agent-assets/templates/{rules → policies}/redaction.md +1 -1
- package/agent-assets/templates/{routines → policies/routines}/_index.md +1 -1
- package/agent-assets/templates/{routines → policies/routines}/evening.md +2 -2
- package/agent-assets/templates/{routines → policies/routines}/hourly.md +1 -1
- package/agent-assets/templates/{routines → policies/routines}/monthly.md +2 -2
- package/bin/aitne.mjs +21 -5
- package/package.json +5 -4
- package/scripts/commands/doctor.mjs +63 -5
- package/scripts/commands/run-now.mjs +187 -0
- package/scripts/commands/verify.mjs +264 -0
- package/scripts/lib/ports.d.mts +27 -0
- package/scripts/lib/ports.mjs +36 -0
- package/scripts/lib/read-api-token.mjs +176 -0
- package/scripts/start.mjs +2 -1
- package/agent-assets/docs/features/lifestyle/travel-time.md +0 -52
- package/agent-assets/docs/features/routines/monthly-review.md +0 -65
- package/agent-assets/skills/management-task-modify/SKILL.md +0 -203
- package/agent-assets/skills/management-task-register/SKILL.md +0 -330
- package/agent-assets/skills/management-task-stop/SKILL.md +0 -166
- package/agent-assets/skills/receipts/SKILL.md +0 -134
- package/agent-assets/skills/travel/SKILL.md +0 -132
- package/agent-assets/skills/travel-time/SKILL.md +0 -158
- package/agent-assets/task-flows/routine.morning_routine.md +0 -322
- package/agent-assets/task-flows/routine.morning_routine_initial.md +0 -204
- package/agent-assets/templates/context-index.md +0 -42
- package/agent-assets/templates/rules/_index.md +0 -19
- package/agent-assets/templates/rules/journal-format.md +0 -61
- package/agent-assets/templates/user/expertise.md +0 -7
- package/agent-assets/templates/user/goals.md +0 -7
- package/agent-assets/templates/user/people.md +0 -7
- package/agent-assets/templates/user/personal.md +0 -7
- package/agent-assets/templates/user/work.md +0 -7
- /package/agent-assets/templates/{agent/journal.md → journal/agent.md} +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/evening.md +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/hourly.md +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/monthly.md +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/morning.md +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/roadmap.md +0 -0
- /package/agent-assets/templates/{dossiers → knowledge/dossiers}/weekly.md +0 -0
- /package/agent-assets/templates/{projects → plans/projects}/_index.md +0 -0
- /package/agent-assets/templates/{roadmap.md → plans/roadmap.md} +0 -0
- /package/agent-assets/templates/{routines → policies/routines}/morning.md +0 -0
- /package/agent-assets/templates/{routines → policies/routines}/weekly.md +0 -0
- /package/agent-assets/templates/{agent → state}/profile-questions.md +0 -0
- /package/agent-assets/templates/{today.md → state/today.md} +0 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aitne verify <target>` — post-launch verification for shipped design
|
|
3
|
+
* surfaces. Each target bundles a small set of pass/warn/fail checks an
|
|
4
|
+
* operator runs once after a rollout to confirm the change actually
|
|
5
|
+
* delivered what it promised.
|
|
6
|
+
*
|
|
7
|
+
* Targets:
|
|
8
|
+
* - `evening-review-slimdown` — Phase 4 of
|
|
9
|
+
* `docs/design/appendices/evening-review-slimdown.md`. Confirms the
|
|
10
|
+
* four post-launch invariants the doc lists (cron audit freshness,
|
|
11
|
+
* token-envelope drop, conditional notify load, 30-day notify
|
|
12
|
+
* invocation sample).
|
|
13
|
+
*
|
|
14
|
+
* Verify is read-only and offline. No daemon HTTP call, no DB writes,
|
|
15
|
+
* no network. Safe to run while the daemon is up (the daemon enables
|
|
16
|
+
* WAL — concurrent readers are fine) or while it is stopped (we open
|
|
17
|
+
* the SQLite file in readonly mode).
|
|
18
|
+
*
|
|
19
|
+
* The check logic itself lives in
|
|
20
|
+
* `packages/daemon/src/core/evening-review-verify.ts` so the rulebook
|
|
21
|
+
* predicate is reused verbatim from the daemon (no drift risk) and the
|
|
22
|
+
* checks are unit-testable under the daemon's coverage gate. This file
|
|
23
|
+
* is a thin CLI wrapper: parse args → resolve contextDir → call the
|
|
24
|
+
* typed runner → render.
|
|
25
|
+
*
|
|
26
|
+
* Exit codes:
|
|
27
|
+
* 0 every check returned pass or warn
|
|
28
|
+
* 1 at least one check returned fail
|
|
29
|
+
* 2 argument error / unknown target
|
|
30
|
+
* 3 the SQLite file or daemon dist is missing
|
|
31
|
+
*/
|
|
32
|
+
import fs from "node:fs";
|
|
33
|
+
import path from "node:path";
|
|
34
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
35
|
+
|
|
36
|
+
const KNOWN_TARGETS = new Set(["evening-review-slimdown"]);
|
|
37
|
+
|
|
38
|
+
export async function run(args, ctx) {
|
|
39
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
40
|
+
printHelp();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const opts = parseArgs(args);
|
|
44
|
+
|
|
45
|
+
if (!KNOWN_TARGETS.has(opts.target)) {
|
|
46
|
+
process.stderr.write(`Unknown verify target: ${opts.target}\n`);
|
|
47
|
+
process.stderr.write(`Available targets: ${[...KNOWN_TARGETS].join(", ")}\n`);
|
|
48
|
+
process.exit(2);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const dbPath = path.join(ctx.DATA_DIR, "data", "personal_agent.db");
|
|
52
|
+
if (!fs.existsSync(dbPath)) {
|
|
53
|
+
process.stderr.write(
|
|
54
|
+
`SQLite file not found at ${dbPath}.\n` +
|
|
55
|
+
`Has the daemon been started? Run \`aitne start\` first.\n`,
|
|
56
|
+
);
|
|
57
|
+
process.exit(3);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const verifyMod = await loadVerifyModule(ctx.PROJECT_ROOT);
|
|
61
|
+
if (!verifyMod) {
|
|
62
|
+
process.stderr.write(
|
|
63
|
+
"Daemon dist is missing — `packages/daemon/dist/core/evening-review-verify.js` " +
|
|
64
|
+
"did not resolve.\nRun `aitne build` first (or `aitne start`, which builds " +
|
|
65
|
+
"if stale).\n",
|
|
66
|
+
);
|
|
67
|
+
process.exit(3);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const { loadBetterSqlite3 } = await import("../lib/sqlite-loader.mjs");
|
|
71
|
+
const Database = await loadBetterSqlite3(ctx.PROJECT_ROOT);
|
|
72
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
73
|
+
|
|
74
|
+
let report;
|
|
75
|
+
try {
|
|
76
|
+
const contextDir = verifyMod.resolveContextDirFromDb(db, ctx.DATA_DIR);
|
|
77
|
+
report = verifyMod.runEveningReviewSlimdownChecks({
|
|
78
|
+
db,
|
|
79
|
+
contextDir,
|
|
80
|
+
windowDays: opts.days,
|
|
81
|
+
});
|
|
82
|
+
} finally {
|
|
83
|
+
db.close();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (opts.json) {
|
|
87
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
88
|
+
process.exit(report.summary.failed > 0 ? 1 : 0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
printReport(opts.target, report, ctx);
|
|
92
|
+
process.exit(report.summary.failed > 0 ? 1 : 0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
96
|
+
// CLI parsing
|
|
97
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
function parseArgs(args) {
|
|
100
|
+
const opts = {
|
|
101
|
+
target: "evening-review-slimdown",
|
|
102
|
+
days: 7,
|
|
103
|
+
json: false,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
let positional = null;
|
|
107
|
+
for (let i = 0; i < args.length; i++) {
|
|
108
|
+
const a = args[i];
|
|
109
|
+
if (a === "--json") {
|
|
110
|
+
opts.json = true;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (a === "--days") {
|
|
114
|
+
if (i + 1 >= args.length) {
|
|
115
|
+
process.stderr.write("--days requires a value\n");
|
|
116
|
+
process.exit(2);
|
|
117
|
+
}
|
|
118
|
+
const raw = args[++i];
|
|
119
|
+
const n = parseInt(raw, 10);
|
|
120
|
+
if (!Number.isFinite(n) || n <= 0 || n > 365) {
|
|
121
|
+
process.stderr.write(`--days must be a positive integer ≤ 365 (got: ${raw})\n`);
|
|
122
|
+
process.exit(2);
|
|
123
|
+
}
|
|
124
|
+
opts.days = n;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (a.startsWith("-")) {
|
|
128
|
+
process.stderr.write(`Unknown flag: ${a}\n`);
|
|
129
|
+
process.stderr.write("See `aitne verify --help`.\n");
|
|
130
|
+
process.exit(2);
|
|
131
|
+
}
|
|
132
|
+
if (positional !== null) {
|
|
133
|
+
process.stderr.write(`Unexpected positional argument: ${a}\n`);
|
|
134
|
+
process.exit(2);
|
|
135
|
+
}
|
|
136
|
+
positional = a;
|
|
137
|
+
}
|
|
138
|
+
if (positional !== null) opts.target = positional;
|
|
139
|
+
return opts;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
143
|
+
// Daemon module + contextDir resolution
|
|
144
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Dynamically import the compiled `evening-review-verify` module from
|
|
148
|
+
* the daemon's dist directory. Returns null when the dist is missing so
|
|
149
|
+
* the caller can surface a clear "build first" hint instead of a stack
|
|
150
|
+
* trace.
|
|
151
|
+
*
|
|
152
|
+
* Three resolution paths cover every shipping shape:
|
|
153
|
+
*
|
|
154
|
+
* 1. Workspace dev — pnpm symlinks `node_modules/@aitne/daemon` →
|
|
155
|
+
* `packages/daemon`, so the compiled module sits under the repo's
|
|
156
|
+
* own `packages/daemon/dist/`. Direct filesystem path.
|
|
157
|
+
* 2. Published install — `npm i -g @aitne-sh/aitne` installs
|
|
158
|
+
* `@aitne/daemon` as a sibling under `<install>/node_modules/`.
|
|
159
|
+
* The daemon's `package.json` only exports `.` (its barrel
|
|
160
|
+
* index), so `import("@aitne/daemon/core/...")` is blocked by
|
|
161
|
+
* Node's exports-field gate. Resolve the barrel via
|
|
162
|
+
* `import.meta.resolve("@aitne/daemon")` to get the daemon root,
|
|
163
|
+
* then reach the sibling file directly.
|
|
164
|
+
* 3. Legacy flatten — historical install layout where `dist/` ended up
|
|
165
|
+
* at the project root. Kept as a last-resort fallback so a future
|
|
166
|
+
* build/publish change doesn't silently break this CLI.
|
|
167
|
+
*
|
|
168
|
+
* The barrel `index.ts` does NOT re-export this module by design —
|
|
169
|
+
* verify is operator-tooling, not a daemon API surface — so we always
|
|
170
|
+
* go through the filesystem path rather than `import("@aitne/daemon")`.
|
|
171
|
+
*/
|
|
172
|
+
async function loadVerifyModule(projectRoot) {
|
|
173
|
+
const candidates = [
|
|
174
|
+
// 1. Workspace dev (pnpm symlink).
|
|
175
|
+
path.join(projectRoot, "packages/daemon/dist/core/evening-review-verify.js"),
|
|
176
|
+
];
|
|
177
|
+
// 2. Published install — resolve via the daemon's own package root.
|
|
178
|
+
try {
|
|
179
|
+
const daemonMainUrl = import.meta.resolve("@aitne/daemon");
|
|
180
|
+
const daemonMainPath = fileURLToPath(daemonMainUrl);
|
|
181
|
+
candidates.push(
|
|
182
|
+
path.join(path.dirname(daemonMainPath), "core/evening-review-verify.js"),
|
|
183
|
+
);
|
|
184
|
+
} catch {
|
|
185
|
+
// @aitne/daemon not resolvable from this context — fall through to
|
|
186
|
+
// the legacy candidate below.
|
|
187
|
+
}
|
|
188
|
+
// 3. Legacy flatten fallback (defensive).
|
|
189
|
+
candidates.push(path.join(projectRoot, "dist/core/evening-review-verify.js"));
|
|
190
|
+
|
|
191
|
+
for (const candidate of candidates) {
|
|
192
|
+
if (fs.existsSync(candidate)) {
|
|
193
|
+
return import(pathToFileURL(candidate).href);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ContextDir resolution lives in the typed daemon module
|
|
200
|
+
// (`resolveContextDirFromDb`) so the degraded-mode branch + tilde
|
|
201
|
+
// expansion are unit-tested in lockstep with `getContextDir`.
|
|
202
|
+
|
|
203
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
204
|
+
// Output
|
|
205
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
function printReport(target, report, ctx) {
|
|
208
|
+
console.log(`${ctx.APP_NAME} verify ${target} — ${report.checks.length} check(s)`);
|
|
209
|
+
console.log("");
|
|
210
|
+
const labelWidth = Math.max(...report.checks.map((c) => c.label.length));
|
|
211
|
+
for (const c of report.checks) {
|
|
212
|
+
const mark = c.status === "pass" ? "ok " : c.status === "warn" ? "warn" : "FAIL";
|
|
213
|
+
const label = c.label.padEnd(labelWidth);
|
|
214
|
+
console.log(` [${mark}] ${label} ${c.detail}`);
|
|
215
|
+
if (c.hint && c.status !== "pass") {
|
|
216
|
+
console.log(` ${" ".repeat(labelWidth)} hint: ${c.hint}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const { passed, warned, failed, windowDays, installAgeDays } = report.summary;
|
|
220
|
+
console.log("");
|
|
221
|
+
console.log(
|
|
222
|
+
`${passed} ok · ${warned} warn · ${failed} fail · window ${windowDays}d · install age ~${installAgeDays}d`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
227
|
+
// Help
|
|
228
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
function printHelp() {
|
|
231
|
+
console.log(`Usage: aitne verify [target] [flags]
|
|
232
|
+
|
|
233
|
+
Run post-launch verification for a shipped design surface. Read-only —
|
|
234
|
+
no daemon HTTP call required, no DB writes, no network. Safe to invoke
|
|
235
|
+
any time.
|
|
236
|
+
|
|
237
|
+
Targets:
|
|
238
|
+
evening-review-slimdown (default)
|
|
239
|
+
Phase 4 of docs/design/appendices/evening-review-slimdown.md.
|
|
240
|
+
Bundles four checks:
|
|
241
|
+
1. Daily 17:45 \`roadmap_mechanical_maintenance\` audit row.
|
|
242
|
+
2. evening_review session envelope (cost / turns / tokens).
|
|
243
|
+
3. Conditional notify load (resolveSkillManifest mirror).
|
|
244
|
+
4. 30-day notify invocations attributable to evening_review.
|
|
245
|
+
|
|
246
|
+
Flags:
|
|
247
|
+
--days <N> Window for time-bounded checks (default 7, max 365).
|
|
248
|
+
Capped at install age automatically; the 30-day notify
|
|
249
|
+
sample uses min(30, install age) regardless.
|
|
250
|
+
--json Machine-readable output. Implies no terminal formatting.
|
|
251
|
+
-h, --help Print this message.
|
|
252
|
+
|
|
253
|
+
Exit codes:
|
|
254
|
+
0 every check returned pass or warn
|
|
255
|
+
1 at least one check returned fail
|
|
256
|
+
2 argument error / unknown target
|
|
257
|
+
3 SQLite file or daemon dist missing — run \`aitne start\` once first
|
|
258
|
+
|
|
259
|
+
Examples:
|
|
260
|
+
aitne verify
|
|
261
|
+
aitne verify evening-review-slimdown --days 14
|
|
262
|
+
aitne verify --json | jq '.summary'
|
|
263
|
+
aitne verify --json | jq '.checks[] | select(.status != "pass")'`);
|
|
264
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for the plain-ESM launcher mirror `ports.mjs`.
|
|
3
|
+
*
|
|
4
|
+
* `ports.mjs` is hand-written JavaScript (it must run before the TypeScript
|
|
5
|
+
* build), so it carries no inferred types. This sidecar lets TypeScript
|
|
6
|
+
* consumers — notably the `packages/shared/src/ports.test.ts` drift guard,
|
|
7
|
+
* which imports this module to assert it stays in lockstep with the TS
|
|
8
|
+
* source-of-truth `packages/shared/src/ports.ts` — typecheck the import under
|
|
9
|
+
* `strict`. Keep these signatures identical to `ports.ts`'s exports (minus
|
|
10
|
+
* `loopbackOrigins`, which is TS-only and not mirrored here).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Daemon HTTP API port. Overridable via `PA_API_PORT`. */
|
|
14
|
+
export const DEFAULT_API_PORT: number;
|
|
15
|
+
|
|
16
|
+
/** Dashboard (Next.js) port. Overridable via `PA_DASHBOARD_PORT`. */
|
|
17
|
+
export const DEFAULT_DASHBOARD_PORT: number;
|
|
18
|
+
|
|
19
|
+
/** Resolve the daemon API port from env, falling back to DEFAULT_API_PORT. */
|
|
20
|
+
export function resolveApiPort(
|
|
21
|
+
env?: Record<string, string | undefined>,
|
|
22
|
+
): number;
|
|
23
|
+
|
|
24
|
+
/** Resolve the dashboard port from env, falling back to DEFAULT_DASHBOARD_PORT. */
|
|
25
|
+
export function resolveDashboardPort(
|
|
26
|
+
env?: Record<string, string | undefined>,
|
|
27
|
+
): number;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default network ports for the Aitne daemon API and dashboard.
|
|
3
|
+
*
|
|
4
|
+
* SINGLE SOURCE OF TRUTH (launcher / plain-ESM side). `bin/aitne.mjs` and the
|
|
5
|
+
* `scripts/**` launchers cannot import `@aitne/shared`: they run *before* the
|
|
6
|
+
* TypeScript build that produces it (running `aitne start` is what triggers
|
|
7
|
+
* that build), and the published package ships only `bin` + `scripts/*.mjs` +
|
|
8
|
+
* `agent-assets`, never `packages/`. So the defaults are mirrored here in a
|
|
9
|
+
* build-independent module that lives under the published `scripts/lib/`.
|
|
10
|
+
*
|
|
11
|
+
* The TypeScript mirror lives in `packages/shared/src/ports.ts`. The two are
|
|
12
|
+
* pinned together by `packages/shared/src/ports.test.ts`, which fails CI if
|
|
13
|
+
* the values ever drift. Change a default in BOTH or the test goes red.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Daemon HTTP API port. Overridable via `PA_API_PORT`. */
|
|
17
|
+
export const DEFAULT_API_PORT = 8321;
|
|
18
|
+
|
|
19
|
+
/** Dashboard (Next.js) port. Overridable via `PA_DASHBOARD_PORT`. Not 3000 — that collides with most dev servers. */
|
|
20
|
+
export const DEFAULT_DASHBOARD_PORT = 8322;
|
|
21
|
+
|
|
22
|
+
function parsePort(raw) {
|
|
23
|
+
if (raw == null || raw === "") return null;
|
|
24
|
+
const n = Number.parseInt(raw, 10);
|
|
25
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Resolve the daemon API port from env, falling back to DEFAULT_API_PORT. */
|
|
29
|
+
export function resolveApiPort(env = process.env) {
|
|
30
|
+
return parsePort(env.PA_API_PORT) ?? DEFAULT_API_PORT;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Resolve the dashboard port from env, falling back to DEFAULT_DASHBOARD_PORT. */
|
|
34
|
+
export function resolveDashboardPort(env = process.env) {
|
|
35
|
+
return parsePort(env.PA_DASHBOARD_PORT) ?? DEFAULT_DASHBOARD_PORT;
|
|
36
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform reader for the daemon's `apiToken` secret.
|
|
3
|
+
*
|
|
4
|
+
* CLI scripts (`run-now`, `remint-roadmap-ids`) need the daemon's apiToken to
|
|
5
|
+
* call Approve-tier `/api/...` routes, but they intentionally must run WITHOUT
|
|
6
|
+
* a successful `@aitne/shared` build (which only ships `./dist/*.js`). So this
|
|
7
|
+
* helper re-implements the per-OS read inline, mirroring the secret clients in
|
|
8
|
+
* `packages/shared/src/`:
|
|
9
|
+
*
|
|
10
|
+
* - darwin → macOS Keychain via `security` (service com.personal-agent.secret.apiToken)
|
|
11
|
+
* - win32 → DPAPI: decrypt ~/.personal-agent/secrets/apiToken.dpapi via PowerShell
|
|
12
|
+
* - linux → libsecret (`secret-tool lookup`), else the AES-256-GCM file store
|
|
13
|
+
* - WSL / other → the AES-256-GCM file store
|
|
14
|
+
*
|
|
15
|
+
* The file-store format/params and the DPAPI script are copied verbatim from
|
|
16
|
+
* `secret-client-file.ts` / `secret-client-windows.ts` — keep them in sync if
|
|
17
|
+
* those change. The secret clients hardcode `~/.personal-agent/secrets` (they
|
|
18
|
+
* do NOT honor PA_DATA_DIR), so this helper uses the same homedir-relative
|
|
19
|
+
* location to find what the daemon actually wrote.
|
|
20
|
+
*
|
|
21
|
+
* Returns the token string, or null when it cannot be read; the caller decides
|
|
22
|
+
* how to message the failure. Best-effort: never throws (so a CLI never dies
|
|
23
|
+
* with a raw stack trace on a misconfigured secret store).
|
|
24
|
+
*/
|
|
25
|
+
import { execFileSync } from "node:child_process";
|
|
26
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
27
|
+
import { homedir } from "node:os";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { createDecipheriv, scryptSync } from "node:crypto";
|
|
30
|
+
|
|
31
|
+
const SECRET_NAME = "apiToken";
|
|
32
|
+
const KEYCHAIN_SERVICE = "com.personal-agent.secret.apiToken";
|
|
33
|
+
|
|
34
|
+
function secretsDir() {
|
|
35
|
+
return join(homedir(), ".personal-agent", "secrets");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** @returns {string | null} the daemon apiToken, or null if unreadable. */
|
|
39
|
+
export function readApiToken() {
|
|
40
|
+
const platform = process.platform;
|
|
41
|
+
if (platform === "darwin") return readDarwin();
|
|
42
|
+
if (platform === "win32") return readWindows();
|
|
43
|
+
if (platform === "linux") {
|
|
44
|
+
if (!isWsl() && whichSync("secret-tool")) {
|
|
45
|
+
const fromKeyring = readSecretTool();
|
|
46
|
+
if (fromKeyring) return fromKeyring;
|
|
47
|
+
}
|
|
48
|
+
return readFileStore();
|
|
49
|
+
}
|
|
50
|
+
return readFileStore();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readDarwin() {
|
|
54
|
+
// Byte-identical to the historical `security` read so macOS cannot regress.
|
|
55
|
+
try {
|
|
56
|
+
return execFileSync(
|
|
57
|
+
"security",
|
|
58
|
+
["find-generic-password", "-s", KEYCHAIN_SERVICE, "-w"],
|
|
59
|
+
{ encoding: "utf-8" },
|
|
60
|
+
).trim();
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Cross-platform `which`, returning the resolved path or null. */
|
|
67
|
+
function whichSync(cmd) {
|
|
68
|
+
const tool = process.platform === "win32" ? "where" : "which";
|
|
69
|
+
try {
|
|
70
|
+
const out = execFileSync(tool, [cmd], {
|
|
71
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
72
|
+
timeout: 2_000,
|
|
73
|
+
});
|
|
74
|
+
return out.toString().split(/\r?\n/)[0]?.trim() || null;
|
|
75
|
+
} catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function readWindows() {
|
|
81
|
+
const path = join(secretsDir(), `${SECRET_NAME}.dpapi`);
|
|
82
|
+
if (!existsSync(path)) return null;
|
|
83
|
+
const encrypted = readFileSync(path, "utf-8").trim();
|
|
84
|
+
// Prefer in-box Windows PowerShell 5.1, fall back to PowerShell 7+ (pwsh),
|
|
85
|
+
// matching the daemon's secret-client-factory resolution order.
|
|
86
|
+
const psBinary = whichSync("powershell.exe")
|
|
87
|
+
? "powershell.exe"
|
|
88
|
+
: whichSync("pwsh.exe")
|
|
89
|
+
? "pwsh.exe"
|
|
90
|
+
: "powershell.exe";
|
|
91
|
+
// Mirrors WindowsDpapiSecretClient.get(): DPAPI-decrypt via
|
|
92
|
+
// ConvertTo-SecureString and marshal back to plaintext. The ciphertext is
|
|
93
|
+
// passed via stdin, never interpolated into the script, to avoid injection.
|
|
94
|
+
const script = [
|
|
95
|
+
"$enc = [System.Console]::In.ReadToEnd().Trim()",
|
|
96
|
+
"$ss = ConvertTo-SecureString $enc",
|
|
97
|
+
"$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ss)",
|
|
98
|
+
"try { [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) }",
|
|
99
|
+
"finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) }",
|
|
100
|
+
].join("; ");
|
|
101
|
+
try {
|
|
102
|
+
const out = execFileSync(
|
|
103
|
+
psBinary,
|
|
104
|
+
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
105
|
+
{ input: encrypted, encoding: "utf-8", timeout: 10_000 },
|
|
106
|
+
);
|
|
107
|
+
return out.trimEnd() || null;
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function readSecretTool() {
|
|
114
|
+
try {
|
|
115
|
+
const out = execFileSync(
|
|
116
|
+
"secret-tool",
|
|
117
|
+
["lookup", "service", "personal-agent", "key", SECRET_NAME],
|
|
118
|
+
{ encoding: "utf-8", timeout: 5_000 },
|
|
119
|
+
);
|
|
120
|
+
return out.replace(/\n$/, "") || null;
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Detect WSL. WSL reports platform "linux" but cannot use `secret-tool`
|
|
128
|
+
* (D-Bus / GNOME Keyring typically unavailable), so it uses the file store.
|
|
129
|
+
*/
|
|
130
|
+
function isWsl() {
|
|
131
|
+
try {
|
|
132
|
+
return /microsoft|wsl/i.test(readFileSync("/proc/version", "utf-8"));
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── AES-256-GCM file store (mirrors secret-client-file.ts) ────────────────
|
|
139
|
+
const FILE_ALGORITHM = "aes-256-gcm";
|
|
140
|
+
const FILE_KEY_LENGTH = 32; // 256 bits
|
|
141
|
+
const FILE_SCRYPT = { N: 16384, r: 8, p: 1 };
|
|
142
|
+
|
|
143
|
+
/** Resolve the file-store master password (env, then key file); null if none. */
|
|
144
|
+
function resolveMasterPassword() {
|
|
145
|
+
if (process.env.PA_MASTER_PASSWORD) return process.env.PA_MASTER_PASSWORD;
|
|
146
|
+
const keyFilePath = join(secretsDir(), ".master-key");
|
|
147
|
+
if (!existsSync(keyFilePath)) return null;
|
|
148
|
+
// Refuse to read a key file with insecure permissions (mirrors the daemon's
|
|
149
|
+
// 0600/0400 gate); degrade to null rather than risk exposing it.
|
|
150
|
+
const mode = statSync(keyFilePath).mode & 0o777;
|
|
151
|
+
if (mode !== 0o600 && mode !== 0o400) return null;
|
|
152
|
+
return readFileSync(keyFilePath, "utf-8").trim();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function readFileStore() {
|
|
156
|
+
const path = join(secretsDir(), `${SECRET_NAME}.enc`);
|
|
157
|
+
if (!existsSync(path)) return null;
|
|
158
|
+
try {
|
|
159
|
+
const password = resolveMasterPassword();
|
|
160
|
+
if (!password) return null;
|
|
161
|
+
const stored = JSON.parse(readFileSync(path, "utf-8"));
|
|
162
|
+
const salt = Buffer.from(stored.salt, "hex");
|
|
163
|
+
const iv = Buffer.from(stored.iv, "hex");
|
|
164
|
+
const authTag = Buffer.from(stored.authTag, "hex");
|
|
165
|
+
const ciphertext = Buffer.from(stored.ciphertext, "hex");
|
|
166
|
+
const key = scryptSync(password, salt, FILE_KEY_LENGTH, FILE_SCRYPT);
|
|
167
|
+
const decipher = createDecipheriv(FILE_ALGORITHM, key, iv);
|
|
168
|
+
decipher.setAuthTag(authTag);
|
|
169
|
+
return Buffer.concat([
|
|
170
|
+
decipher.update(ciphertext),
|
|
171
|
+
decipher.final(),
|
|
172
|
+
]).toString("utf-8");
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
package/scripts/start.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import path from "node:path";
|
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import { ensureBuild, log } from "./run-node.mjs";
|
|
8
8
|
import { openBrowser, waitForHttpReady } from "./browser.mjs";
|
|
9
|
+
import { resolveDashboardPort } from "./lib/ports.mjs";
|
|
9
10
|
|
|
10
11
|
const IS_WINDOWS = process.platform === "win32";
|
|
11
12
|
const requireFromScript = createRequire(import.meta.url);
|
|
@@ -57,7 +58,7 @@ function nextSpawnArgs(dashboardDir, nextBin, userArgs) {
|
|
|
57
58
|
* 5. Ctrl+C stops both
|
|
58
59
|
*/
|
|
59
60
|
|
|
60
|
-
const DASHBOARD_PORT =
|
|
61
|
+
const DASHBOARD_PORT = resolveDashboardPort();
|
|
61
62
|
const noOpen = process.argv.slice(2).includes("--no-open");
|
|
62
63
|
const children = [];
|
|
63
64
|
let shuttingDown = false;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
schema_version: 1
|
|
3
|
-
slug: features/lifestyle/travel-time
|
|
4
|
-
title: Travel Time
|
|
5
|
-
id: travel-time
|
|
6
|
-
aliases:
|
|
7
|
-
- door to door
|
|
8
|
-
- eta
|
|
9
|
-
category: features
|
|
10
|
-
summary: |
|
|
11
|
-
A skill that estimates door-to-door travel time given an origin
|
|
12
|
-
and destination — used by schedule-approaching reminders for
|
|
13
|
-
events with location.
|
|
14
|
-
section: lifestyle
|
|
15
|
-
tags:
|
|
16
|
-
- lifestyle
|
|
17
|
-
- travel
|
|
18
|
-
- skill
|
|
19
|
-
status: stable
|
|
20
|
-
ask_examples:
|
|
21
|
-
- How long will it take me to get to the airport?
|
|
22
|
-
- Does the agent know about traffic?
|
|
23
|
-
locale: en-US
|
|
24
|
-
created: 2026-04-25
|
|
25
|
-
updated: 2026-04-25
|
|
26
|
-
related:
|
|
27
|
-
- features/lifestyle/travel-bookings
|
|
28
|
-
- features/operations/schedule-approaching
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
# Travel Time
|
|
32
|
-
|
|
33
|
-
## In One Sentence
|
|
34
|
-
|
|
35
|
-
A skill the agent calls to estimate door-to-door travel time before
|
|
36
|
-
a calendar event with a location.
|
|
37
|
-
|
|
38
|
-
## What It Does
|
|
39
|
-
|
|
40
|
-
- Reads origin (current location, configured home/work) and
|
|
41
|
-
destination (event location).
|
|
42
|
-
- Returns a typical-time estimate with mode (drive, transit, walk).
|
|
43
|
-
- Used by `schedule-approaching` reminders to lead-time the alert.
|
|
44
|
-
|
|
45
|
-
## Where in the Dashboard
|
|
46
|
-
|
|
47
|
-
There is no operator surface for the travel-time data itself; the
|
|
48
|
-
estimates appear inline in event reminders and morning routines.
|
|
49
|
-
|
|
50
|
-
## Related
|
|
51
|
-
|
|
52
|
-
- [Schedule Approaching](../operations/schedule-approaching.md)
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
schema_version: 1
|
|
3
|
-
slug: features/routines/monthly-review
|
|
4
|
-
title: Monthly Review
|
|
5
|
-
id: monthly-review
|
|
6
|
-
aliases:
|
|
7
|
-
- monthly retro
|
|
8
|
-
category: features
|
|
9
|
-
summary: |
|
|
10
|
-
Once a month, the agent rolls up the four weekly retros into a
|
|
11
|
-
single monthly synthesis under monthly/<YYYY-MM>.md.
|
|
12
|
-
section: routines
|
|
13
|
-
tags:
|
|
14
|
-
- routine
|
|
15
|
-
- autonomous
|
|
16
|
-
- light-tier
|
|
17
|
-
status: stable
|
|
18
|
-
ask_examples:
|
|
19
|
-
- When does the monthly review fire?
|
|
20
|
-
- Where do monthly retros live?
|
|
21
|
-
locale: en-US
|
|
22
|
-
created: 2026-04-25
|
|
23
|
-
updated: 2026-04-25
|
|
24
|
-
related:
|
|
25
|
-
- features/routines/weekly-review
|
|
26
|
-
process_keys:
|
|
27
|
-
- routine.monthly_review
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
# Monthly Review
|
|
31
|
-
|
|
32
|
-
## In One Sentence
|
|
33
|
-
|
|
34
|
-
Light-tier monthly retro that synthesizes the four weekly reviews into
|
|
35
|
-
a single monthly file.
|
|
36
|
-
|
|
37
|
-
## What It Does
|
|
38
|
-
|
|
39
|
-
- Reads the past month of weekly retros.
|
|
40
|
-
- Surfaces threads, recurring patterns, and unfinished pushes.
|
|
41
|
-
- Writes the synthesis into `monthly/<YYYY-MM>.md`.
|
|
42
|
-
|
|
43
|
-
## When It Runs / How It Is Triggered
|
|
44
|
-
|
|
45
|
-
The **last day of the calendar month at 18:00 local time**. The schedule
|
|
46
|
-
is fixed in `packages/daemon/src/core/scheduler.ts` and is not
|
|
47
|
-
operator-configurable.
|
|
48
|
-
|
|
49
|
-
## What It Outputs
|
|
50
|
-
|
|
51
|
-
- A single `monthly/<YYYY-MM>.md` file.
|
|
52
|
-
|
|
53
|
-
## Configuration
|
|
54
|
-
|
|
55
|
-
This routine has no operator-tunable knobs. The fire time, day-of-month,
|
|
56
|
-
and tier are fixed in code.
|
|
57
|
-
|
|
58
|
-
## When Something Goes Wrong
|
|
59
|
-
|
|
60
|
-
- A late-month install will skip the first month's retro because
|
|
61
|
-
there are not four weekly retros to synthesize yet.
|
|
62
|
-
|
|
63
|
-
## Related
|
|
64
|
-
|
|
65
|
-
- [Weekly Review](weekly-review.md)
|