create-egregore 0.20.2 → 0.21.0-runtime-mvp.2
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/assets/egregore-launcher.js +1013 -16
- package/bin/cli.js +11 -0
- package/lib/claude-runtime.js +192 -0
- package/lib/local.js +38 -31
- package/lib/pi-runtime.js +1 -0
- package/lib/prime-runtime.js +1 -0
- package/lib/runtime-identity.js +146 -0
- package/lib/setup.js +116 -17
- package/package.json +10 -6
- package/runtime/claude/.claude/context/commit-format.md +110 -0
- package/runtime/claude/.claude/context/git-language.md +46 -0
- package/runtime/claude/.claude/context/notification-consent.md +66 -0
- package/runtime/claude/.claude/context/pr-format.md +67 -0
- package/runtime/claude/.claude/context/telemetry.md +133 -0
- package/runtime/claude/.claude/hooks/boundary-check.sh +333 -0
- package/runtime/claude/.claude/hooks/branch-guard.sh +231 -0
- package/runtime/claude/.claude/hooks/card-context.sh +38 -0
- package/runtime/claude/.claude/hooks/emissary-detect.sh +53 -0
- package/runtime/claude/.claude/hooks/memory-refresh.sh +67 -0
- package/runtime/claude/.claude/hooks/onboarding-guard.sh +86 -0
- package/runtime/claude/.claude/hooks/retrieval-context.sh +43 -0
- package/runtime/claude/.claude/rules/voice-bedrock.md +73 -0
- package/runtime/claude/.claude/settings.json +131 -0
- package/runtime/claude/.claude/skills/activity/SKILL.md +68 -0
- package/runtime/claude/.claude/skills/announce/SKILL.md +54 -0
- package/runtime/claude/.claude/skills/archive/SKILL.md +71 -0
- package/runtime/claude/.claude/skills/branch/SKILL.md +147 -0
- package/runtime/claude/.claude/skills/checkup/SKILL.md +159 -0
- package/runtime/claude/.claude/skills/commit/SKILL.md +103 -0
- package/runtime/claude/.claude/skills/contribute/SKILL.md +343 -0
- package/runtime/claude/.claude/skills/create-skill/SKILL.md +135 -0
- package/runtime/claude/.claude/skills/dark-mode/SKILL.md +410 -0
- package/runtime/claude/.claude/skills/dashboard/SKILL.md +43 -0
- package/runtime/claude/.claude/skills/deep-reflect/REPORT.md +140 -0
- package/runtime/claude/.claude/skills/deep-reflect/RESEARCH.md +132 -0
- package/runtime/claude/.claude/skills/deep-reflect/ROLES.md +104 -0
- package/runtime/claude/.claude/skills/deep-reflect/SKILL.md +170 -0
- package/runtime/claude/.claude/skills/delete-user/SKILL.md +150 -0
- package/runtime/claude/.claude/skills/emissary/SKILL.md +220 -0
- package/runtime/claude/.claude/skills/handoff/SKILL.md +124 -0
- package/runtime/claude/.claude/skills/harvest/AUDIT.md +546 -0
- package/runtime/claude/.claude/skills/harvest/FORMAT.md +436 -0
- package/runtime/claude/.claude/skills/harvest/PROCESS.md +395 -0
- package/runtime/claude/.claude/skills/harvest/QUESTION_PALETTE.md +76 -0
- package/runtime/claude/.claude/skills/harvest/SKILL.md +100 -0
- package/runtime/claude/.claude/skills/ingest/SKILL.md +112 -0
- package/runtime/claude/.claude/skills/ingest-corpus/SKILL.md +187 -0
- package/runtime/claude/.claude/skills/ingest-notion/SKILL.md +214 -0
- package/runtime/claude/.claude/skills/ingest-user-interview/SKILL.md +65 -0
- package/runtime/claude/.claude/skills/ingest-user-interview/references/analysis-contract.md +125 -0
- package/runtime/claude/.claude/skills/invite/SKILL.md +111 -0
- package/runtime/claude/.claude/skills/issue/SKILL.md +104 -0
- package/runtime/claude/.claude/skills/me/SKILL.md +81 -0
- package/runtime/claude/.claude/skills/meeting/SKILL.md +76 -0
- package/runtime/claude/.claude/skills/meeting/references/analysis-contract.md +102 -0
- package/runtime/claude/.claude/skills/note/SKILL.md +71 -0
- package/runtime/claude/.claude/skills/notion-connect/SKILL.md +124 -0
- package/runtime/claude/.claude/skills/onboarding/SKILL.md +159 -0
- package/runtime/claude/.claude/skills/pr/SKILL.md +85 -0
- package/runtime/claude/.claude/skills/pull/SKILL.md +79 -0
- package/runtime/claude/.claude/skills/push/SKILL.md +47 -0
- package/runtime/claude/.claude/skills/quest/SKILL.md +121 -0
- package/runtime/claude/.claude/skills/reflect/SKILL.md +69 -0
- package/runtime/claude/.claude/skills/review-pr/SKILL.md +276 -0
- package/runtime/claude/.claude/skills/save/SKILL.md +92 -0
- package/runtime/claude/.claude/skills/slack-connect/SKILL.md +148 -0
- package/runtime/claude/.claude/skills/summon/SKILL.md +240 -0
- package/runtime/claude/.claude/skills/sync-repos/SKILL.md +82 -0
- package/runtime/claude/.claude/skills/teams-connect/SKILL.md +216 -0
- package/runtime/claude/.claude/skills/telegram-connect/SKILL.md +110 -0
- package/runtime/claude/.claude/skills/telemetry/SKILL.md +117 -0
- package/runtime/claude/.claude/skills/test/SKILL.md +87 -0
- package/runtime/claude/.claude/skills/the-spiral/SKILL.md +492 -0
- package/runtime/claude/.claude/skills/tui-design/SKILL.md +188 -0
- package/runtime/claude/.claude/skills/tutorial/SKILL.md +100 -0
- package/runtime/claude/.claude/skills/update/SKILL.md +265 -0
- package/runtime/claude/.claude/skills/view/SKILL.md +393 -0
- package/runtime/claude/.claude/skills/view/compose-scaffold.html +221 -0
- package/runtime/claude/.claude/skills/visual-explain/SKILL.md +132 -0
- package/runtime/claude/.claude/skills/wrap/SKILL.md +98 -0
- package/runtime/claude/CLAUDE.md +447 -0
- package/runtime/claude/bin/activity-action.sh +92 -0
- package/runtime/claude/bin/activity-data.sh +17 -0
- package/runtime/claude/bin/agent.sh +783 -0
- package/runtime/claude/bin/artifact-register.sh +164 -0
- package/runtime/claude/bin/artifact-writeback.sh +53 -0
- package/runtime/claude/bin/artifacts.sh +288 -0
- package/runtime/claude/bin/attendant.sh +707 -0
- package/runtime/claude/bin/autosave.sh +112 -0
- package/runtime/claude/bin/boundary.sh +253 -0
- package/runtime/claude/bin/build-sealed-dataroom.mjs +722 -0
- package/runtime/claude/bin/capture-reconcile.sh +69 -0
- package/runtime/claude/bin/capture-run.sh +357 -0
- package/runtime/claude/bin/codex-install-skills.sh +78 -0
- package/runtime/claude/bin/codex-render-spec.mjs +462 -0
- package/runtime/claude/bin/codex-session-start.sh +275 -0
- package/runtime/claude/bin/codex-skill-render.mjs +349 -0
- package/runtime/claude/bin/codex-sync-skills.sh +237 -0
- package/runtime/claude/bin/connect-refresh.sh +33 -0
- package/runtime/claude/bin/contribute-guard.sh +79 -0
- package/runtime/claude/bin/corpus_map.py +806 -0
- package/runtime/claude/bin/corpus_survey.py +304 -0
- package/runtime/claude/bin/dashboard-data.sh +18 -0
- package/runtime/claude/bin/github-auth.sh +121 -0
- package/runtime/claude/bin/graph-batch.sh +86 -0
- package/runtime/claude/bin/graph-op.sh +1106 -0
- package/runtime/claude/bin/graph-projection.sh +54 -0
- package/runtime/claude/bin/graph-wal.sh +242 -0
- package/runtime/claude/bin/graph.sh +267 -0
- package/runtime/claude/bin/handoff-lifecycle-job.sh +146 -0
- package/runtime/claude/bin/handoff-lifecycle.sh +280 -0
- package/runtime/claude/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/claude/bin/handoff-preview.sh +169 -0
- package/runtime/claude/bin/handoff-run.sh +692 -0
- package/runtime/claude/bin/handoff-save-egregore.sh +224 -0
- package/runtime/claude/bin/index-handoff.sh +322 -0
- package/runtime/claude/bin/ingest-graph.sh +86 -0
- package/runtime/claude/bin/ingest-item.sh +10 -0
- package/runtime/claude/bin/ingest-surface.html +495 -0
- package/runtime/claude/bin/ingest.py +1011 -0
- package/runtime/claude/bin/ingest.sh +308 -0
- package/runtime/claude/bin/ingest_graph.py +856 -0
- package/runtime/claude/bin/ingest_surface.py +544 -0
- package/runtime/claude/bin/invite.sh +6 -0
- package/runtime/claude/bin/issue.sh +10 -0
- package/runtime/claude/bin/knowledge.sh +10 -0
- package/runtime/claude/bin/lib/artifact-id.sh +46 -0
- package/runtime/claude/bin/lib/config.sh +136 -0
- package/runtime/claude/bin/lib/context.sh +642 -0
- package/runtime/claude/bin/lib/dashboard-artifact.sh +242 -0
- package/runtime/claude/bin/lib/ensure-develop.sh +183 -0
- package/runtime/claude/bin/lib/git-message.sh +37 -0
- package/runtime/claude/bin/lib/git-sync.sh +494 -0
- package/runtime/claude/bin/lib/greeting.sh +548 -0
- package/runtime/claude/bin/lib/handoff-meta.sh +97 -0
- package/runtime/claude/bin/lib/hash.sh +13 -0
- package/runtime/claude/bin/lib/identity.sh +213 -0
- package/runtime/claude/bin/lib/metrics.sh +374 -0
- package/runtime/claude/bin/lib/noncode.sh +31 -0
- package/runtime/claude/bin/lib/permissions.sh +106 -0
- package/runtime/claude/bin/lib/time.sh +56 -0
- package/runtime/claude/bin/lib/worktree-links.sh +85 -0
- package/runtime/claude/bin/node-run.sh +42 -0
- package/runtime/claude/bin/notification.sh +6 -0
- package/runtime/claude/bin/notify.sh +636 -0
- package/runtime/claude/bin/observe-context.sh +14 -0
- package/runtime/claude/bin/onboarding.sh +6 -0
- package/runtime/claude/bin/person.py +634 -0
- package/runtime/claude/bin/person.sh +481 -0
- package/runtime/claude/bin/pi-render-spec.mjs +140 -0
- package/runtime/claude/bin/post-update.sh +37 -0
- package/runtime/claude/bin/prime-render-spec.mjs +147 -0
- package/runtime/claude/bin/publish-artifact.sh +324 -0
- package/runtime/claude/bin/publish-references.sh +144 -0
- package/runtime/claude/bin/quest.sh +9 -0
- package/runtime/claude/bin/question.sh +8 -0
- package/runtime/claude/bin/repo-state.sh +96 -0
- package/runtime/claude/bin/research-ingest.sh +7 -0
- package/runtime/claude/bin/restore-owned-skills.sh +67 -0
- package/runtime/claude/bin/retrieval_eval.py +385 -0
- package/runtime/claude/bin/runtime-identity.sh +70 -0
- package/runtime/claude/bin/runtime-upgrade.sh +43 -0
- package/runtime/claude/bin/scroll.sh +9 -0
- package/runtime/claude/bin/search.sh +318 -0
- package/runtime/claude/bin/session-autosave.sh +220 -0
- package/runtime/claude/bin/session-log.sh +199 -0
- package/runtime/claude/bin/session-start.sh +696 -0
- package/runtime/claude/bin/settings.sh +532 -0
- package/runtime/claude/bin/startup-check.sh +136 -0
- package/runtime/claude/bin/statusline.sh +41 -0
- package/runtime/claude/bin/telemetry.sh +666 -0
- package/runtime/claude/bin/test-changes.sh +344 -0
- package/runtime/claude/bin/thread.sh +9 -0
- package/runtime/claude/bin/todo.sh +9 -0
- package/runtime/claude/bin/view-render.sh +126 -0
- package/runtime/claude/bin/worktree-create.sh +145 -0
- package/runtime/claude/bin/worktree-remove.sh +50 -0
- package/runtime/claude/bin/worktree.sh +198 -0
- package/runtime/claude/egregore_runtime/__init__.py +228 -0
- package/runtime/claude/egregore_runtime/adapters/__init__.py +5 -0
- package/runtime/claude/egregore_runtime/adapters/invitation.py +237 -0
- package/runtime/claude/egregore_runtime/adapters/notification.py +59 -0
- package/runtime/claude/egregore_runtime/adapters/qmd.py +1701 -0
- package/runtime/claude/egregore_runtime/adapters/qmd_cli.py +210 -0
- package/runtime/claude/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
- package/runtime/claude/egregore_runtime/admin_gate.py +102 -0
- package/runtime/claude/egregore_runtime/artifacts.py +523 -0
- package/runtime/claude/egregore_runtime/contracts.py +499 -0
- package/runtime/claude/egregore_runtime/entitlements.py +85 -0
- package/runtime/claude/egregore_runtime/errors.py +10 -0
- package/runtime/claude/egregore_runtime/graph.py +356 -0
- package/runtime/claude/egregore_runtime/handoff_lookup.py +196 -0
- package/runtime/claude/egregore_runtime/harness_cli.py +1221 -0
- package/runtime/claude/egregore_runtime/identity.py +734 -0
- package/runtime/claude/egregore_runtime/identity_cli.py +91 -0
- package/runtime/claude/egregore_runtime/ingest.py +575 -0
- package/runtime/claude/egregore_runtime/ingest_cli.py +254 -0
- package/runtime/claude/egregore_runtime/ingest_index_cli.py +147 -0
- package/runtime/claude/egregore_runtime/invitation_cli.py +51 -0
- package/runtime/claude/egregore_runtime/invitations.py +116 -0
- package/runtime/claude/egregore_runtime/issue_cli.py +305 -0
- package/runtime/claude/egregore_runtime/issues.py +359 -0
- package/runtime/claude/egregore_runtime/knowledge.py +376 -0
- package/runtime/claude/egregore_runtime/knowledge_cli.py +173 -0
- package/runtime/claude/egregore_runtime/lifecycle.py +888 -0
- package/runtime/claude/egregore_runtime/lifecycle_cli.py +269 -0
- package/runtime/claude/egregore_runtime/notification_cli.py +125 -0
- package/runtime/claude/egregore_runtime/notifications.py +230 -0
- package/runtime/claude/egregore_runtime/observe.py +342 -0
- package/runtime/claude/egregore_runtime/onboarding.py +290 -0
- package/runtime/claude/egregore_runtime/onboarding_cli.py +110 -0
- package/runtime/claude/egregore_runtime/policy.py +144 -0
- package/runtime/claude/egregore_runtime/profile.py +193 -0
- package/runtime/claude/egregore_runtime/quest_cli.py +216 -0
- package/runtime/claude/egregore_runtime/question_cli.py +180 -0
- package/runtime/claude/egregore_runtime/questions.py +304 -0
- package/runtime/claude/egregore_runtime/quests.py +419 -0
- package/runtime/claude/egregore_runtime/readiness.py +379 -0
- package/runtime/claude/egregore_runtime/research_ingest.py +256 -0
- package/runtime/claude/egregore_runtime/research_ingest_cli.py +44 -0
- package/runtime/claude/egregore_runtime/runtime.py +464 -0
- package/runtime/claude/egregore_runtime/scroll_cli.py +185 -0
- package/runtime/claude/egregore_runtime/scrolls.py +726 -0
- package/runtime/claude/egregore_runtime/status.py +412 -0
- package/runtime/claude/egregore_runtime/status_cli.py +174 -0
- package/runtime/claude/egregore_runtime/sync.py +218 -0
- package/runtime/claude/egregore_runtime/teamsync.py +139 -0
- package/runtime/claude/egregore_runtime/telemetry.py +640 -0
- package/runtime/claude/egregore_runtime/thread_cli.py +173 -0
- package/runtime/claude/egregore_runtime/threads.py +517 -0
- package/runtime/claude/egregore_runtime/todo_cli.py +142 -0
- package/runtime/claude/egregore_runtime/todos.py +244 -0
- package/runtime/claude/egregore_runtime/upgrade.py +770 -0
- package/runtime/claude/egregore_runtime/upgrade_worker.py +53 -0
- package/runtime/claude/egregore_runtime/writeback.py +391 -0
- package/runtime/claude/egregore_runtime/writeback_cli.py +114 -0
- package/runtime/claude/manifest.json +284 -0
- package/runtime/codex/.codex/hooks/search-hint.js +21 -52
- package/runtime/codex/.codex/hooks.json +3 -3
- package/runtime/codex/.codex/skills/activity/SKILL.md +23 -66
- package/runtime/codex/.codex/skills/announce/SKILL.md +27 -50
- package/runtime/codex/.codex/skills/archive/SKILL.md +21 -36
- package/runtime/codex/.codex/skills/checkup/SKILL.md +77 -36
- package/runtime/codex/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/dashboard/SKILL.md +17 -47
- package/runtime/codex/.codex/skills/handoff/SKILL.md +84 -133
- package/runtime/codex/.codex/skills/harvest/SKILL.md +32 -117
- package/runtime/codex/.codex/skills/ingest/SKILL.md +47 -25
- package/runtime/codex/.codex/skills/ingest-user-interview/SKILL.md +18 -36
- package/runtime/codex/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
- package/runtime/codex/.codex/skills/invite/SKILL.md +21 -35
- package/runtime/codex/.codex/skills/issue/SKILL.md +60 -41
- package/runtime/codex/.codex/skills/me/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/meeting/SKILL.md +16 -36
- package/runtime/codex/.codex/skills/meeting/references/analysis-contract.md +48 -0
- package/runtime/codex/.codex/skills/note/SKILL.md +30 -25
- package/runtime/codex/.codex/skills/onboarding/SKILL.md +36 -41
- package/runtime/codex/.codex/skills/pull/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/quest/SKILL.md +27 -66
- package/runtime/codex/.codex/skills/reflect/SKILL.md +22 -36
- package/runtime/codex/.codex/skills/save/SKILL.md +2 -2
- package/runtime/codex/.codex/skills/telemetry/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/test/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/tutorial/SKILL.md +40 -41
- package/runtime/codex/.codex/skills/view/SKILL.md +115 -111
- package/runtime/codex/.codex/skills/wrap/SKILL.md +45 -41
- package/runtime/codex/.codex/spec-manifest.json +9 -9
- package/runtime/codex/AGENTS.md +62 -58
- package/runtime/codex/bin/activity-action.sh +92 -0
- package/runtime/codex/bin/activity-data.sh +12 -233
- package/runtime/codex/bin/agent.sh +84 -100
- package/runtime/codex/bin/artifact-register.sh +164 -0
- package/runtime/codex/bin/artifact-writeback.sh +53 -0
- package/runtime/codex/bin/artifacts.sh +288 -0
- package/runtime/codex/bin/build-sealed-dataroom.mjs +722 -0
- package/runtime/codex/bin/capture-run.sh +18 -2
- package/runtime/codex/bin/codex-render-spec.mjs +41 -16
- package/runtime/codex/bin/codex-session-start.sh +14 -4
- package/runtime/codex/bin/codex-skill-render.mjs +9 -7
- package/runtime/codex/bin/corpus_map.py +806 -0
- package/runtime/codex/bin/corpus_survey.py +304 -0
- package/runtime/codex/bin/dashboard-data.sh +11 -171
- package/runtime/codex/bin/github-auth.sh +121 -0
- package/runtime/codex/bin/graph-batch.sh +7 -0
- package/runtime/codex/bin/graph-op.sh +4 -0
- package/runtime/codex/bin/graph-projection.sh +54 -0
- package/runtime/codex/bin/graph-wal.sh +13 -0
- package/runtime/codex/bin/graph.sh +44 -0
- package/runtime/codex/bin/handoff-lifecycle-job.sh +146 -0
- package/runtime/codex/bin/handoff-lifecycle.sh +280 -0
- package/runtime/codex/bin/handoff-preview.sh +169 -0
- package/runtime/codex/bin/handoff-run.sh +42 -26
- package/runtime/codex/bin/ingest-graph.sh +6 -0
- package/runtime/codex/bin/ingest-item.sh +10 -0
- package/runtime/codex/bin/ingest.sh +59 -30
- package/runtime/codex/bin/invite.sh +6 -0
- package/runtime/codex/bin/issue.sh +10 -0
- package/runtime/codex/bin/knowledge.sh +10 -0
- package/runtime/codex/bin/lib/config.sh +20 -0
- package/runtime/codex/bin/lib/context.sh +46 -25
- package/runtime/codex/bin/lib/git-sync.sh +70 -6
- package/runtime/codex/bin/lib/greeting.sh +34 -5
- package/runtime/codex/bin/lib/handoff-meta.sh +97 -0
- package/runtime/codex/bin/lib/worktree-links.sh +6 -0
- package/runtime/codex/bin/node-run.sh +42 -0
- package/runtime/codex/bin/notification.sh +6 -0
- package/runtime/codex/bin/observe-context.sh +14 -0
- package/runtime/codex/bin/onboarding.sh +6 -0
- package/runtime/codex/bin/person.py +4 -0
- package/runtime/codex/bin/person.sh +43 -10
- package/runtime/codex/bin/pi-render-spec.mjs +140 -0
- package/runtime/codex/bin/post-update.sh +37 -0
- package/runtime/codex/bin/prime-render-spec.mjs +147 -0
- package/runtime/codex/bin/publish-artifact.sh +55 -2
- package/runtime/codex/bin/quest.sh +9 -0
- package/runtime/codex/bin/question.sh +8 -0
- package/runtime/codex/bin/research-ingest.sh +7 -0
- package/runtime/codex/bin/restore-owned-skills.sh +67 -0
- package/runtime/codex/bin/retrieval_eval.py +385 -0
- package/runtime/codex/bin/runtime-identity.sh +70 -0
- package/runtime/codex/bin/runtime-upgrade.sh +43 -0
- package/runtime/codex/bin/scroll.sh +9 -0
- package/runtime/codex/bin/search.sh +231 -195
- package/runtime/codex/bin/settings.sh +174 -5
- package/runtime/codex/bin/startup-check.sh +136 -0
- package/runtime/codex/bin/telemetry.sh +522 -247
- package/runtime/codex/bin/test-changes.sh +344 -0
- package/runtime/codex/bin/thread.sh +9 -0
- package/runtime/codex/bin/todo.sh +9 -0
- package/runtime/codex/bin/view-render.sh +126 -0
- package/runtime/codex/bin/worktree-create.sh +19 -5
- package/runtime/codex/egregore_runtime/__init__.py +228 -0
- package/runtime/codex/egregore_runtime/adapters/__init__.py +5 -0
- package/runtime/codex/egregore_runtime/adapters/invitation.py +237 -0
- package/runtime/codex/egregore_runtime/adapters/notification.py +59 -0
- package/runtime/codex/egregore_runtime/adapters/qmd.py +1701 -0
- package/runtime/codex/egregore_runtime/adapters/qmd_cli.py +210 -0
- package/runtime/codex/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
- package/runtime/codex/egregore_runtime/admin_gate.py +102 -0
- package/runtime/codex/egregore_runtime/artifacts.py +523 -0
- package/runtime/codex/egregore_runtime/contracts.py +499 -0
- package/runtime/codex/egregore_runtime/entitlements.py +85 -0
- package/runtime/codex/egregore_runtime/errors.py +10 -0
- package/runtime/codex/egregore_runtime/graph.py +356 -0
- package/runtime/codex/egregore_runtime/handoff_lookup.py +196 -0
- package/runtime/codex/egregore_runtime/harness_cli.py +1221 -0
- package/runtime/codex/egregore_runtime/identity.py +734 -0
- package/runtime/codex/egregore_runtime/identity_cli.py +91 -0
- package/runtime/codex/egregore_runtime/ingest.py +575 -0
- package/runtime/codex/egregore_runtime/ingest_cli.py +254 -0
- package/runtime/codex/egregore_runtime/ingest_index_cli.py +147 -0
- package/runtime/codex/egregore_runtime/invitation_cli.py +51 -0
- package/runtime/codex/egregore_runtime/invitations.py +116 -0
- package/runtime/codex/egregore_runtime/issue_cli.py +305 -0
- package/runtime/codex/egregore_runtime/issues.py +359 -0
- package/runtime/codex/egregore_runtime/knowledge.py +376 -0
- package/runtime/codex/egregore_runtime/knowledge_cli.py +173 -0
- package/runtime/codex/egregore_runtime/lifecycle.py +888 -0
- package/runtime/codex/egregore_runtime/lifecycle_cli.py +269 -0
- package/runtime/codex/egregore_runtime/notification_cli.py +125 -0
- package/runtime/codex/egregore_runtime/notifications.py +230 -0
- package/runtime/codex/egregore_runtime/observe.py +342 -0
- package/runtime/codex/egregore_runtime/onboarding.py +290 -0
- package/runtime/codex/egregore_runtime/onboarding_cli.py +110 -0
- package/runtime/codex/egregore_runtime/policy.py +144 -0
- package/runtime/codex/egregore_runtime/profile.py +193 -0
- package/runtime/codex/egregore_runtime/quest_cli.py +216 -0
- package/runtime/codex/egregore_runtime/question_cli.py +180 -0
- package/runtime/codex/egregore_runtime/questions.py +304 -0
- package/runtime/codex/egregore_runtime/quests.py +419 -0
- package/runtime/codex/egregore_runtime/readiness.py +379 -0
- package/runtime/codex/egregore_runtime/research_ingest.py +256 -0
- package/runtime/codex/egregore_runtime/research_ingest_cli.py +44 -0
- package/runtime/codex/egregore_runtime/runtime.py +464 -0
- package/runtime/codex/egregore_runtime/scroll_cli.py +185 -0
- package/runtime/codex/egregore_runtime/scrolls.py +726 -0
- package/runtime/codex/egregore_runtime/status.py +412 -0
- package/runtime/codex/egregore_runtime/status_cli.py +174 -0
- package/runtime/codex/egregore_runtime/sync.py +218 -0
- package/runtime/codex/egregore_runtime/teamsync.py +139 -0
- package/runtime/codex/egregore_runtime/telemetry.py +640 -0
- package/runtime/codex/egregore_runtime/thread_cli.py +173 -0
- package/runtime/codex/egregore_runtime/threads.py +517 -0
- package/runtime/codex/egregore_runtime/todo_cli.py +142 -0
- package/runtime/codex/egregore_runtime/todos.py +244 -0
- package/runtime/codex/egregore_runtime/upgrade.py +770 -0
- package/runtime/codex/egregore_runtime/upgrade_worker.py +53 -0
- package/runtime/codex/egregore_runtime/writeback.py +391 -0
- package/runtime/codex/egregore_runtime/writeback_cli.py +114 -0
- package/runtime/codex/manifest.json +98 -1
- package/runtime/pi/.codex/hooks/search-hint.js +21 -52
- package/runtime/pi/.codex/hooks.json +3 -3
- package/runtime/pi/.codex/skills/activity/SKILL.md +23 -66
- package/runtime/pi/.codex/skills/announce/SKILL.md +27 -50
- package/runtime/pi/.codex/skills/archive/SKILL.md +21 -36
- package/runtime/pi/.codex/skills/checkup/SKILL.md +77 -36
- package/runtime/pi/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/dashboard/SKILL.md +17 -47
- package/runtime/pi/.codex/skills/handoff/SKILL.md +84 -133
- package/runtime/pi/.codex/skills/harvest/SKILL.md +32 -117
- package/runtime/pi/.codex/skills/ingest/SKILL.md +47 -25
- package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +18 -36
- package/runtime/pi/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
- package/runtime/pi/.codex/skills/invite/SKILL.md +21 -35
- package/runtime/pi/.codex/skills/issue/SKILL.md +60 -41
- package/runtime/pi/.codex/skills/me/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/meeting/SKILL.md +16 -36
- package/runtime/pi/.codex/skills/meeting/references/analysis-contract.md +48 -0
- package/runtime/pi/.codex/skills/note/SKILL.md +30 -25
- package/runtime/pi/.codex/skills/onboarding/SKILL.md +36 -41
- package/runtime/pi/.codex/skills/pull/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/quest/SKILL.md +27 -66
- package/runtime/pi/.codex/skills/reflect/SKILL.md +22 -36
- package/runtime/pi/.codex/skills/save/SKILL.md +2 -2
- package/runtime/pi/.codex/skills/telemetry/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/test/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/tutorial/SKILL.md +40 -41
- package/runtime/pi/.codex/skills/view/SKILL.md +115 -111
- package/runtime/pi/.codex/skills/wrap/SKILL.md +45 -41
- package/runtime/pi/.codex/spec-manifest.json +9 -9
- package/runtime/pi/.pi/APPEND_SYSTEM.md +57 -48
- package/runtime/pi/.pi/extensions/egregore.ts +7 -0
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +62 -58
- package/runtime/pi/bin/activity-action.sh +92 -0
- package/runtime/pi/bin/activity-data.sh +12 -233
- package/runtime/pi/bin/agent.sh +84 -100
- package/runtime/pi/bin/artifact-register.sh +164 -0
- package/runtime/pi/bin/artifact-writeback.sh +53 -0
- package/runtime/pi/bin/artifacts.sh +288 -0
- package/runtime/pi/bin/build-sealed-dataroom.mjs +722 -0
- package/runtime/pi/bin/capture-run.sh +18 -2
- package/runtime/pi/bin/codex-render-spec.mjs +41 -16
- package/runtime/pi/bin/codex-session-start.sh +14 -4
- package/runtime/pi/bin/codex-skill-render.mjs +9 -7
- package/runtime/pi/bin/corpus_map.py +806 -0
- package/runtime/pi/bin/corpus_survey.py +304 -0
- package/runtime/pi/bin/dashboard-data.sh +11 -171
- package/runtime/pi/bin/github-auth.sh +121 -0
- package/runtime/pi/bin/graph-batch.sh +7 -0
- package/runtime/pi/bin/graph-op.sh +4 -0
- package/runtime/pi/bin/graph-projection.sh +54 -0
- package/runtime/pi/bin/graph-wal.sh +13 -0
- package/runtime/pi/bin/graph.sh +44 -0
- package/runtime/pi/bin/handoff-lifecycle-job.sh +146 -0
- package/runtime/pi/bin/handoff-lifecycle.sh +280 -0
- package/runtime/pi/bin/handoff-preview.sh +169 -0
- package/runtime/pi/bin/handoff-run.sh +42 -26
- package/runtime/pi/bin/ingest-graph.sh +6 -0
- package/runtime/pi/bin/ingest-item.sh +10 -0
- package/runtime/pi/bin/ingest.sh +59 -30
- package/runtime/pi/bin/invite.sh +6 -0
- package/runtime/pi/bin/issue.sh +10 -0
- package/runtime/pi/bin/knowledge.sh +10 -0
- package/runtime/pi/bin/lib/config.sh +20 -0
- package/runtime/pi/bin/lib/context.sh +46 -25
- package/runtime/pi/bin/lib/git-sync.sh +70 -6
- package/runtime/pi/bin/lib/greeting.sh +34 -5
- package/runtime/pi/bin/lib/handoff-meta.sh +97 -0
- package/runtime/pi/bin/lib/worktree-links.sh +6 -0
- package/runtime/pi/bin/node-run.sh +42 -0
- package/runtime/pi/bin/notification.sh +6 -0
- package/runtime/pi/bin/observe-context.sh +14 -0
- package/runtime/pi/bin/onboarding.sh +6 -0
- package/runtime/pi/bin/person.py +4 -0
- package/runtime/pi/bin/person.sh +43 -10
- package/runtime/pi/bin/pi-observe-context.mjs +93 -0
- package/runtime/pi/bin/pi-product-workflows.mjs +1 -1
- package/runtime/pi/bin/pi-render-spec.mjs +1 -1
- package/runtime/pi/bin/post-update.sh +37 -0
- package/runtime/pi/bin/prime-render-spec.mjs +147 -0
- package/runtime/pi/bin/publish-artifact.sh +55 -2
- package/runtime/pi/bin/quest.sh +9 -0
- package/runtime/pi/bin/question.sh +8 -0
- package/runtime/pi/bin/research-ingest.sh +7 -0
- package/runtime/pi/bin/restore-owned-skills.sh +67 -0
- package/runtime/pi/bin/retrieval_eval.py +385 -0
- package/runtime/pi/bin/runtime-identity.sh +70 -0
- package/runtime/pi/bin/runtime-upgrade.sh +43 -0
- package/runtime/pi/bin/scroll.sh +9 -0
- package/runtime/pi/bin/search.sh +231 -195
- package/runtime/pi/bin/settings.sh +174 -5
- package/runtime/pi/bin/startup-check.sh +136 -0
- package/runtime/pi/bin/telemetry.sh +522 -247
- package/runtime/pi/bin/test-changes.sh +344 -0
- package/runtime/pi/bin/thread.sh +9 -0
- package/runtime/pi/bin/todo.sh +9 -0
- package/runtime/pi/bin/view-render.sh +126 -0
- package/runtime/pi/bin/worktree-create.sh +19 -5
- package/runtime/pi/egregore_runtime/__init__.py +228 -0
- package/runtime/pi/egregore_runtime/adapters/__init__.py +5 -0
- package/runtime/pi/egregore_runtime/adapters/invitation.py +237 -0
- package/runtime/pi/egregore_runtime/adapters/notification.py +59 -0
- package/runtime/pi/egregore_runtime/adapters/qmd.py +1701 -0
- package/runtime/pi/egregore_runtime/adapters/qmd_cli.py +210 -0
- package/runtime/pi/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
- package/runtime/pi/egregore_runtime/admin_gate.py +102 -0
- package/runtime/pi/egregore_runtime/artifacts.py +523 -0
- package/runtime/pi/egregore_runtime/contracts.py +499 -0
- package/runtime/pi/egregore_runtime/entitlements.py +85 -0
- package/runtime/pi/egregore_runtime/errors.py +10 -0
- package/runtime/pi/egregore_runtime/graph.py +356 -0
- package/runtime/pi/egregore_runtime/handoff_lookup.py +196 -0
- package/runtime/pi/egregore_runtime/harness_cli.py +1221 -0
- package/runtime/pi/egregore_runtime/identity.py +734 -0
- package/runtime/pi/egregore_runtime/identity_cli.py +91 -0
- package/runtime/pi/egregore_runtime/ingest.py +575 -0
- package/runtime/pi/egregore_runtime/ingest_cli.py +254 -0
- package/runtime/pi/egregore_runtime/ingest_index_cli.py +147 -0
- package/runtime/pi/egregore_runtime/invitation_cli.py +51 -0
- package/runtime/pi/egregore_runtime/invitations.py +116 -0
- package/runtime/pi/egregore_runtime/issue_cli.py +305 -0
- package/runtime/pi/egregore_runtime/issues.py +359 -0
- package/runtime/pi/egregore_runtime/knowledge.py +376 -0
- package/runtime/pi/egregore_runtime/knowledge_cli.py +173 -0
- package/runtime/pi/egregore_runtime/lifecycle.py +888 -0
- package/runtime/pi/egregore_runtime/lifecycle_cli.py +269 -0
- package/runtime/pi/egregore_runtime/notification_cli.py +125 -0
- package/runtime/pi/egregore_runtime/notifications.py +230 -0
- package/runtime/pi/egregore_runtime/observe.py +342 -0
- package/runtime/pi/egregore_runtime/onboarding.py +290 -0
- package/runtime/pi/egregore_runtime/onboarding_cli.py +110 -0
- package/runtime/pi/egregore_runtime/policy.py +144 -0
- package/runtime/pi/egregore_runtime/profile.py +193 -0
- package/runtime/pi/egregore_runtime/quest_cli.py +216 -0
- package/runtime/pi/egregore_runtime/question_cli.py +180 -0
- package/runtime/pi/egregore_runtime/questions.py +304 -0
- package/runtime/pi/egregore_runtime/quests.py +419 -0
- package/runtime/pi/egregore_runtime/readiness.py +379 -0
- package/runtime/pi/egregore_runtime/research_ingest.py +256 -0
- package/runtime/pi/egregore_runtime/research_ingest_cli.py +44 -0
- package/runtime/pi/egregore_runtime/runtime.py +464 -0
- package/runtime/pi/egregore_runtime/scroll_cli.py +185 -0
- package/runtime/pi/egregore_runtime/scrolls.py +726 -0
- package/runtime/pi/egregore_runtime/status.py +412 -0
- package/runtime/pi/egregore_runtime/status_cli.py +174 -0
- package/runtime/pi/egregore_runtime/sync.py +218 -0
- package/runtime/pi/egregore_runtime/teamsync.py +139 -0
- package/runtime/pi/egregore_runtime/telemetry.py +640 -0
- package/runtime/pi/egregore_runtime/thread_cli.py +173 -0
- package/runtime/pi/egregore_runtime/threads.py +517 -0
- package/runtime/pi/egregore_runtime/todo_cli.py +142 -0
- package/runtime/pi/egregore_runtime/todos.py +244 -0
- package/runtime/pi/egregore_runtime/upgrade.py +770 -0
- package/runtime/pi/egregore_runtime/upgrade_worker.py +53 -0
- package/runtime/pi/egregore_runtime/writeback.py +391 -0
- package/runtime/pi/egregore_runtime/writeback_cli.py +114 -0
- package/runtime/pi/manifest.json +98 -1
- package/runtime/prime/.codex/hooks/search-hint.js +21 -52
- package/runtime/prime/.codex/hooks.json +3 -3
- package/runtime/prime/.codex/skills/activity/SKILL.md +23 -66
- package/runtime/prime/.codex/skills/announce/SKILL.md +27 -50
- package/runtime/prime/.codex/skills/archive/SKILL.md +21 -36
- package/runtime/prime/.codex/skills/checkup/SKILL.md +77 -36
- package/runtime/prime/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/dashboard/SKILL.md +17 -47
- package/runtime/prime/.codex/skills/handoff/SKILL.md +84 -133
- package/runtime/prime/.codex/skills/harvest/SKILL.md +32 -117
- package/runtime/prime/.codex/skills/ingest/SKILL.md +47 -25
- package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +18 -36
- package/runtime/prime/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
- package/runtime/prime/.codex/skills/invite/SKILL.md +21 -35
- package/runtime/prime/.codex/skills/issue/SKILL.md +60 -41
- package/runtime/prime/.codex/skills/me/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/meeting/SKILL.md +16 -36
- package/runtime/prime/.codex/skills/meeting/references/analysis-contract.md +48 -0
- package/runtime/prime/.codex/skills/note/SKILL.md +30 -25
- package/runtime/prime/.codex/skills/onboarding/SKILL.md +36 -41
- package/runtime/prime/.codex/skills/pull/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/quest/SKILL.md +27 -66
- package/runtime/prime/.codex/skills/reflect/SKILL.md +22 -36
- package/runtime/prime/.codex/skills/save/SKILL.md +2 -2
- package/runtime/prime/.codex/skills/telemetry/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/test/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/tutorial/SKILL.md +40 -41
- package/runtime/prime/.codex/skills/view/SKILL.md +115 -111
- package/runtime/prime/.codex/skills/wrap/SKILL.md +45 -41
- package/runtime/prime/.codex/spec-manifest.json +9 -9
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +57 -48
- package/runtime/prime/.prime/agent/extensions/egregore.ts +7 -0
- package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
- package/runtime/prime/AGENTS.md +62 -58
- package/runtime/prime/bin/activity-action.sh +92 -0
- package/runtime/prime/bin/activity-data.sh +12 -233
- package/runtime/prime/bin/agent.sh +84 -100
- package/runtime/prime/bin/artifact-register.sh +164 -0
- package/runtime/prime/bin/artifact-writeback.sh +53 -0
- package/runtime/prime/bin/artifacts.sh +288 -0
- package/runtime/prime/bin/build-sealed-dataroom.mjs +722 -0
- package/runtime/prime/bin/capture-run.sh +18 -2
- package/runtime/prime/bin/codex-render-spec.mjs +41 -16
- package/runtime/prime/bin/codex-session-start.sh +14 -4
- package/runtime/prime/bin/codex-skill-render.mjs +9 -7
- package/runtime/prime/bin/corpus_map.py +806 -0
- package/runtime/prime/bin/corpus_survey.py +304 -0
- package/runtime/prime/bin/dashboard-data.sh +11 -171
- package/runtime/prime/bin/github-auth.sh +121 -0
- package/runtime/prime/bin/graph-batch.sh +7 -0
- package/runtime/prime/bin/graph-op.sh +4 -0
- package/runtime/prime/bin/graph-projection.sh +54 -0
- package/runtime/prime/bin/graph-wal.sh +13 -0
- package/runtime/prime/bin/graph.sh +44 -0
- package/runtime/prime/bin/handoff-lifecycle-job.sh +146 -0
- package/runtime/prime/bin/handoff-lifecycle.sh +280 -0
- package/runtime/prime/bin/handoff-preview.sh +169 -0
- package/runtime/prime/bin/handoff-run.sh +42 -26
- package/runtime/prime/bin/ingest-graph.sh +6 -0
- package/runtime/prime/bin/ingest-item.sh +10 -0
- package/runtime/prime/bin/ingest.sh +59 -30
- package/runtime/prime/bin/invite.sh +6 -0
- package/runtime/prime/bin/issue.sh +10 -0
- package/runtime/prime/bin/knowledge.sh +10 -0
- package/runtime/prime/bin/lib/config.sh +20 -0
- package/runtime/prime/bin/lib/context.sh +46 -25
- package/runtime/prime/bin/lib/git-sync.sh +70 -6
- package/runtime/prime/bin/lib/greeting.sh +34 -5
- package/runtime/prime/bin/lib/handoff-meta.sh +97 -0
- package/runtime/prime/bin/lib/worktree-links.sh +6 -0
- package/runtime/prime/bin/node-run.sh +42 -0
- package/runtime/prime/bin/notification.sh +6 -0
- package/runtime/prime/bin/observe-context.sh +14 -0
- package/runtime/prime/bin/onboarding.sh +6 -0
- package/runtime/prime/bin/person.py +4 -0
- package/runtime/prime/bin/person.sh +43 -10
- package/runtime/prime/bin/pi-observe-context.mjs +93 -0
- package/runtime/prime/bin/pi-product-workflows.mjs +1 -1
- package/runtime/prime/bin/pi-render-spec.mjs +140 -0
- package/runtime/prime/bin/post-update.sh +37 -0
- package/runtime/prime/bin/prime-render-spec.mjs +1 -1
- package/runtime/prime/bin/publish-artifact.sh +55 -2
- package/runtime/prime/bin/quest.sh +9 -0
- package/runtime/prime/bin/question.sh +8 -0
- package/runtime/prime/bin/research-ingest.sh +7 -0
- package/runtime/prime/bin/restore-owned-skills.sh +67 -0
- package/runtime/prime/bin/retrieval_eval.py +385 -0
- package/runtime/prime/bin/runtime-identity.sh +70 -0
- package/runtime/prime/bin/runtime-upgrade.sh +43 -0
- package/runtime/prime/bin/scroll.sh +9 -0
- package/runtime/prime/bin/search.sh +231 -195
- package/runtime/prime/bin/settings.sh +174 -5
- package/runtime/prime/bin/startup-check.sh +136 -0
- package/runtime/prime/bin/telemetry.sh +522 -247
- package/runtime/prime/bin/test-changes.sh +344 -0
- package/runtime/prime/bin/thread.sh +9 -0
- package/runtime/prime/bin/todo.sh +9 -0
- package/runtime/prime/bin/view-render.sh +126 -0
- package/runtime/prime/bin/worktree-create.sh +19 -5
- package/runtime/prime/egregore_runtime/__init__.py +228 -0
- package/runtime/prime/egregore_runtime/adapters/__init__.py +5 -0
- package/runtime/prime/egregore_runtime/adapters/invitation.py +237 -0
- package/runtime/prime/egregore_runtime/adapters/notification.py +59 -0
- package/runtime/prime/egregore_runtime/adapters/qmd.py +1701 -0
- package/runtime/prime/egregore_runtime/adapters/qmd_cli.py +210 -0
- package/runtime/prime/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
- package/runtime/prime/egregore_runtime/admin_gate.py +102 -0
- package/runtime/prime/egregore_runtime/artifacts.py +523 -0
- package/runtime/prime/egregore_runtime/contracts.py +499 -0
- package/runtime/prime/egregore_runtime/entitlements.py +85 -0
- package/runtime/prime/egregore_runtime/errors.py +10 -0
- package/runtime/prime/egregore_runtime/graph.py +356 -0
- package/runtime/prime/egregore_runtime/handoff_lookup.py +196 -0
- package/runtime/prime/egregore_runtime/harness_cli.py +1221 -0
- package/runtime/prime/egregore_runtime/identity.py +734 -0
- package/runtime/prime/egregore_runtime/identity_cli.py +91 -0
- package/runtime/prime/egregore_runtime/ingest.py +575 -0
- package/runtime/prime/egregore_runtime/ingest_cli.py +254 -0
- package/runtime/prime/egregore_runtime/ingest_index_cli.py +147 -0
- package/runtime/prime/egregore_runtime/invitation_cli.py +51 -0
- package/runtime/prime/egregore_runtime/invitations.py +116 -0
- package/runtime/prime/egregore_runtime/issue_cli.py +305 -0
- package/runtime/prime/egregore_runtime/issues.py +359 -0
- package/runtime/prime/egregore_runtime/knowledge.py +376 -0
- package/runtime/prime/egregore_runtime/knowledge_cli.py +173 -0
- package/runtime/prime/egregore_runtime/lifecycle.py +888 -0
- package/runtime/prime/egregore_runtime/lifecycle_cli.py +269 -0
- package/runtime/prime/egregore_runtime/notification_cli.py +125 -0
- package/runtime/prime/egregore_runtime/notifications.py +230 -0
- package/runtime/prime/egregore_runtime/observe.py +342 -0
- package/runtime/prime/egregore_runtime/onboarding.py +290 -0
- package/runtime/prime/egregore_runtime/onboarding_cli.py +110 -0
- package/runtime/prime/egregore_runtime/policy.py +144 -0
- package/runtime/prime/egregore_runtime/profile.py +193 -0
- package/runtime/prime/egregore_runtime/quest_cli.py +216 -0
- package/runtime/prime/egregore_runtime/question_cli.py +180 -0
- package/runtime/prime/egregore_runtime/questions.py +304 -0
- package/runtime/prime/egregore_runtime/quests.py +419 -0
- package/runtime/prime/egregore_runtime/readiness.py +379 -0
- package/runtime/prime/egregore_runtime/research_ingest.py +256 -0
- package/runtime/prime/egregore_runtime/research_ingest_cli.py +44 -0
- package/runtime/prime/egregore_runtime/runtime.py +464 -0
- package/runtime/prime/egregore_runtime/scroll_cli.py +185 -0
- package/runtime/prime/egregore_runtime/scrolls.py +726 -0
- package/runtime/prime/egregore_runtime/status.py +412 -0
- package/runtime/prime/egregore_runtime/status_cli.py +174 -0
- package/runtime/prime/egregore_runtime/sync.py +218 -0
- package/runtime/prime/egregore_runtime/teamsync.py +139 -0
- package/runtime/prime/egregore_runtime/telemetry.py +640 -0
- package/runtime/prime/egregore_runtime/thread_cli.py +173 -0
- package/runtime/prime/egregore_runtime/threads.py +517 -0
- package/runtime/prime/egregore_runtime/todo_cli.py +142 -0
- package/runtime/prime/egregore_runtime/todos.py +244 -0
- package/runtime/prime/egregore_runtime/upgrade.py +770 -0
- package/runtime/prime/egregore_runtime/upgrade_worker.py +53 -0
- package/runtime/prime/egregore_runtime/writeback.py +391 -0
- package/runtime/prime/egregore_runtime/writeback_cli.py +114 -0
- package/runtime/prime/manifest.json +98 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.
|
|
2
|
+
// egregore-launcher-version: 0.21.0-runtime-mvp.2
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
// egregore ls | list list instances (non-interactive table)
|
|
15
15
|
// egregore use <slug> set the default for bare `egregore`
|
|
16
16
|
// egregore connect [slug] activate Connected for an existing instance
|
|
17
|
+
// egregore telemetry <verb> manage local telemetry for an instance
|
|
18
|
+
// egregore runtime <verb> inspect or synchronize Local retrieval
|
|
17
19
|
// egregore /invite <user> invite a GitHub user to an instance
|
|
18
20
|
// egregore settings [slug] hosting on/off, managed repos, admins (s in browser)
|
|
19
21
|
// egregore prune [--dry-run] remove entries whose path is gone
|
|
@@ -33,7 +35,7 @@ const crypto = require("node:crypto");
|
|
|
33
35
|
const { spawnSync, spawn } = require("node:child_process");
|
|
34
36
|
const readline = require("node:readline");
|
|
35
37
|
|
|
36
|
-
const VERSION = "0.
|
|
38
|
+
const VERSION = "0.21.0-runtime-mvp.2";
|
|
37
39
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
38
40
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
39
41
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
|
@@ -360,6 +362,52 @@ function initialCursorForCwd(registry, cwd = safeCwd()) {
|
|
|
360
362
|
return 0;
|
|
361
363
|
}
|
|
362
364
|
|
|
365
|
+
function currentWorktreeInstance(registry, cwd = safeCwd()) {
|
|
366
|
+
// Development checkouts are intentionally not persisted as separate
|
|
367
|
+
// Egregore instances, but launching from one must preserve the exact code
|
|
368
|
+
// under test. A linked worktree has a `.git` file; a safe standalone clone
|
|
369
|
+
// has a `.git` directory. Walk upward and borrow only display/runtime
|
|
370
|
+
// preferences from a registered parent when one exists.
|
|
371
|
+
let candidate = path.resolve(cwd);
|
|
372
|
+
const filesystemRoot = path.parse(candidate).root;
|
|
373
|
+
while (candidate !== filesystemRoot) {
|
|
374
|
+
const marker = path.join(candidate, ".git");
|
|
375
|
+
const config = path.join(candidate, "egregore.json");
|
|
376
|
+
try {
|
|
377
|
+
const gitMarker = fs.statSync(marker);
|
|
378
|
+
if ((gitMarker.isFile() || gitMarker.isDirectory()) && fs.statSync(config).isFile()) {
|
|
379
|
+
const exact = registry.find(
|
|
380
|
+
(entry) => entry?.path && path.resolve(entry.path) === candidate,
|
|
381
|
+
);
|
|
382
|
+
if (exact) return null;
|
|
383
|
+
const parent = registry
|
|
384
|
+
.filter((entry) => entry?.path && pathContains(entry.path, candidate))
|
|
385
|
+
.sort((a, b) => path.resolve(b.path).length - path.resolve(a.path).length)[0];
|
|
386
|
+
if (parent) return { ...parent, path: candidate, transientWorktree: true };
|
|
387
|
+
const local = JSON.parse(fs.readFileSync(config, "utf-8"));
|
|
388
|
+
return {
|
|
389
|
+
slug: local.slug || path.basename(candidate),
|
|
390
|
+
name: local.org_name || local.slug || path.basename(candidate),
|
|
391
|
+
path: candidate,
|
|
392
|
+
transientWorktree: true,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
} catch {
|
|
396
|
+
// Keep walking: normal subdirectories do not contain both markers.
|
|
397
|
+
}
|
|
398
|
+
candidate = path.dirname(candidate);
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function isLinkedGitWorktree(directory) {
|
|
404
|
+
try {
|
|
405
|
+
return fs.statSync(path.join(directory, ".git")).isFile();
|
|
406
|
+
} catch {
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
363
411
|
// ── launch ──────────────────────────────────────────────────────────
|
|
364
412
|
|
|
365
413
|
function normalizeRuntime(raw) {
|
|
@@ -676,7 +724,7 @@ async function renderCodexStartupCard(egregoreDir) {
|
|
|
676
724
|
}, "Preparing Codex startup");
|
|
677
725
|
let output = result.stdout || "";
|
|
678
726
|
if (isConnectedPath(egregoreDir) && !output.includes("◆ CONNECTED")) {
|
|
679
|
-
const connectedLine =
|
|
727
|
+
const connectedLine = ` ◆ CONNECTED ${connectedModeSuffix(egregoreDir)}\n`;
|
|
680
728
|
output = output.includes("\nWhat are you working on?")
|
|
681
729
|
? output.replace("\nWhat are you working on?", `\n${connectedLine}\nWhat are you working on?`)
|
|
682
730
|
: `${output}${output.endsWith("\n") || !output ? "" : "\n"}${connectedLine}`;
|
|
@@ -846,6 +894,9 @@ function installCodexSkills(egregoreDir) {
|
|
|
846
894
|
}
|
|
847
895
|
|
|
848
896
|
function claudeLaunchArgs(egregoreDir) {
|
|
897
|
+
// Claude treats the positional value as the initial user prompt. Egregore
|
|
898
|
+
// deliberately submits `start` so the opening experience renders without
|
|
899
|
+
// requiring the user to type first.
|
|
849
900
|
const args = ["start"];
|
|
850
901
|
const memoryLink = path.join(egregoreDir, "memory");
|
|
851
902
|
try {
|
|
@@ -863,14 +914,21 @@ function claudeLaunchArgs(egregoreDir) {
|
|
|
863
914
|
return args;
|
|
864
915
|
}
|
|
865
916
|
|
|
866
|
-
function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
917
|
+
function runtimeLaunchArgs(runtime, egregoreDir, options = {}) {
|
|
867
918
|
if (runtime === "codex") {
|
|
868
|
-
|
|
919
|
+
const args = [
|
|
869
920
|
"--enable", "hooks",
|
|
870
921
|
"--sandbox", "danger-full-access",
|
|
871
922
|
"--ask-for-approval", "never",
|
|
872
923
|
"--cd", egregoreDir,
|
|
873
924
|
];
|
|
925
|
+
// Codex treats each linked worktree as a separate hook-trust root, while
|
|
926
|
+
// project hooks may still be discovered from the registered primary
|
|
927
|
+
// checkout. The Egregore launcher validates the Runtime surface above;
|
|
928
|
+
// trust that bounded hook set for this transient invocation so Observe
|
|
929
|
+
// and the branch guard are not silently skipped in the worktree.
|
|
930
|
+
if (options.bypassHookTrust) args.push("--dangerously-bypass-hook-trust");
|
|
931
|
+
return args;
|
|
874
932
|
}
|
|
875
933
|
if (runtime === "pi") return piTrustArgs();
|
|
876
934
|
if (runtime === "prime") return primeTrustArgs();
|
|
@@ -894,6 +952,12 @@ async function launch(inst, runtimeOverride) {
|
|
|
894
952
|
}
|
|
895
953
|
const runtime = await chooseRuntimeForLaunch(inst, runtimeOverride);
|
|
896
954
|
if (!runtime) return;
|
|
955
|
+
if (runtime === "claude-code" && isLinkedGitWorktree(inst.path)) {
|
|
956
|
+
die(
|
|
957
|
+
"Claude Code automatically removes linked Git worktrees when its worktree session ends.\n" +
|
|
958
|
+
" Launch Claude from a standalone clone of this branch instead; Codex, Pi, and Prime may use this worktree directly.",
|
|
959
|
+
);
|
|
960
|
+
}
|
|
897
961
|
if (runtime === "claude-code") {
|
|
898
962
|
normalizeClaudeDenyRules(inst.path);
|
|
899
963
|
ensureClaudeModeStatusLine(inst.path);
|
|
@@ -949,9 +1013,12 @@ async function launch(inst, runtimeOverride) {
|
|
|
949
1013
|
const launchEnv = {
|
|
950
1014
|
...process.env,
|
|
951
1015
|
EGREGORE_RUNTIME: runtime,
|
|
1016
|
+
EGREGORE_TRANSIENT_CHECKOUT: inst.transientWorktree ? "1" : process.env.EGREGORE_TRANSIENT_CHECKOUT,
|
|
952
1017
|
EGREGORE_CODEX_TRUSTED: runtime === "codex" ? "1" : process.env.EGREGORE_CODEX_TRUSTED,
|
|
953
1018
|
};
|
|
954
|
-
const child = spawn(binary, launchArgs || runtimeLaunchArgs(runtime, inst.path
|
|
1019
|
+
const child = spawn(binary, launchArgs || runtimeLaunchArgs(runtime, inst.path, {
|
|
1020
|
+
bypassHookTrust: runtime === "codex" && Boolean(inst.transientWorktree),
|
|
1021
|
+
}), {
|
|
955
1022
|
cwd: inst.path,
|
|
956
1023
|
stdio: "inherit",
|
|
957
1024
|
env: launchEnv,
|
|
@@ -1080,8 +1147,11 @@ function cmdHelp() {
|
|
|
1080
1147
|
` ${CYAN}egregore ls${RESET} ${DIM}| list${RESET} list installed instances`,
|
|
1081
1148
|
` ${CYAN}egregore use${RESET} ${DIM}<slug>${RESET} set the default for bare ${BOLD}egregore${RESET}`,
|
|
1082
1149
|
` ${CYAN}egregore connect${RESET} ${DIM}[slug]${RESET} activate Connected for an existing instance`,
|
|
1150
|
+
` ${CYAN}egregore telemetry${RESET} ${DIM}<verb>${RESET} status, inspect, enable, disable, export, or share`,
|
|
1151
|
+
` ${CYAN}egregore runtime${RESET} ${DIM}<verb>${RESET} status, sync, start, or stop Local retrieval`,
|
|
1083
1152
|
` ${CYAN}egregore /invite${RESET} ${DIM}<user> [slug]${RESET} invite a GitHub user`,
|
|
1084
1153
|
` ${CYAN}egregore settings${RESET} ${DIM}[slug]${RESET} hosting on/off, repos, admins`,
|
|
1154
|
+
` ${CYAN}egregore settings${RESET} ${DIM}<slug> runtime${RESET} Runtime update: review, prepare, activate, roll back`,
|
|
1085
1155
|
` ${CYAN}egregore prune${RESET} ${DIM}[--dry-run]${RESET} remove entries with missing paths`,
|
|
1086
1156
|
` ${CYAN}egregore rm${RESET} ${DIM}<slug|path>${RESET} remove a specific entry`,
|
|
1087
1157
|
``,
|
|
@@ -2116,6 +2186,79 @@ async function cmdInvite(args) {
|
|
|
2116
2186
|
return inviteToInstance(inst, username);
|
|
2117
2187
|
}
|
|
2118
2188
|
|
|
2189
|
+
function cmdTelemetry(args) {
|
|
2190
|
+
const registry = readRegistry();
|
|
2191
|
+
if (registry.length === 0) die("no egregores installed yet.\n run: npx -y create-egregore@latest");
|
|
2192
|
+
|
|
2193
|
+
const forwarded = args.slice();
|
|
2194
|
+
let instanceQuery = "";
|
|
2195
|
+
const marker = forwarded.indexOf("--instance");
|
|
2196
|
+
if (marker !== -1) {
|
|
2197
|
+
instanceQuery = forwarded[marker + 1] || "";
|
|
2198
|
+
if (!instanceQuery) die("usage: egregore telemetry <verb> [args] --instance <slug>");
|
|
2199
|
+
forwarded.splice(marker, 2);
|
|
2200
|
+
}
|
|
2201
|
+
if (forwarded.length === 0) forwarded.push("status");
|
|
2202
|
+
|
|
2203
|
+
const inst = resolveInviteInstance(registry, instanceQuery);
|
|
2204
|
+
if (!inst) {
|
|
2205
|
+
die("multiple egregores installed; choose one:\n egregore telemetry <verb> --instance <slug>\n run: egregore ls");
|
|
2206
|
+
}
|
|
2207
|
+
const script = path.join(inst.path, "bin", "telemetry.sh");
|
|
2208
|
+
if (!fs.existsSync(script)) {
|
|
2209
|
+
die("bin/telemetry.sh not found — update this Egregore before managing telemetry");
|
|
2210
|
+
}
|
|
2211
|
+
const result = spawnSync("bash", [script, ...forwarded], {
|
|
2212
|
+
cwd: inst.path,
|
|
2213
|
+
stdio: "inherit",
|
|
2214
|
+
env: { ...process.env },
|
|
2215
|
+
});
|
|
2216
|
+
if (result.error) die(`telemetry command failed: ${result.error.message}`);
|
|
2217
|
+
process.exitCode = result.status ?? 1;
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
function cmdRuntime(args) {
|
|
2221
|
+
const registry = readRegistry();
|
|
2222
|
+
if (registry.length === 0) die("no egregores installed yet.\n run: npx -y create-egregore@latest");
|
|
2223
|
+
|
|
2224
|
+
const forwarded = args.slice();
|
|
2225
|
+
let instanceQuery = "";
|
|
2226
|
+
const marker = forwarded.indexOf("--instance");
|
|
2227
|
+
if (marker !== -1) {
|
|
2228
|
+
instanceQuery = forwarded[marker + 1] || "";
|
|
2229
|
+
if (!instanceQuery) die("usage: egregore runtime <status|sync|start|stop> --instance <slug>");
|
|
2230
|
+
forwarded.splice(marker, 2);
|
|
2231
|
+
}
|
|
2232
|
+
const verb = forwarded[0] || "status";
|
|
2233
|
+
if (!["status", "sync", "start", "stop", "update"].includes(verb) || forwarded.length > 1) {
|
|
2234
|
+
die("usage: egregore runtime <status|sync|start|stop> [--instance <slug>]");
|
|
2235
|
+
}
|
|
2236
|
+
const inst = resolveInviteInstance(registry, instanceQuery);
|
|
2237
|
+
if (!inst) {
|
|
2238
|
+
die("multiple egregores installed; choose one:\n egregore runtime status --instance <slug>\n run: egregore ls");
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
let script;
|
|
2242
|
+
let scriptArgs;
|
|
2243
|
+
if (verb === "sync" || verb === "update") {
|
|
2244
|
+
script = path.join(inst.path, "bin", "agent.sh");
|
|
2245
|
+
scriptArgs = ["sync"];
|
|
2246
|
+
} else {
|
|
2247
|
+
script = path.join(inst.path, "bin", "search.sh");
|
|
2248
|
+
scriptArgs = [verb];
|
|
2249
|
+
}
|
|
2250
|
+
if (!fs.existsSync(script)) {
|
|
2251
|
+
die("Local Runtime controls are missing — update this Egregore before managing retrieval");
|
|
2252
|
+
}
|
|
2253
|
+
const result = spawnSync("bash", [script, ...scriptArgs], {
|
|
2254
|
+
cwd: inst.path,
|
|
2255
|
+
stdio: "inherit",
|
|
2256
|
+
env: { ...process.env },
|
|
2257
|
+
});
|
|
2258
|
+
if (result.error) die(`runtime command failed: ${result.error.message}`);
|
|
2259
|
+
process.exitCode = result.status ?? 1;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2119
2262
|
// ── settings ───────────────────────────────────────────────────────
|
|
2120
2263
|
//
|
|
2121
2264
|
// The launcher stays a THIN caller: every config change shells out to the
|
|
@@ -2145,17 +2288,442 @@ function settingsDump(inst) {
|
|
|
2145
2288
|
try { return JSON.parse(r.stdout); } catch { return null; }
|
|
2146
2289
|
}
|
|
2147
2290
|
|
|
2291
|
+
// ── runtime upgrade (per-instance, settings-first) ──────────────────
|
|
2292
|
+
// The launcher stays a thin caller: the transactional engine, gates,
|
|
2293
|
+
// activation, and rollback live in the instance's Python Runtime behind
|
|
2294
|
+
// bin/runtime-upgrade.sh. The launcher renders that state and forwards
|
|
2295
|
+
// explicit verbs — one source of truth, no JS reimplementation.
|
|
2296
|
+
|
|
2297
|
+
const RUNTIME_MVP_VERSION_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-runtime-mvp\.(0|[1-9]\d*)$/;
|
|
2298
|
+
const RUNTIME_MVP_REGISTRY_URL = process.env.EGREGORE_RUNTIME_MVP_REGISTRY_URL
|
|
2299
|
+
|| "https://registry.npmjs.org/create-egregore/runtime-mvp";
|
|
2300
|
+
|
|
2301
|
+
function upgradeScriptPath(inst) {
|
|
2302
|
+
return path.join(inst.path, "bin", "runtime-upgrade.sh");
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
// After the Runtime cutover, a Connected instance's hosted link no longer
|
|
2306
|
+
// serves retrieval — saying "hosted graph active" would misstate what the
|
|
2307
|
+
// connection is for. Mirror the shell gate (bin/search.sh): stable org
|
|
2308
|
+
// identity composed with the main installation path keys the activation
|
|
2309
|
+
// record; only a real record flips the wording.
|
|
2310
|
+
function upgradedGraphRetrievalOff(instPath) {
|
|
2311
|
+
try {
|
|
2312
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(instPath, "egregore.json"), "utf-8"));
|
|
2313
|
+
const orgId = String(cfg.org_id || "").trim();
|
|
2314
|
+
if (!orgId) return false;
|
|
2315
|
+
let main = instPath;
|
|
2316
|
+
const gitFile = path.join(instPath, ".git");
|
|
2317
|
+
if (fs.existsSync(gitFile) && fs.statSync(gitFile).isFile()) {
|
|
2318
|
+
const m = /^gitdir: (.*)$/m.exec(fs.readFileSync(gitFile, "utf-8"));
|
|
2319
|
+
if (m && m[1].includes("/.git/worktrees/")) main = m[1].split("/.git/worktrees/")[0];
|
|
2320
|
+
}
|
|
2321
|
+
main = fs.realpathSync(main);
|
|
2322
|
+
const key = crypto.createHash("sha256").update(`${orgId}|${main}`).digest("hex").slice(0, 16);
|
|
2323
|
+
const base = process.env.EGREGORE_UPGRADE_ROOT || path.join(os.homedir(), ".egregore", "runtime", "upgrade");
|
|
2324
|
+
const record = JSON.parse(fs.readFileSync(path.join(base, key, "active.json"), "utf-8"));
|
|
2325
|
+
return record.retrieval === "runtime-qmd";
|
|
2326
|
+
} catch {
|
|
2327
|
+
return false;
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
function connectedModeSuffix(instPath) {
|
|
2332
|
+
return upgradedGraphRetrievalOff(instPath)
|
|
2333
|
+
? "· hosted services · graph retrieval off"
|
|
2334
|
+
: "· hosted graph active";
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
// An instance that predates the bridge (0.20.1 and earlier) is still
|
|
2338
|
+
// upgradable: the installed launcher package carries the candidate's own
|
|
2339
|
+
// engine, so the bootstrap never depends on a git sync delivering it.
|
|
2340
|
+
// EGREGORE_RUNTIME_PACKAGED_BRIDGE is the test seam ("" disables).
|
|
2341
|
+
function packagedUpgradeScript() {
|
|
2342
|
+
const seeded = process.env.EGREGORE_RUNTIME_PACKAGED_BRIDGE;
|
|
2343
|
+
if (seeded !== undefined) return seeded || null;
|
|
2344
|
+
const script = path.join(__dirname, "..", "runtime", "claude", "bin", "runtime-upgrade.sh");
|
|
2345
|
+
return fs.existsSync(script) ? script : null;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
function resolveUpgradeBridge(inst) {
|
|
2349
|
+
const own = upgradeScriptPath(inst);
|
|
2350
|
+
if (fs.existsSync(own)) return { script: own, env: {} };
|
|
2351
|
+
const packaged = packagedUpgradeScript();
|
|
2352
|
+
if (packaged && fs.existsSync(packaged)) {
|
|
2353
|
+
return { script: packaged, env: { EGREGORE_INSTANCE_ROOT: inst.path } };
|
|
2354
|
+
}
|
|
2355
|
+
return null;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
function runUpgrade(inst, args, timeout = 60000) {
|
|
2359
|
+
const bridge = resolveUpgradeBridge(inst);
|
|
2360
|
+
if (!bridge) {
|
|
2361
|
+
return { status: 127, stdout: "", stderr: "Runtime update is unavailable — no upgrade engine in this egregore or the installed launcher package.\n", missing: true };
|
|
2362
|
+
}
|
|
2363
|
+
try {
|
|
2364
|
+
return spawnSync("bash", [bridge.script, ...args], { cwd: inst.path, stdio: "pipe", encoding: "utf-8", timeout, env: { ...process.env, ...bridge.env } });
|
|
2365
|
+
} catch (err) {
|
|
2366
|
+
return { status: 1, stdout: "", stderr: String(err) };
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
// ── privacy & access + telemetry (Settings sections) ───────────────
|
|
2371
|
+
// Thin callers over deterministic adapters: bin/settings.sh privacy and
|
|
2372
|
+
// bin/telemetry.sh. The Runtime authorization backend supplies identity,
|
|
2373
|
+
// membership, and capability truth; the launcher only renders it. No model
|
|
2374
|
+
// round-trip, no raw JSON shown, no secrets or internal paths.
|
|
2375
|
+
|
|
2376
|
+
function runTelemetry(inst, args) {
|
|
2377
|
+
const script = path.join(inst.path, "bin", "telemetry.sh");
|
|
2378
|
+
if (!fs.existsSync(script)) return { status: 127, stdout: "", stderr: "telemetry adapter unavailable\n" };
|
|
2379
|
+
try {
|
|
2380
|
+
return spawnSync("bash", [script, ...args], { cwd: inst.path, stdio: "pipe", encoding: "utf-8", timeout: 15000 });
|
|
2381
|
+
} catch (err) {
|
|
2382
|
+
return { status: 1, stdout: "", stderr: String(err) };
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
function privacySnapshot(inst) {
|
|
2387
|
+
const r = runSettings(inst, ["privacy"]);
|
|
2388
|
+
if (!r || r.status !== 0 || !r.stdout) return null;
|
|
2389
|
+
try { return JSON.parse(r.stdout); } catch { return null; }
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
function telemetrySnapshot(inst) {
|
|
2393
|
+
const r = runTelemetry(inst, ["status", "--json"]);
|
|
2394
|
+
if (!r || r.status !== 0 || !r.stdout) return null;
|
|
2395
|
+
try { return JSON.parse(r.stdout); } catch { return null; }
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
function formatPrivacyLines(snapshot) {
|
|
2399
|
+
if (!snapshot) return ["Privacy & access state is unavailable for this egregore."];
|
|
2400
|
+
const a = snapshot.access || {};
|
|
2401
|
+
const b = snapshot.boundary || {};
|
|
2402
|
+
const lines = [];
|
|
2403
|
+
if (a.status !== "ok") {
|
|
2404
|
+
lines.push("Access needs attention — identity could not be resolved.");
|
|
2405
|
+
return lines;
|
|
2406
|
+
}
|
|
2407
|
+
lines.push(`Member: ${a.display_name || "unknown"}`);
|
|
2408
|
+
lines.push(`Organization: ${a.org_name || "unknown"} — membership ${a.membership_status || "unknown"}`);
|
|
2409
|
+
lines.push(`Details: actor ${String(a.actor_id || "").slice(0, 18)}…`);
|
|
2410
|
+
lines.push("");
|
|
2411
|
+
const caps = a.capabilities || {};
|
|
2412
|
+
const capLine = ["read", "create", "update", "publish", "notify", "org_settings"]
|
|
2413
|
+
.map((k) => `${k.replace("_", " ")} ${caps[k] ? "yes" : "no"}`)
|
|
2414
|
+
.join(" · ");
|
|
2415
|
+
lines.push(`Authorized capabilities: ${capLine}`);
|
|
2416
|
+
lines.push("For publish and notify, yes means you may request the action —");
|
|
2417
|
+
lines.push("every delivery still needs its own explicit approval.");
|
|
2418
|
+
lines.push("Custom roles: not enabled in this MVP.");
|
|
2419
|
+
lines.push(a.admin ? "Admin content: visible (you are an organization admin)" : "Admin content: hidden on Egregore surfaces");
|
|
2420
|
+
lines.push("");
|
|
2421
|
+
lines.push("Shared memory: available to authorized organization members");
|
|
2422
|
+
lines.push("Per-document restrictions: not enabled (raw repository access is organization-wide)");
|
|
2423
|
+
lines.push("Admin-marked content: hidden in Egregore surfaces from non-admin members");
|
|
2424
|
+
lines.push("External publication of admin-marked content: blocked unless an authorized admin separately confirms");
|
|
2425
|
+
lines.push("Publications require approval; notifications require separate exact approval.");
|
|
2426
|
+
lines.push("");
|
|
2427
|
+
lines.push(`Boundary posture: ${b.posture || "standard"}${b.locked ? " · organization policy locked" : ""}`);
|
|
2428
|
+
lines.push(`Other Egregore instances: ${snapshot.isolation ? snapshot.isolation.foreign_instances_denied : 0} isolated (hard, no consent path)`);
|
|
2429
|
+
const orgRoots = (b.org_read_roots || []).length;
|
|
2430
|
+
const personalRoots = b.personal_read_roots || [];
|
|
2431
|
+
lines.push(`Organization read roots: ${orgRoots} (managed by your organization)`);
|
|
2432
|
+
lines.push(`Personal read roots: ${personalRoots.length ? personalRoots.join(", ") : "none"}`);
|
|
2433
|
+
lines.push(
|
|
2434
|
+
snapshot.graph_retrieval === "not-used-by-this-runtime"
|
|
2435
|
+
? "Graph retrieval: not used by this Runtime"
|
|
2436
|
+
: "Graph retrieval: legacy configuration",
|
|
2437
|
+
);
|
|
2438
|
+
return lines;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
function telemetryEvents(inst, n = 50) {
|
|
2442
|
+
const r = runTelemetry(inst, ["inspect", String(n), "--json"]);
|
|
2443
|
+
if (!r || r.status !== 0 || !r.stdout) return [];
|
|
2444
|
+
try {
|
|
2445
|
+
const events = JSON.parse(r.stdout);
|
|
2446
|
+
return Array.isArray(events) ? events : [];
|
|
2447
|
+
} catch { return []; }
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
function formatEventRow(event) {
|
|
2451
|
+
const at = String(event.occurred_at || "").replace("T", " ").slice(0, 16) || "????-?? ??:??";
|
|
2452
|
+
const metrics = event.metrics || {};
|
|
2453
|
+
const what = metrics.command || metrics.subcommand || metrics.action || "";
|
|
2454
|
+
const extras = [];
|
|
2455
|
+
if (metrics.duration_ms != null) extras.push(`${metrics.duration_ms}ms`);
|
|
2456
|
+
if (metrics.model) extras.push(String(metrics.model));
|
|
2457
|
+
if (metrics.result) extras.push(String(metrics.result));
|
|
2458
|
+
return `${at} ${pad(String(event.event_type || "event"), 12)} ${pad(String(what), 16)} ${extras.join(" · ")}`;
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
function listSubdirectories(dir, showHidden) {
|
|
2462
|
+
try {
|
|
2463
|
+
return fs.readdirSync(dir, { withFileTypes: true })
|
|
2464
|
+
.filter((entry) => entry.isDirectory() && (showHidden || !entry.name.startsWith(".")))
|
|
2465
|
+
.map((entry) => entry.name)
|
|
2466
|
+
.sort();
|
|
2467
|
+
} catch { return []; }
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
function formatTelemetryLines(status) {
|
|
2471
|
+
if (!status) return ["Telemetry state is unavailable for this egregore."];
|
|
2472
|
+
const lines = [];
|
|
2473
|
+
lines.push(`Telemetry: ${status.enabled ? "On" : "Off"}${status.reason ? ` (${status.reason})` : ""}`);
|
|
2474
|
+
lines.push(`Notice shown: ${status.notice_shown ? "yes" : "not yet"}`);
|
|
2475
|
+
lines.push(
|
|
2476
|
+
status.buffered_events > 0
|
|
2477
|
+
? `Local events waiting: ${status.buffered_events}`
|
|
2478
|
+
: "No buffered events",
|
|
2479
|
+
);
|
|
2480
|
+
if (status.last_event_at) lines.push(`Last event: ${status.last_event_at}`);
|
|
2481
|
+
lines.push("Events are held in a local buffer and never shared automatically.");
|
|
2482
|
+
lines.push("Collected: command names, timings, counts, model tiers — documented metadata only.");
|
|
2483
|
+
lines.push("Never collected: file contents, code, prompts, document excerpts,");
|
|
2484
|
+
lines.push("environment values, credentials, message bodies, personal memory content.");
|
|
2485
|
+
lines.push("Turning telemetry on or off is a personal setting for this member only.");
|
|
2486
|
+
return lines;
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
function upgradeStatus(inst, { fetch = false } = {}) {
|
|
2490
|
+
const args = ["status"]; if (fetch) args.push("--fetch");
|
|
2491
|
+
const r = runUpgrade(inst, args);
|
|
2492
|
+
if (!r || r.status !== 0 || !r.stdout) return null;
|
|
2493
|
+
try { return JSON.parse(r.stdout); } catch { return null; }
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
function upgradeStatusAsync(inst, cb) {
|
|
2497
|
+
const bridge = resolveUpgradeBridge(inst);
|
|
2498
|
+
if (!bridge) return cb(null);
|
|
2499
|
+
let buf = "";
|
|
2500
|
+
try {
|
|
2501
|
+
const child = spawn("bash", [bridge.script, "status"], { cwd: inst.path, stdio: ["ignore", "pipe", "ignore"], env: { ...process.env, ...bridge.env } });
|
|
2502
|
+
child.stdout.on("data", (d) => { buf += d; });
|
|
2503
|
+
child.on("close", () => { try { cb(JSON.parse(buf)); } catch { cb(null); } });
|
|
2504
|
+
child.on("error", () => cb(null));
|
|
2505
|
+
} catch { cb(null); }
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
// Exact candidate resolution: the runtime-mvp dist-tag only, validated
|
|
2509
|
+
// against the prerelease scheme — never latest, never a retired scheme.
|
|
2510
|
+
// EGREGORE_RUNTIME_MVP_CANDIDATE is the offline/test seam.
|
|
2511
|
+
async function fetchRuntimeMvpCandidate() {
|
|
2512
|
+
const seeded = process.env.EGREGORE_RUNTIME_MVP_CANDIDATE;
|
|
2513
|
+
if (seeded !== undefined) return RUNTIME_MVP_VERSION_RE.test(seeded) ? seeded : null;
|
|
2514
|
+
try {
|
|
2515
|
+
const url = new URL(RUNTIME_MVP_REGISTRY_URL);
|
|
2516
|
+
const result = await requestJson({
|
|
2517
|
+
hostname: url.hostname,
|
|
2518
|
+
port: url.port || undefined,
|
|
2519
|
+
path: `${url.pathname}${url.search}`,
|
|
2520
|
+
method: "GET",
|
|
2521
|
+
protocol: url.protocol,
|
|
2522
|
+
timeoutMs: 1500,
|
|
2523
|
+
unref: true,
|
|
2524
|
+
headers: { Accept: "application/json" },
|
|
2525
|
+
});
|
|
2526
|
+
const version = result.status === 200 && result.data && result.data.version;
|
|
2527
|
+
return version && RUNTIME_MVP_VERSION_RE.test(version) ? version : null;
|
|
2528
|
+
} catch {
|
|
2529
|
+
return null;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
const UPGRADE_STATUS_LABEL = {
|
|
2534
|
+
none: "no update staged",
|
|
2535
|
+
pending: "staged, not started",
|
|
2536
|
+
preparing: "preparing…",
|
|
2537
|
+
interrupted: "interrupted — resume to continue",
|
|
2538
|
+
failed: "needs attention",
|
|
2539
|
+
"ready-to-activate": "ready to activate",
|
|
2540
|
+
active: "active",
|
|
2541
|
+
cancelled: "cancelled",
|
|
2542
|
+
"rolled-back": "rolled back",
|
|
2543
|
+
};
|
|
2544
|
+
|
|
2545
|
+
function upgradeSummary(st) {
|
|
2546
|
+
// "none" means no activation record — a first-time state, not freshness.
|
|
2547
|
+
if (!st || st.status === "none") return "no update staged";
|
|
2548
|
+
if (st.status === "active") return `${st.active_version || "?"} active`;
|
|
2549
|
+
return UPGRADE_STATUS_LABEL[st.status] || st.status;
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
function upgradeElapsed(st) {
|
|
2553
|
+
const worker = (st && st.worker) || {};
|
|
2554
|
+
const from = worker.started_at || st?.started_at;
|
|
2555
|
+
if (!from) return "";
|
|
2556
|
+
const s = Math.max(0, Math.floor(Date.now() / 1000 - from));
|
|
2557
|
+
return s >= 3600 ? `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m` : s >= 60 ? `${Math.floor(s / 60)}m ${s % 60}s` : `${s}s`;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
// Plain-language body shared by the non-interactive `settings <slug> runtime`
|
|
2561
|
+
// output and the interactive panel. Returns undecorated strings; callers add
|
|
2562
|
+
// color. Never JSON, never internal paths beyond the instance's own root.
|
|
2563
|
+
function formatUpgradeLines(inst, st, { candidate = "" } = {}) {
|
|
2564
|
+
const lines = [];
|
|
2565
|
+
const d = st || { status: "none" };
|
|
2566
|
+
lines.push(`Selected Egregore: ${inst.name || inst.slug} (${inst.slug || "?"})`);
|
|
2567
|
+
lines.push(`Location: ${inst.path}`);
|
|
2568
|
+
lines.push("");
|
|
2569
|
+
const activeLabel = d.active_version ? `${d.active_version} active` : "not yet activated here";
|
|
2570
|
+
lines.push(`Runtime: ${activeLabel}`
|
|
2571
|
+
+ (d.candidate_version ? ` → candidate ${d.candidate_version}` : candidate ? ` → candidate ${candidate} available` : ""));
|
|
2572
|
+
lines.push(`Status: ${UPGRADE_STATUS_LABEL[d.status] || d.status}`);
|
|
2573
|
+
if (d.candidate_digest) lines.push(`Package digest: sha256 ${String(d.candidate_digest).slice(0, 16)}…`);
|
|
2574
|
+
if (d.failure && d.failure.message) lines.push(`Attention: ${d.failure.message}`);
|
|
2575
|
+
if (d.rollback_version && d.status !== "none") lines.push(`Rollback target: ${d.rollback_version}`);
|
|
2576
|
+
const ts = d.team_sync;
|
|
2577
|
+
if (ts && ts.label) lines.push(`Team memory: ${ts.label}`);
|
|
2578
|
+
if (d.status === "active") {
|
|
2579
|
+
lines.push("Organizational retrieval: Runtime/QMD");
|
|
2580
|
+
lines.push("Graph retrieval: not used by this Runtime version");
|
|
2581
|
+
} else if (d.status !== "none") {
|
|
2582
|
+
lines.push("Previous Runtime remains active until activation.");
|
|
2583
|
+
}
|
|
2584
|
+
if (Array.isArray(d.stages) && d.status !== "none" && d.status !== "active") {
|
|
2585
|
+
lines.push("");
|
|
2586
|
+
for (const stage of d.stages) {
|
|
2587
|
+
const glyph = stage.state === "done" ? "✓" : stage.state === "running" ? "◦" : stage.state === "failed" ? "✗" : "·";
|
|
2588
|
+
let detail = "";
|
|
2589
|
+
if (stage.key === "embed" || stage.key === "delta") {
|
|
2590
|
+
const p = d.progress || {};
|
|
2591
|
+
if (stage.state === "running") {
|
|
2592
|
+
const parts = [];
|
|
2593
|
+
if (p.vectors) parts.push(`${p.vectors} chunks embedded`);
|
|
2594
|
+
if (p.pending) parts.push(`${p.pending} pending`);
|
|
2595
|
+
parts.push(`${upgradeElapsed(d)} elapsed`);
|
|
2596
|
+
detail = ` — ${parts.join(" · ")}`;
|
|
2597
|
+
} else if (stage.state === "done" && stage.detail) {
|
|
2598
|
+
detail = ` — ${stage.detail}`;
|
|
2599
|
+
}
|
|
2600
|
+
} else if (stage.state === "failed" && stage.detail) {
|
|
2601
|
+
detail = ` — ${stage.detail}`;
|
|
2602
|
+
}
|
|
2603
|
+
lines.push(` ${glyph} ${stage.label}${detail}`);
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return lines;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
const UPGRADE_STAYS = [
|
|
2610
|
+
"Your team memory and organizational history",
|
|
2611
|
+
"Your identity and organization membership",
|
|
2612
|
+
"Permissions and authorization",
|
|
2613
|
+
"Projects, handoffs, and artifacts",
|
|
2614
|
+
"Connection configuration",
|
|
2615
|
+
"The current Runtime, until the new one is fully ready",
|
|
2616
|
+
];
|
|
2617
|
+
const UPGRADE_CHANGES = [
|
|
2618
|
+
"Runtime version",
|
|
2619
|
+
"Organizational retrieval moves to Runtime/QMD",
|
|
2620
|
+
"Keyword and meaning search become owned by this Egregore",
|
|
2621
|
+
"Graph retrieval stops after activation (kept only for rollback)",
|
|
2622
|
+
"Cross-session continuity uses the new Runtime",
|
|
2623
|
+
"Readiness and synchronization become visible here in Settings",
|
|
2624
|
+
];
|
|
2625
|
+
|
|
2626
|
+
async function cmdSettingsRuntime(inst, args) {
|
|
2627
|
+
const action = args[0] || "status";
|
|
2628
|
+
const fetchFlag = args.includes("--fetch");
|
|
2629
|
+
const emit = (st, extra = {}) => {
|
|
2630
|
+
for (const line of formatUpgradeLines(inst, st, extra)) process.stdout.write(line + "\n");
|
|
2631
|
+
};
|
|
2632
|
+
if (action === "status" || action === "review") {
|
|
2633
|
+
const st = upgradeStatus(inst, { fetch: fetchFlag });
|
|
2634
|
+
if (st === null) { process.stderr.write("Runtime update state is unavailable for this egregore.\n"); process.exitCode = 1; return; }
|
|
2635
|
+
emit(st);
|
|
2636
|
+
if (action === "review" || (st.status !== "active" && st.status !== "none")) {
|
|
2637
|
+
process.stdout.write("\nWhat stays:\n");
|
|
2638
|
+
for (const s of UPGRADE_STAYS) process.stdout.write(` · ${s}\n`);
|
|
2639
|
+
process.stdout.write("What changes:\n");
|
|
2640
|
+
for (const c of UPGRADE_CHANGES) process.stdout.write(` · ${c}\n`);
|
|
2641
|
+
}
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
if (action === "init") {
|
|
2645
|
+
const version = (args[1] || "").trim();
|
|
2646
|
+
const tarball = (args[2] || "").trim();
|
|
2647
|
+
if (!RUNTIME_MVP_VERSION_RE.test(version)) {
|
|
2648
|
+
process.stderr.write("Runtime update needs an exact candidate like 0.21.0-runtime-mvp.1.\n");
|
|
2649
|
+
process.exitCode = 1; return;
|
|
2650
|
+
}
|
|
2651
|
+
if (!tarball || !fs.existsSync(tarball)) {
|
|
2652
|
+
process.stderr.write("Runtime update installs actual packaged bytes: egregore settings <slug> runtime init <version> <candidate.tgz>\n");
|
|
2653
|
+
process.exitCode = 1; return;
|
|
2654
|
+
}
|
|
2655
|
+
const r = runUpgrade(inst, ["init", "--candidate", version, "--tarball", path.resolve(tarball)]);
|
|
2656
|
+
if (r.status !== 0) { process.stderr.write(r.stderr || "could not stage the candidate\n"); process.exitCode = r.status; return; }
|
|
2657
|
+
emit(upgradeStatus(inst) || null);
|
|
2658
|
+
return;
|
|
2659
|
+
}
|
|
2660
|
+
if (["prepare", "activate", "cancel", "rollback"].includes(action)) {
|
|
2661
|
+
const r = runUpgrade(inst, [action]);
|
|
2662
|
+
if (r.status !== 0) { process.stderr.write(r.stderr || `${action} failed\n`); process.exitCode = r.status; return; }
|
|
2663
|
+
const st = upgradeStatus(inst);
|
|
2664
|
+
emit(st);
|
|
2665
|
+
if (action === "activate" && st && st.status === "active") {
|
|
2666
|
+
process.stdout.write("\nUpdate complete. Start a session to work on the new Runtime.\n");
|
|
2667
|
+
}
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2670
|
+
process.stderr.write("usage: egregore settings <slug> runtime [status|review|init <version>|prepare|activate|cancel|rollback]\n");
|
|
2671
|
+
process.exitCode = 2;
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2148
2674
|
async function cmdSettings(args) {
|
|
2149
2675
|
const registry = readRegistry();
|
|
2150
2676
|
if (registry.length === 0) die("no egregores installed yet.\n run: npx -y create-egregore@latest");
|
|
2151
|
-
const DOMAINS = new Set(["hosting", "workflow", "repo", "admin", "people", "dump"]);
|
|
2677
|
+
const DOMAINS = new Set(["hosting", "workflow", "repo", "admin", "people", "dump", "runtime", "privacy", "telemetry", "boundary"]);
|
|
2152
2678
|
let rest = args.slice();
|
|
2153
2679
|
let slug = "";
|
|
2154
2680
|
if (rest.length && !DOMAINS.has(rest[0])) { slug = rest[0]; rest = rest.slice(1); }
|
|
2155
2681
|
const inst = resolveInviteInstance(registry, slug);
|
|
2156
2682
|
if (!inst) {
|
|
2157
|
-
die(`multiple egregores installed; choose one:\n egregore settings <slug> [hosting|workflow|repo|admin|people]\n run: egregore ls`);
|
|
2683
|
+
die(`multiple egregores installed; choose one:\n egregore settings <slug> [runtime|hosting|workflow|repo|admin|people|privacy|telemetry]\n run: egregore ls`);
|
|
2684
|
+
}
|
|
2685
|
+
// Runtime update is Runtime-owned state, not org config — it routes to the
|
|
2686
|
+
// upgrade bridge instead of bin/settings.sh.
|
|
2687
|
+
if (rest[0] === "runtime") return cmdSettingsRuntime(inst, rest.slice(1));
|
|
2688
|
+
// Privacy & access: rendered plain-language snapshot backed by the Runtime
|
|
2689
|
+
// authorization decision — never raw JSON, secrets, or internal paths.
|
|
2690
|
+
if (rest[0] === "privacy") {
|
|
2691
|
+
for (const line of formatPrivacyLines(privacySnapshot(inst))) console.log(line);
|
|
2692
|
+
return;
|
|
2693
|
+
}
|
|
2694
|
+
// Telemetry: personal, opt-out, content-free. Mutations require the exact
|
|
2695
|
+
// --confirm because a non-interactive verb has no y/N checkpoint.
|
|
2696
|
+
if (rest[0] === "telemetry") {
|
|
2697
|
+
const verb = rest[1] || "status";
|
|
2698
|
+
if (verb === "status") {
|
|
2699
|
+
for (const line of formatTelemetryLines(telemetrySnapshot(inst))) console.log(line);
|
|
2700
|
+
return;
|
|
2701
|
+
}
|
|
2702
|
+
if (verb === "inspect") {
|
|
2703
|
+
const n = /^\d+$/.test(rest[2] || "") ? Number(rest[2]) : 20;
|
|
2704
|
+
const events = telemetryEvents(inst, n);
|
|
2705
|
+
if (!events.length) { console.log("No buffered events."); return; }
|
|
2706
|
+
for (const event of events) console.log(formatEventRow(event));
|
|
2707
|
+
return;
|
|
2708
|
+
}
|
|
2709
|
+
if (verb === "on" || verb === "off" || verb === "clear") {
|
|
2710
|
+
if (!rest.includes("--confirm")) {
|
|
2711
|
+
const what = verb === "clear"
|
|
2712
|
+
? `delete ${(telemetrySnapshot(inst) || {}).buffered_events || 0} locally buffered event(s); nothing else is removed`
|
|
2713
|
+
: `turn telemetry ${verb} for this member only`;
|
|
2714
|
+
process.stderr.write(`this will ${what}.\nre-run with --confirm to proceed: egregore settings ${inst.slug} telemetry ${verb} --confirm\n`);
|
|
2715
|
+
process.exitCode = 1;
|
|
2716
|
+
return;
|
|
2717
|
+
}
|
|
2718
|
+
const r = runTelemetry(inst, [verb]);
|
|
2719
|
+
if (r.stdout) process.stdout.write(r.stdout);
|
|
2720
|
+
if (r.stderr) process.stderr.write(r.stderr);
|
|
2721
|
+
process.exitCode = r.status || 0;
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
die("usage: egregore settings <slug> telemetry [status|inspect [n]|on|off|clear] [--confirm]");
|
|
2158
2725
|
}
|
|
2726
|
+
|
|
2159
2727
|
// Interactive editing lives in the launcher (press `s`). With no verb, print
|
|
2160
2728
|
// the snapshot; otherwise forward straight to the deterministic verb.
|
|
2161
2729
|
if (rest.length === 0) rest = ["dump"];
|
|
@@ -2373,7 +2941,7 @@ function renderRuntimePanel({ inst, cursor, width, height }) {
|
|
|
2373
2941
|
boxLine(`${DIM}${inst.path}${RESET}`, innerWidth, margin),
|
|
2374
2942
|
boxLine(
|
|
2375
2943
|
isConnectedInstance(inst)
|
|
2376
|
-
? `${CYAN}◆ CONNECTED${RESET} ${DIM}
|
|
2944
|
+
? `${CYAN}◆ CONNECTED${RESET} ${DIM}${connectedModeSuffix(inst.path)}${RESET}`
|
|
2377
2945
|
: `${DIM}◇ LOCAL · Markdown + Git${RESET}`,
|
|
2378
2946
|
innerWidth,
|
|
2379
2947
|
margin,
|
|
@@ -2413,7 +2981,67 @@ const SETTINGS_DOMAIN_LABEL = { repo: "Managed repos", admin: "Admins", people:
|
|
|
2413
2981
|
const SETTINGS_DOMAIN_NOUN = { repo: "repo name", admin: "github handle", people: "github handle" };
|
|
2414
2982
|
|
|
2415
2983
|
// Same box geometry as renderRuntimePanel so pressing `s` keeps the frame put.
|
|
2416
|
-
|
|
2984
|
+
// Runtime-update panel: renders the durable upgrade state from the Python
|
|
2985
|
+
// engine. Same geometry as the settings panel; plain-language body from
|
|
2986
|
+
// formatUpgradeLines with launcher glyph decoration only.
|
|
2987
|
+
function renderUpgradePanel({ inst, data, candidate, mode, notice, width }) {
|
|
2988
|
+
const outerWidth = Math.min(Math.max(50, width - 2), 126);
|
|
2989
|
+
const innerWidth = Math.max(48, outerWidth - 2);
|
|
2990
|
+
const margin = " ".repeat(Math.max(0, Math.floor((width - outerWidth) / 2)));
|
|
2991
|
+
const label = " runtime update ";
|
|
2992
|
+
const lines = [
|
|
2993
|
+
`${margin}${DIM}┌${"─".repeat(2)}${label}${"─".repeat(Math.max(0, innerWidth - label.length - 2))}┐${RESET}`,
|
|
2994
|
+
emptyBoxLine(innerWidth, margin),
|
|
2995
|
+
];
|
|
2996
|
+
const body = data === undefined
|
|
2997
|
+
? ["Checking this egregore's Runtime state…"]
|
|
2998
|
+
: data === null
|
|
2999
|
+
? ["Runtime update state is unavailable for this egregore."]
|
|
3000
|
+
: formatUpgradeLines(inst, data, { candidate });
|
|
3001
|
+
for (const raw of body) {
|
|
3002
|
+
let line = raw;
|
|
3003
|
+
if (/^ ✓ /.test(raw)) line = ` ${GREEN}✓${RESET} ${raw.slice(4)}`;
|
|
3004
|
+
else if (/^ ◦ /.test(raw)) line = ` ${CYAN}◦${RESET} ${raw.slice(4)}`;
|
|
3005
|
+
else if (/^ ✗ /.test(raw)) line = ` ${RED}✗${RESET} ${raw.slice(4)}`;
|
|
3006
|
+
else if (/^ · /.test(raw)) line = ` ${DIM}·${RESET} ${DIM}${raw.slice(4)}${RESET}`;
|
|
3007
|
+
else if (/^(Location|Rollback target):/.test(raw)) line = `${DIM}${raw}${RESET}`;
|
|
3008
|
+
lines.push(boxLine(line, innerWidth, margin));
|
|
3009
|
+
}
|
|
3010
|
+
const status = data && data.status;
|
|
3011
|
+
if (mode === "confirm-prepare") {
|
|
3012
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3013
|
+
lines.push(boxLine(`${BOLD}What stays${RESET}`, innerWidth, margin));
|
|
3014
|
+
for (const s of UPGRADE_STAYS) lines.push(boxLine(` · ${s}`, innerWidth, margin));
|
|
3015
|
+
lines.push(boxLine(`${BOLD}What changes${RESET}`, innerWidth, margin));
|
|
3016
|
+
for (const c of UPGRADE_CHANGES) lines.push(boxLine(` · ${c}`, innerWidth, margin));
|
|
3017
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3018
|
+
lines.push(boxLine(`${YELLOW}Prepare the update for ${BOLD}${inst.slug}${RESET}${YELLOW} at this location only?${RESET} ${DIM}y / N${RESET}`, innerWidth, margin));
|
|
3019
|
+
} else if (mode === "confirm-activate") {
|
|
3020
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3021
|
+
lines.push(boxLine(`${YELLOW}Activate the new Runtime for ${BOLD}${inst.slug}${RESET}${YELLOW}?${RESET} ${DIM}y / N${RESET}`, innerWidth, margin));
|
|
3022
|
+
} else if (mode === "confirm-rollback") {
|
|
3023
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3024
|
+
lines.push(boxLine(`${YELLOW}Roll ${BOLD}${inst.slug}${RESET}${YELLOW} back to ${data?.rollback_version || "the previous Runtime"}?${RESET} ${DIM}y / N${RESET}`, innerWidth, margin));
|
|
3025
|
+
} else if (mode === "confirm-cancel") {
|
|
3026
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3027
|
+
lines.push(boxLine(`${YELLOW}Cancel preparation? The current Runtime stays untouched.${RESET} ${DIM}y / N${RESET}`, innerWidth, margin));
|
|
3028
|
+
} else {
|
|
3029
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3030
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3031
|
+
const keys = [];
|
|
3032
|
+
if (!status || status === "none" || ["pending", "failed", "interrupted", "cancelled", "rolled-back"].includes(status)) keys.push(`${BOLD}p${RESET}${DIM} prepare${RESET}`);
|
|
3033
|
+
if (status === "ready-to-activate") keys.push(`${BOLD}a${RESET}${DIM} activate${RESET}`);
|
|
3034
|
+
if (status === "preparing") keys.push(`${BOLD}c${RESET}${DIM} cancel${RESET}`);
|
|
3035
|
+
if (status === "active") keys.push(`${BOLD}r${RESET}${DIM} roll back${RESET}`);
|
|
3036
|
+
keys.push(`${DIM}← back · q quit${RESET}`);
|
|
3037
|
+
lines.push(boxLine(keys.join(`${DIM} · ${RESET}`), innerWidth, margin));
|
|
3038
|
+
}
|
|
3039
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3040
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3041
|
+
return lines;
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCursor, mode, input, notice, width, upgrade }) {
|
|
2417
3045
|
const title = inst.slug || inst.name || path.basename(inst.path);
|
|
2418
3046
|
const outerWidth = Math.min(Math.max(50, width - 2), 126);
|
|
2419
3047
|
const innerWidth = Math.max(48, outerWidth - 2);
|
|
@@ -2428,6 +3056,114 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
2428
3056
|
emptyBoxLine(innerWidth, margin),
|
|
2429
3057
|
];
|
|
2430
3058
|
|
|
3059
|
+
if (view === "privacy" || view === "telemetry") {
|
|
3060
|
+
lines.push(boxLine(`${BOLD}${view === "privacy" ? "Privacy & access" : "Telemetry"}${RESET}`, innerWidth, margin));
|
|
3061
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3062
|
+
if (mode === "shareinfo") {
|
|
3063
|
+
const shareLines = (data && data.shareLines) || ["share proposal unavailable"];
|
|
3064
|
+
lines.push(boxLine(`${BOLD}Share proposal${RESET} ${DIM}(nothing has been sent)${RESET}`, innerWidth, margin));
|
|
3065
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3066
|
+
for (const line of shareLines.slice(0, 16)) {
|
|
3067
|
+
lines.push(boxLine(`${line.includes("--confirm") ? "" : DIM}${line}${RESET}`, innerWidth, margin));
|
|
3068
|
+
}
|
|
3069
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3070
|
+
lines.push(boxLine(`${DIM}Sharing completes only by running the confirm command above in a terminal. ← back${RESET}`, innerWidth, margin));
|
|
3071
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3072
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3073
|
+
return lines;
|
|
3074
|
+
}
|
|
3075
|
+
if (mode === "events") {
|
|
3076
|
+
const events = (data && data.telemetryEvents) || [];
|
|
3077
|
+
lines.push(boxLine(`${BOLD}Local events${RESET} ${DIM}(newest last · nothing here ever uploads by itself)${RESET}`, innerWidth, margin));
|
|
3078
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3079
|
+
if (!events.length) {
|
|
3080
|
+
lines.push(boxLine(`${DIM}(no buffered events)${RESET}`, innerWidth, margin));
|
|
3081
|
+
} else {
|
|
3082
|
+
const cursorAt = Math.min(listCursor || 0, events.length - 1);
|
|
3083
|
+
const windowSize = 12;
|
|
3084
|
+
const start = Math.max(0, Math.min(cursorAt - Math.floor(windowSize / 2), events.length - windowSize));
|
|
3085
|
+
events.slice(start, start + windowSize).forEach((event, i) => {
|
|
3086
|
+
const sel = start + i === cursorAt;
|
|
3087
|
+
lines.push(boxLine(`${sel ? `${CYAN}❯${RESET} ` : " "}${sel ? "" : DIM}${formatEventRow(event)}${RESET}`, innerWidth, margin));
|
|
3088
|
+
});
|
|
3089
|
+
if (events.length > windowSize) lines.push(boxLine(`${DIM}${cursorAt + 1}/${events.length}${RESET}`, innerWidth, margin));
|
|
3090
|
+
}
|
|
3091
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3092
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3093
|
+
lines.push(boxLine(`${DIM}↑↓ scroll · ${RESET}${BOLD}e${RESET}${DIM} export to file · ${RESET}${BOLD}s${RESET}${DIM} share (two-step consent) · ← back${RESET}`, innerWidth, margin));
|
|
3094
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3095
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3096
|
+
return lines;
|
|
3097
|
+
}
|
|
3098
|
+
if (mode === "pickdir") {
|
|
3099
|
+
const pick = (data && data.dirPick) || { dir: os.homedir(), entries: [], cursor: 0, hidden: false };
|
|
3100
|
+
lines.push(boxLine(`${BOLD}Choose a directory to allow reading${RESET}`, innerWidth, margin));
|
|
3101
|
+
lines.push(boxLine(`${DIM}${pick.dir}${RESET}`, innerWidth, margin));
|
|
3102
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3103
|
+
if (!pick.entries.length) {
|
|
3104
|
+
lines.push(boxLine(`${DIM}(no subdirectories${pick.hidden ? "" : " — press . to show hidden"})${RESET}`, innerWidth, margin));
|
|
3105
|
+
} else {
|
|
3106
|
+
const windowSize = 10;
|
|
3107
|
+
const start = Math.max(0, Math.min(pick.cursor - Math.floor(windowSize / 2), pick.entries.length - windowSize));
|
|
3108
|
+
pick.entries.slice(start, start + windowSize).forEach((name, i) => {
|
|
3109
|
+
const sel = start + i === pick.cursor;
|
|
3110
|
+
lines.push(boxLine(`${sel ? `${CYAN}❯${RESET} ` : " "}${sel ? BOLD : DIM}${name}/${RESET}`, innerWidth, margin));
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3114
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3115
|
+
lines.push(boxLine(`${DIM}↑↓ nav · → enter descend · ← up · ${RESET}${BOLD}space${RESET}${DIM} allow this directory · . hidden · esc cancel${RESET}`, innerWidth, margin));
|
|
3116
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3117
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3118
|
+
return lines;
|
|
3119
|
+
}
|
|
3120
|
+
if (mode === "pickroot") {
|
|
3121
|
+
const roots = (data && data.privacySnapshot && data.privacySnapshot.boundary && data.privacySnapshot.boundary.personal_read_roots) || [];
|
|
3122
|
+
lines.push(boxLine(`${BOLD}Remove a personal read root${RESET}`, innerWidth, margin));
|
|
3123
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3124
|
+
if (!roots.length) {
|
|
3125
|
+
lines.push(boxLine(`${DIM}(no personal read roots)${RESET}`, innerWidth, margin));
|
|
3126
|
+
} else {
|
|
3127
|
+
roots.forEach((root, i) => {
|
|
3128
|
+
const sel = i === (listCursor || 0);
|
|
3129
|
+
lines.push(boxLine(`${sel ? `${CYAN}❯${RESET} ` : " "}${sel ? BOLD : DIM}${root}${RESET}`, innerWidth, margin));
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3133
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3134
|
+
lines.push(boxLine(`${DIM}↑↓ nav · enter remove · esc cancel${RESET}`, innerWidth, margin));
|
|
3135
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3136
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3137
|
+
return lines;
|
|
3138
|
+
}
|
|
3139
|
+
const body = view === "privacy" ? formatPrivacyLines(data && data.privacySnapshot) : formatTelemetryLines(data && data.telemetrySnapshot);
|
|
3140
|
+
for (const line of body) {
|
|
3141
|
+
lines.push(line === "" ? emptyBoxLine(innerWidth, margin) : boxLine(`${line.startsWith("Access needs") || line.startsWith("Telemetry needs") ? YELLOW : ""}${line}${RESET}`, innerWidth, margin));
|
|
3142
|
+
}
|
|
3143
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3144
|
+
if (mode === "confirm" && input) {
|
|
3145
|
+
lines.push(boxLine(`${YELLOW}${input}${RESET}`, innerWidth, margin));
|
|
3146
|
+
} else if (mode === "input") {
|
|
3147
|
+
lines.push(boxLine(`${BOLD}directory:${RESET} ${input}${DIM}▌${RESET}`, innerWidth, margin));
|
|
3148
|
+
}
|
|
3149
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3150
|
+
if (view === "privacy") {
|
|
3151
|
+
const locked = !!(data && data.privacySnapshot && data.privacySnapshot.boundary && data.privacySnapshot.boundary.locked);
|
|
3152
|
+
lines.push(boxLine(
|
|
3153
|
+
locked
|
|
3154
|
+
? `${DIM}Boundary policy is managed by your organization. ← back · q quit${RESET}`
|
|
3155
|
+
: `${DIM}${RESET}${BOLD}a${RESET}${DIM} add personal read root · ${RESET}${BOLD}r${RESET}${DIM} remove · ← back · q quit${RESET}`,
|
|
3156
|
+
innerWidth, margin,
|
|
3157
|
+
));
|
|
3158
|
+
} else {
|
|
3159
|
+
const on = !!(data && data.telemetrySnapshot && data.telemetrySnapshot.enabled);
|
|
3160
|
+
lines.push(boxLine(`${DIM}${RESET}${BOLD}i${RESET}${DIM} view events · ${RESET}${BOLD}t${RESET}${DIM} turn ${on ? "off" : "on"} · ${RESET}${BOLD}x${RESET}${DIM} clear local buffer · ← back · q quit${RESET}`, innerWidth, margin));
|
|
3161
|
+
}
|
|
3162
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3163
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3164
|
+
return lines;
|
|
3165
|
+
}
|
|
3166
|
+
|
|
2431
3167
|
if (view === "list") {
|
|
2432
3168
|
lines.push(boxLine(`${BOLD}${SETTINGS_DOMAIN_LABEL[domain] || domain}${RESET}`, innerWidth, margin));
|
|
2433
3169
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
@@ -2450,7 +3186,19 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
2450
3186
|
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}a${RESET}${DIM} add · ${RESET}${BOLD}d${RESET}${DIM} delete · ← back · q quit${RESET}`, innerWidth, margin));
|
|
2451
3187
|
}
|
|
2452
3188
|
} else {
|
|
3189
|
+
const upgradeValue = upgrade === undefined
|
|
3190
|
+
? `${DIM}checking…${RESET}`
|
|
3191
|
+
: upgrade === null
|
|
3192
|
+
? `${DIM}unavailable${RESET}`
|
|
3193
|
+
: upgrade.status === "ready-to-activate"
|
|
3194
|
+
? `${GREEN}${upgradeSummary(upgrade)}${RESET}`
|
|
3195
|
+
: upgrade.status === "failed" || upgrade.status === "interrupted"
|
|
3196
|
+
? `${YELLOW}${upgradeSummary(upgrade)}${RESET}`
|
|
3197
|
+
: `${DIM}${upgradeSummary(upgrade)}${RESET}`;
|
|
2453
3198
|
const rows = [
|
|
3199
|
+
{ name: "Runtime update", value: upgradeValue },
|
|
3200
|
+
{ name: "Privacy & access", value: `${DIM}identity · boundary · consent${RESET}` },
|
|
3201
|
+
{ name: "Telemetry", value: `${DIM}personal · opt-out${RESET}` },
|
|
2454
3202
|
{ name: "Hosted Artifacts", value: (d.hosting !== false) ? `${GREEN}ON${RESET}` : `${YELLOW}OFF${RESET}` },
|
|
2455
3203
|
{
|
|
2456
3204
|
name: "Git workflow",
|
|
@@ -2472,7 +3220,7 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
2472
3220
|
});
|
|
2473
3221
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
2474
3222
|
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
2475
|
-
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}enter${RESET}${DIM} ${cursor
|
|
3223
|
+
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}enter${RESET}${DIM} ${cursor === 3 || cursor === 4 ? "toggle" : "open"} · ← back · q quit${RESET}`, innerWidth, margin));
|
|
2476
3224
|
}
|
|
2477
3225
|
|
|
2478
3226
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
@@ -2597,6 +3345,22 @@ async function browser(args = {}) {
|
|
|
2597
3345
|
return;
|
|
2598
3346
|
}
|
|
2599
3347
|
|
|
3348
|
+
if (state.upgradeInst) {
|
|
3349
|
+
const upgradeLines = renderUpgradePanel({
|
|
3350
|
+
inst: state.upgradeInst,
|
|
3351
|
+
data: state.upgradeData,
|
|
3352
|
+
candidate: state.upgradeCandidate,
|
|
3353
|
+
mode: state.upgradeMode,
|
|
3354
|
+
notice: state.upgradeNotice,
|
|
3355
|
+
width: w,
|
|
3356
|
+
});
|
|
3357
|
+
for (const line of upgradeLines) out.push(line + ANSI.clearLine + "\n");
|
|
3358
|
+
const upgradeRemaining = Math.max(0, h - upgradeLines.length - 1);
|
|
3359
|
+
for (let i = 0; i < upgradeRemaining; i++) out.push(ANSI.clearLine + "\n");
|
|
3360
|
+
process.stdout.write(out.join(""));
|
|
3361
|
+
return;
|
|
3362
|
+
}
|
|
3363
|
+
|
|
2600
3364
|
if (state.settingsInst) {
|
|
2601
3365
|
const settingsLines = renderSettingsPanel({
|
|
2602
3366
|
inst: state.settingsInst,
|
|
@@ -2610,6 +3374,7 @@ async function browser(args = {}) {
|
|
|
2610
3374
|
input: state.settingsInput,
|
|
2611
3375
|
notice: state.settingsNotice,
|
|
2612
3376
|
width: w,
|
|
3377
|
+
upgrade: state.settingsUpgrade,
|
|
2613
3378
|
});
|
|
2614
3379
|
for (const line of settingsLines) out.push(line + ANSI.clearLine + "\n");
|
|
2615
3380
|
const remainingRows = Math.max(0, h - settingsLines.length - 1);
|
|
@@ -2736,7 +3501,7 @@ async function browser(args = {}) {
|
|
|
2736
3501
|
: ` ${label("path")} ${truncate(selected.path, valW)}`);
|
|
2737
3502
|
if (pv.org) previewLines.push(` ${label("org")} ${truncate(`${pv.org} ${DIM}(${pv.githubOrg || "?"})${RESET}`, valW)}`);
|
|
2738
3503
|
previewLines.push(pv.connected
|
|
2739
|
-
? ` ${label("mode")} ${CYAN}◆ CONNECTED${RESET} ${DIM}
|
|
3504
|
+
? ` ${label("mode")} ${CYAN}◆ CONNECTED${RESET} ${DIM}${connectedModeSuffix(selected.path)}${RESET}`
|
|
2740
3505
|
: ` ${label("mode")} ${DIM}◇ LOCAL · Markdown + Git${RESET}`);
|
|
2741
3506
|
if (pv.branch) previewLines.push(` ${label("branch")} ${BOLD}${pv.branch}${RESET}`);
|
|
2742
3507
|
if (pv.lastCommit) previewLines.push(` ${label("last")} ${DIM}${truncate(pv.lastCommit, valW)}${RESET}`);
|
|
@@ -2837,9 +3602,27 @@ async function browser(args = {}) {
|
|
|
2837
3602
|
const onResize = () => render(); // render() itself no-ops once done is set
|
|
2838
3603
|
let onSigint;
|
|
2839
3604
|
let onSigterm;
|
|
3605
|
+
const stopUpgradePoll = () => {
|
|
3606
|
+
if (state.upgradePoll) { clearInterval(state.upgradePoll); state.upgradePoll = null; }
|
|
3607
|
+
};
|
|
3608
|
+
const refreshUpgrade = () => {
|
|
3609
|
+
if (!state.upgradeInst) return;
|
|
3610
|
+
upgradeStatusAsync(state.upgradeInst, (st) => {
|
|
3611
|
+
if (!state.upgradeInst) return;
|
|
3612
|
+
state.upgradeData = st;
|
|
3613
|
+
if (st && st.status === "preparing") {
|
|
3614
|
+
if (!state.upgradePoll) state.upgradePoll = setInterval(refreshUpgrade, 2500);
|
|
3615
|
+
} else {
|
|
3616
|
+
stopUpgradePoll();
|
|
3617
|
+
}
|
|
3618
|
+
render();
|
|
3619
|
+
});
|
|
3620
|
+
};
|
|
3621
|
+
|
|
2840
3622
|
const cleanup = () => {
|
|
2841
3623
|
if (done) return;
|
|
2842
3624
|
done = true;
|
|
3625
|
+
stopUpgradePoll();
|
|
2843
3626
|
process.stdin.setRawMode(false);
|
|
2844
3627
|
process.stdin.pause();
|
|
2845
3628
|
process.stdin.removeAllListeners("keypress");
|
|
@@ -2893,11 +3676,195 @@ async function browser(args = {}) {
|
|
|
2893
3676
|
if (!key) return;
|
|
2894
3677
|
if (isMouseEvent(chunk, key)) return; // drop scroll-wheel / mouse escape sequences
|
|
2895
3678
|
|
|
3679
|
+
if (state.upgradeInst) {
|
|
3680
|
+
if (key.ctrl && key.name === "c") { cleanup(); process.exit(130); }
|
|
3681
|
+
if (key.name === "q") { cleanup(); resolve(); return; }
|
|
3682
|
+
if (state.upgradeMode && state.upgradeMode.startsWith("confirm-")) {
|
|
3683
|
+
const mode = state.upgradeMode;
|
|
3684
|
+
state.upgradeMode = "view";
|
|
3685
|
+
if (chunk === "y" || chunk === "Y") {
|
|
3686
|
+
const inst = state.upgradeInst;
|
|
3687
|
+
if (mode === "confirm-prepare") {
|
|
3688
|
+
const r = runUpgrade(inst, ["prepare"]);
|
|
3689
|
+
state.upgradeNotice = r.status === 0
|
|
3690
|
+
? `${DIM}Preparing in the background — safe to leave this screen.${RESET}`
|
|
3691
|
+
: `${YELLOW}${(r.stderr || "prepare failed").trim().split("\n")[0]}${RESET}`;
|
|
3692
|
+
} else if (mode === "confirm-activate") {
|
|
3693
|
+
const r = runUpgrade(inst, ["activate"]);
|
|
3694
|
+
state.upgradeNotice = r.status === 0
|
|
3695
|
+
? `${GREEN}Update complete. Start a session to work on the new Runtime.${RESET}`
|
|
3696
|
+
: `${YELLOW}${(r.stderr || "activation refused — a gate has not passed").trim().split("\n")[0]}${RESET}`;
|
|
3697
|
+
} else if (mode === "confirm-rollback") {
|
|
3698
|
+
const r = runUpgrade(inst, ["rollback"]);
|
|
3699
|
+
state.upgradeNotice = r.status === 0
|
|
3700
|
+
? `${DIM}Rolled back. The previous Runtime is active again.${RESET}`
|
|
3701
|
+
: `${YELLOW}${(r.stderr || "rollback failed").trim().split("\n")[0]}${RESET}`;
|
|
3702
|
+
} else if (mode === "confirm-cancel") {
|
|
3703
|
+
runUpgrade(inst, ["cancel"]);
|
|
3704
|
+
state.upgradeNotice = `${DIM}Preparation cancelled. The current Runtime was never touched.${RESET}`;
|
|
3705
|
+
}
|
|
3706
|
+
refreshUpgrade();
|
|
3707
|
+
}
|
|
3708
|
+
render(); return;
|
|
3709
|
+
}
|
|
3710
|
+
if (key.name === "escape" || key.name === "left") {
|
|
3711
|
+
stopUpgradePoll();
|
|
3712
|
+
state.settingsUpgrade = state.upgradeData;
|
|
3713
|
+
state.upgradeInst = null; state.upgradeNotice = "";
|
|
3714
|
+
render(); return;
|
|
3715
|
+
}
|
|
3716
|
+
const status = state.upgradeData && state.upgradeData.status;
|
|
3717
|
+
if (chunk === "p" && (!status || ["none", "pending", "failed", "interrupted", "cancelled", "rolled-back"].includes(status))) {
|
|
3718
|
+
const staged = state.upgradeData
|
|
3719
|
+
&& !["none", "cancelled", "rolled-back"].includes(status)
|
|
3720
|
+
&& state.upgradeData.candidate_version;
|
|
3721
|
+
if (!staged) {
|
|
3722
|
+
state.upgradeNotice = `${DIM}Stage a candidate package first: egregore settings ${state.upgradeInst.slug} runtime init <version> <candidate.tgz>${RESET}`;
|
|
3723
|
+
render(); return;
|
|
3724
|
+
}
|
|
3725
|
+
state.upgradeMode = "confirm-prepare"; render(); return;
|
|
3726
|
+
}
|
|
3727
|
+
if (chunk === "a" && status === "ready-to-activate") { state.upgradeMode = "confirm-activate"; render(); return; }
|
|
3728
|
+
if (chunk === "c" && status === "preparing") { state.upgradeMode = "confirm-cancel"; render(); return; }
|
|
3729
|
+
if (chunk === "r" && status === "active") { state.upgradeMode = "confirm-rollback"; render(); return; }
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3732
|
+
|
|
2896
3733
|
if (state.settingsInst) {
|
|
2897
3734
|
const S = state;
|
|
2898
3735
|
if (key.ctrl && key.name === "c") { cleanup(); process.exit(130); }
|
|
2899
3736
|
if (key.name === "q") { cleanup(); resolve(); return; }
|
|
2900
3737
|
|
|
3738
|
+
if (S.settingsView === "privacy" || S.settingsView === "telemetry") {
|
|
3739
|
+
const backToMenu = () => {
|
|
3740
|
+
S.settingsView = "menu"; S.settingsMode = "browse"; S.settingsInput = ""; S.settingsNotice = ""; render();
|
|
3741
|
+
};
|
|
3742
|
+
const refreshPanel = () => {
|
|
3743
|
+
if (S.settingsView === "privacy") S.settingsData = { ...(S.settingsData || {}), privacySnapshot: privacySnapshot(S.settingsInst) };
|
|
3744
|
+
else S.settingsData = { ...(S.settingsData || {}), telemetrySnapshot: telemetrySnapshot(S.settingsInst) };
|
|
3745
|
+
};
|
|
3746
|
+
if (S.settingsMode === "events") {
|
|
3747
|
+
const events = (S.settingsData && S.settingsData.telemetryEvents) || [];
|
|
3748
|
+
if (key.name === "escape" || key.name === "left") { S.settingsMode = "browse"; S.settingsListCursor = 0; S.settingsNotice = ""; render(); return; }
|
|
3749
|
+
if (key.name === "up" || key.name === "k") { S.settingsListCursor = Math.max(0, (S.settingsListCursor || 0) - 1); render(); return; }
|
|
3750
|
+
if (key.name === "down" || key.name === "j") { S.settingsListCursor = Math.min(Math.max(0, events.length - 1), (S.settingsListCursor || 0) + 1); render(); return; }
|
|
3751
|
+
if (chunk === "e") {
|
|
3752
|
+
const stamp = new Date().toISOString().slice(0, 10);
|
|
3753
|
+
S.settingsPendingDir = path.join(os.homedir(), "Desktop", `egregore-telemetry-${S.settingsInst.slug}-${stamp}.jsonl`);
|
|
3754
|
+
S.settingsAction = "tele-export";
|
|
3755
|
+
S.settingsMode = "confirm";
|
|
3756
|
+
S.settingsInput = `Export ${events.length} local event(s) to ${S.settingsPendingDir}? [y/N]`;
|
|
3757
|
+
render(); return;
|
|
3758
|
+
}
|
|
3759
|
+
if (chunk === "s") {
|
|
3760
|
+
const r = runTelemetry(S.settingsInst, ["share"]);
|
|
3761
|
+
const shareLines = ((r && (r.stdout || r.stderr)) || "share preview unavailable").split("\n").filter(Boolean);
|
|
3762
|
+
S.settingsData = { ...(S.settingsData || {}), shareLines };
|
|
3763
|
+
S.settingsMode = "shareinfo"; S.settingsNotice = "";
|
|
3764
|
+
render(); return;
|
|
3765
|
+
}
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
if (S.settingsMode === "shareinfo") {
|
|
3769
|
+
if (key.name === "escape" || key.name === "left") { S.settingsMode = "events"; render(); return; }
|
|
3770
|
+
return;
|
|
3771
|
+
}
|
|
3772
|
+
if (S.settingsMode === "pickdir") {
|
|
3773
|
+
const pick = S.settingsData.dirPick;
|
|
3774
|
+
const reload = () => { pick.entries = listSubdirectories(pick.dir, pick.hidden); pick.cursor = Math.min(pick.cursor, Math.max(0, pick.entries.length - 1)); };
|
|
3775
|
+
if (key.name === "escape") { S.settingsMode = "browse"; S.settingsNotice = ""; render(); return; }
|
|
3776
|
+
if (key.name === "up" || key.name === "k") { pick.cursor = Math.max(0, pick.cursor - 1); render(); return; }
|
|
3777
|
+
if (key.name === "down" || key.name === "j") { pick.cursor = Math.min(Math.max(0, pick.entries.length - 1), pick.cursor + 1); render(); return; }
|
|
3778
|
+
if (key.name === "right" || key.name === "return") {
|
|
3779
|
+
if (pick.entries.length) { pick.dir = path.join(pick.dir, pick.entries[pick.cursor]); pick.cursor = 0; reload(); }
|
|
3780
|
+
render(); return;
|
|
3781
|
+
}
|
|
3782
|
+
if (key.name === "left") {
|
|
3783
|
+
const parent = path.dirname(pick.dir);
|
|
3784
|
+
if (parent !== pick.dir) { pick.dir = parent; pick.cursor = 0; reload(); }
|
|
3785
|
+
render(); return;
|
|
3786
|
+
}
|
|
3787
|
+
if (chunk === ".") { pick.hidden = !pick.hidden; reload(); render(); return; }
|
|
3788
|
+
if (chunk === " ") {
|
|
3789
|
+
S.settingsPendingDir = pick.dir;
|
|
3790
|
+
S.settingsAction = "add";
|
|
3791
|
+
S.settingsMode = "confirm";
|
|
3792
|
+
S.settingsInput = `Allow reading ${pick.dir} for this member? [y/N]`;
|
|
3793
|
+
render(); return;
|
|
3794
|
+
}
|
|
3795
|
+
return;
|
|
3796
|
+
}
|
|
3797
|
+
if (S.settingsMode === "pickroot") {
|
|
3798
|
+
const roots = (S.settingsData.privacySnapshot && S.settingsData.privacySnapshot.boundary && S.settingsData.privacySnapshot.boundary.personal_read_roots) || [];
|
|
3799
|
+
if (key.name === "escape" || key.name === "left") { S.settingsMode = "browse"; S.settingsListCursor = 0; render(); return; }
|
|
3800
|
+
if (key.name === "up" || key.name === "k") { S.settingsListCursor = Math.max(0, (S.settingsListCursor || 0) - 1); render(); return; }
|
|
3801
|
+
if (key.name === "down" || key.name === "j") { S.settingsListCursor = Math.min(Math.max(0, roots.length - 1), (S.settingsListCursor || 0) + 1); render(); return; }
|
|
3802
|
+
if (key.name === "return" && roots.length) {
|
|
3803
|
+
S.settingsPendingDir = roots[Math.min(S.settingsListCursor || 0, roots.length - 1)];
|
|
3804
|
+
S.settingsAction = "remove";
|
|
3805
|
+
S.settingsMode = "confirm";
|
|
3806
|
+
S.settingsInput = `Stop allowing reads of ${S.settingsPendingDir}? [y/N]`;
|
|
3807
|
+
render(); return;
|
|
3808
|
+
}
|
|
3809
|
+
return;
|
|
3810
|
+
}
|
|
3811
|
+
if (S.settingsMode === "confirm") {
|
|
3812
|
+
if (chunk === "y" || chunk === "Y") {
|
|
3813
|
+
let r = null;
|
|
3814
|
+
if (S.settingsAction === "add" || S.settingsAction === "remove") {
|
|
3815
|
+
r = runSettings(S.settingsInst, ["boundary", S.settingsAction, S.settingsPendingDir]);
|
|
3816
|
+
} else if (S.settingsAction === "tele-export") {
|
|
3817
|
+
r = runTelemetry(S.settingsInst, ["export", S.settingsPendingDir]);
|
|
3818
|
+
} else if (S.settingsAction === "tele-on") {
|
|
3819
|
+
r = runTelemetry(S.settingsInst, ["on"]);
|
|
3820
|
+
} else if (S.settingsAction === "tele-off") {
|
|
3821
|
+
r = runTelemetry(S.settingsInst, ["off"]);
|
|
3822
|
+
} else if (S.settingsAction === "tele-clear") {
|
|
3823
|
+
r = runTelemetry(S.settingsInst, ["clear"]);
|
|
3824
|
+
}
|
|
3825
|
+
S.settingsNotice = r && r.status === 0
|
|
3826
|
+
? `${GREEN}done${RESET}`
|
|
3827
|
+
: `${YELLOW}${((r && (r.stderr || r.stdout)) || "action failed").split("\n")[0]}${RESET}`;
|
|
3828
|
+
S.settingsMode = "browse"; S.settingsInput = ""; S.settingsPendingDir = "";
|
|
3829
|
+
refreshPanel(); render(); return;
|
|
3830
|
+
}
|
|
3831
|
+
S.settingsMode = "browse"; S.settingsInput = ""; S.settingsPendingDir = ""; S.settingsNotice = ""; render(); return;
|
|
3832
|
+
}
|
|
3833
|
+
if (key.name === "escape" || key.name === "left") { backToMenu(); return; }
|
|
3834
|
+
if (S.settingsView === "privacy") {
|
|
3835
|
+
const locked = !!(S.settingsData && S.settingsData.privacySnapshot && S.settingsData.privacySnapshot.boundary && S.settingsData.privacySnapshot.boundary.locked);
|
|
3836
|
+
if (!locked && chunk === "a") {
|
|
3837
|
+
const dir = os.homedir();
|
|
3838
|
+
S.settingsData = { ...(S.settingsData || {}), dirPick: { dir, entries: listSubdirectories(dir, false), cursor: 0, hidden: false } };
|
|
3839
|
+
S.settingsMode = "pickdir"; S.settingsNotice = ""; render(); return;
|
|
3840
|
+
}
|
|
3841
|
+
if (!locked && chunk === "r") {
|
|
3842
|
+
S.settingsMode = "pickroot"; S.settingsListCursor = 0; S.settingsNotice = ""; render(); return;
|
|
3843
|
+
}
|
|
3844
|
+
return;
|
|
3845
|
+
}
|
|
3846
|
+
// telemetry view
|
|
3847
|
+
if (chunk === "i") {
|
|
3848
|
+
S.settingsData = { ...(S.settingsData || {}), telemetryEvents: telemetryEvents(S.settingsInst, 100) };
|
|
3849
|
+
S.settingsMode = "events"; S.settingsListCursor = 0; S.settingsNotice = ""; render(); return;
|
|
3850
|
+
}
|
|
3851
|
+
if (chunk === "t") {
|
|
3852
|
+
const on = !!(S.settingsData && S.settingsData.telemetrySnapshot && S.settingsData.telemetrySnapshot.enabled);
|
|
3853
|
+
S.settingsAction = on ? "tele-off" : "tele-on";
|
|
3854
|
+
S.settingsMode = "confirm";
|
|
3855
|
+
S.settingsInput = `Turn telemetry ${on ? "off" : "on"} for this member only? [y/N]`;
|
|
3856
|
+
render(); return;
|
|
3857
|
+
}
|
|
3858
|
+
if (chunk === "x") {
|
|
3859
|
+
const count = (S.settingsData && S.settingsData.telemetrySnapshot && S.settingsData.telemetrySnapshot.buffered_events) || 0;
|
|
3860
|
+
S.settingsAction = "tele-clear";
|
|
3861
|
+
S.settingsMode = "confirm";
|
|
3862
|
+
S.settingsInput = `Delete ${count} locally buffered telemetry event(s)? Nothing else is removed. [y/N]`;
|
|
3863
|
+
render(); return;
|
|
3864
|
+
}
|
|
3865
|
+
return;
|
|
3866
|
+
}
|
|
3867
|
+
|
|
2901
3868
|
if (S.settingsView === "list") {
|
|
2902
3869
|
if (S.settingsMode === "add") {
|
|
2903
3870
|
if (key.name === "escape") { S.settingsMode = "browse"; S.settingsInput = ""; render(); return; }
|
|
@@ -2930,19 +3897,40 @@ async function browser(args = {}) {
|
|
|
2930
3897
|
|
|
2931
3898
|
// menu view
|
|
2932
3899
|
if (key.name === "escape" || key.name === "left") { S.settingsInst = null; S.settingsNotice = ""; render(); return; }
|
|
2933
|
-
if (key.name === "up" || key.name === "k") { S.settingsCursor = (S.settingsCursor - 1 +
|
|
2934
|
-
if (key.name === "down" || key.name === "j") { S.settingsCursor = (S.settingsCursor + 1) %
|
|
3900
|
+
if (key.name === "up" || key.name === "k") { S.settingsCursor = (S.settingsCursor - 1 + 8) % 8; render(); return; }
|
|
3901
|
+
if (key.name === "down" || key.name === "j") { S.settingsCursor = (S.settingsCursor + 1) % 8; render(); return; }
|
|
2935
3902
|
if (key.name === "return" || chunk === " ") {
|
|
2936
3903
|
if (S.settingsCursor === 0) {
|
|
3904
|
+
state.upgradeInst = S.settingsInst;
|
|
3905
|
+
state.upgradeData = S.settingsUpgrade;
|
|
3906
|
+
state.upgradeMode = "view";
|
|
3907
|
+
state.upgradeNotice = "";
|
|
3908
|
+
refreshUpgrade();
|
|
3909
|
+
if (!state.upgradeCandidate) {
|
|
3910
|
+
fetchRuntimeMvpCandidate().then((v) => {
|
|
3911
|
+
state.upgradeCandidate = v || "";
|
|
3912
|
+
if (state.upgradeInst) render();
|
|
3913
|
+
});
|
|
3914
|
+
}
|
|
3915
|
+
render();
|
|
3916
|
+
} else if (S.settingsCursor === 1) {
|
|
3917
|
+
S.settingsView = "privacy"; S.settingsMode = "browse"; S.settingsInput = ""; S.settingsNotice = "";
|
|
3918
|
+
S.settingsData = { ...(S.settingsData || {}), privacySnapshot: privacySnapshot(S.settingsInst) };
|
|
3919
|
+
render();
|
|
3920
|
+
} else if (S.settingsCursor === 2) {
|
|
3921
|
+
S.settingsView = "telemetry"; S.settingsMode = "browse"; S.settingsInput = ""; S.settingsNotice = "";
|
|
3922
|
+
S.settingsData = { ...(S.settingsData || {}), telemetrySnapshot: telemetrySnapshot(S.settingsInst) };
|
|
3923
|
+
render();
|
|
3924
|
+
} else if (S.settingsCursor === 3) {
|
|
2937
3925
|
const on = (S.settingsData && S.settingsData.hosting) !== false;
|
|
2938
3926
|
settingsRunVerb(["hosting", on ? "off" : "on"]);
|
|
2939
3927
|
render();
|
|
2940
|
-
} else if (S.settingsCursor ===
|
|
3928
|
+
} else if (S.settingsCursor === 4) {
|
|
2941
3929
|
const simple = (S.settingsData && S.settingsData.workflow) === "simple";
|
|
2942
3930
|
settingsRunVerb(["workflow", simple ? "staged" : "simple"]);
|
|
2943
3931
|
render();
|
|
2944
3932
|
} else {
|
|
2945
|
-
const domain = S.settingsCursor ===
|
|
3933
|
+
const domain = S.settingsCursor === 5 ? "repo" : S.settingsCursor === 6 ? "admin" : "people";
|
|
2946
3934
|
S.settingsView = "list"; S.settingsDomain = domain;
|
|
2947
3935
|
S.settingsItems = settingsItemsFor(S.settingsData, domain);
|
|
2948
3936
|
S.settingsListCursor = 0; S.settingsMode = "browse"; S.settingsNotice = "";
|
|
@@ -3201,6 +4189,11 @@ async function browser(args = {}) {
|
|
|
3201
4189
|
state.settingsData = settingsDump(pick) || { hosting: true, workflow: "staged", base_branch: "develop", repos: [], admins: [], people: [] };
|
|
3202
4190
|
state.settingsCursor = 0;
|
|
3203
4191
|
state.settingsView = "menu";
|
|
4192
|
+
state.settingsUpgrade = undefined;
|
|
4193
|
+
upgradeStatusAsync(pick, (st) => {
|
|
4194
|
+
state.settingsUpgrade = st;
|
|
4195
|
+
if (state.settingsInst === pick && !state.upgradeInst) render();
|
|
4196
|
+
});
|
|
3204
4197
|
state.settingsNotice = "";
|
|
3205
4198
|
render();
|
|
3206
4199
|
return;
|
|
@@ -3328,6 +4321,8 @@ function main() {
|
|
|
3328
4321
|
if (cmd === "ls" || cmd === "list") return cmdLs();
|
|
3329
4322
|
if (cmd === "use") return cmdUse(args[1]);
|
|
3330
4323
|
if (cmd === "connect") return cmdConnect(args.slice(1));
|
|
4324
|
+
if (cmd === "telemetry") return cmdTelemetry(args.slice(1));
|
|
4325
|
+
if (cmd === "runtime") return cmdRuntime(args.slice(1));
|
|
3331
4326
|
if (cmd === "/invite" || cmd === "invite") return cmdInvite(args.slice(1));
|
|
3332
4327
|
if (cmd === "settings" || cmd === "config") return cmdSettings(args.slice(1));
|
|
3333
4328
|
if (cmd === "prune") return cmdPruneNonInteractive(args[1] === "--dry-run" || args[1] === "-n");
|
|
@@ -3338,6 +4333,8 @@ function main() {
|
|
|
3338
4333
|
if (cmd.startsWith("-")) die(`unknown flag: ${cmd}\n run: egregore help`);
|
|
3339
4334
|
|
|
3340
4335
|
const registry = readRegistry();
|
|
4336
|
+
const worktree = currentWorktreeInstance(registry);
|
|
4337
|
+
if (!cmd && worktree) return launch(worktree, runtimeOverride);
|
|
3341
4338
|
if (registry.length === 0) {
|
|
3342
4339
|
if (canPrompt()) return setupNewEgregore(runtimeOverride);
|
|
3343
4340
|
die("no egregores installed yet.\n run: npx -y create-egregore@latest");
|