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
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""Look at a folder of documents before asking its owner anything about it.
|
|
2
|
+
|
|
3
|
+
Setting up a knowledge base needs three decisions: what must be kept apart, which
|
|
4
|
+
sources win when two disagree, and what language the documents are written in.
|
|
5
|
+
Asked cold, none of them are answerable. Someone who has just dropped a folder on
|
|
6
|
+
a machine cannot say "what must never mix" — the question is about a model of the
|
|
7
|
+
system, not about their files.
|
|
8
|
+
|
|
9
|
+
So this looks first. It reports the groups the folder already has, the kinds of
|
|
10
|
+
document inside it, and the language it can detect. The questions that follow can
|
|
11
|
+
then name the user's own directories and counts, and be answered yes or no.
|
|
12
|
+
|
|
13
|
+
Everything here is counting and pattern-matching. It proposes; it never decides.
|
|
14
|
+
Where it cannot tell — a language it does not recognise, a folder with no obvious
|
|
15
|
+
grouping — it says so, because a confident wrong grouping is harder to notice
|
|
16
|
+
than an admitted gap.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from collections import Counter
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
# Extensions worth reading. Anything else is counted and reported, not parsed.
|
|
27
|
+
DOCUMENT_SUFFIXES = {".pdf", ".md", ".txt", ".docx", ".doc", ".rtf", ".html", ".htm"}
|
|
28
|
+
CATALOGUE_SUFFIXES = {".csv", ".xlsx", ".xls", ".tsv"}
|
|
29
|
+
|
|
30
|
+
# A group needs enough documents to be worth separating. Below this it is noise —
|
|
31
|
+
# a stray folder, a scratch directory — and offering it as a boundary would ask
|
|
32
|
+
# the user to rule on something that does not matter.
|
|
33
|
+
MIN_GROUP = 5
|
|
34
|
+
|
|
35
|
+
# Short, very common words that are distinctive to one language. Detection here
|
|
36
|
+
# is deliberately crude: it only has to be right often enough to propose, and it
|
|
37
|
+
# reports nothing rather than guessing when the evidence is thin.
|
|
38
|
+
LANGUAGE_MARKERS = {
|
|
39
|
+
"turkish": {"ve", "ile", "için", "olarak", "bir", "bu", "daha", "gibi", "olan"},
|
|
40
|
+
"english": {"the", "and", "for", "with", "that", "this", "from", "are", "which"},
|
|
41
|
+
"german": {"und", "der", "die", "das", "mit", "für", "eine", "nicht", "auch"},
|
|
42
|
+
"french": {"les", "des", "est", "pour", "dans", "une", "sur", "que", "par"},
|
|
43
|
+
"spanish": {"los", "las", "por", "para", "con", "una", "que", "del", "como"},
|
|
44
|
+
"italian": {"che", "per", "con", "una", "del", "sono", "nella", "alla", "dei"},
|
|
45
|
+
}
|
|
46
|
+
WORD = re.compile(r"[^\W\d_]{2,}", re.UNICODE)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Group:
|
|
51
|
+
"""A directory holding enough documents to be worth keeping separate."""
|
|
52
|
+
|
|
53
|
+
name: str
|
|
54
|
+
path: str
|
|
55
|
+
documents: int
|
|
56
|
+
|
|
57
|
+
def as_dict(self) -> dict:
|
|
58
|
+
return {"name": self.name, "path": self.path, "documents": self.documents}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class Survey:
|
|
63
|
+
root: str = ""
|
|
64
|
+
documents: int = 0
|
|
65
|
+
unreadable: int = 0
|
|
66
|
+
groups: list = field(default_factory=list)
|
|
67
|
+
by_suffix: dict = field(default_factory=dict)
|
|
68
|
+
catalogues: list = field(default_factory=list)
|
|
69
|
+
language: str = "unknown"
|
|
70
|
+
language_evidence: dict = field(default_factory=dict)
|
|
71
|
+
language_by_group: dict = field(default_factory=dict)
|
|
72
|
+
sample_titles: list = field(default_factory=list)
|
|
73
|
+
notes: list = field(default_factory=list)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def needs_a_boundary_question(self) -> bool:
|
|
77
|
+
"""Whether separating anything is even plausible.
|
|
78
|
+
|
|
79
|
+
One group means there is nothing to keep apart, so asking would be a
|
|
80
|
+
question with one answer.
|
|
81
|
+
"""
|
|
82
|
+
return len(self.groups) > 1
|
|
83
|
+
|
|
84
|
+
def as_dict(self) -> dict:
|
|
85
|
+
return {
|
|
86
|
+
"root": self.root,
|
|
87
|
+
"documents": self.documents,
|
|
88
|
+
"unreadable": self.unreadable,
|
|
89
|
+
"groups": [g.as_dict() for g in self.groups],
|
|
90
|
+
"by_suffix": self.by_suffix,
|
|
91
|
+
"catalogues": self.catalogues,
|
|
92
|
+
"language": self.language,
|
|
93
|
+
"language_evidence": self.language_evidence,
|
|
94
|
+
"language_by_group": self.language_by_group,
|
|
95
|
+
"sample_titles": self.sample_titles,
|
|
96
|
+
"notes": self.notes,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def detect_language(samples: list) -> tuple:
|
|
101
|
+
"""The language of some text, or that it cannot be told.
|
|
102
|
+
|
|
103
|
+
Returns the name and the per-language hit counts, so a caller can show its
|
|
104
|
+
working rather than assert a result. A near-tie reports unknown: proposing
|
|
105
|
+
the wrong grammar produces a profile that silently finds no advice at all.
|
|
106
|
+
"""
|
|
107
|
+
text = " ".join(samples).lower()
|
|
108
|
+
words = set(WORD.findall(text))
|
|
109
|
+
if len(words) < 20:
|
|
110
|
+
return "unknown", {}
|
|
111
|
+
scores = {lang: len(words & markers) for lang, markers in LANGUAGE_MARKERS.items()}
|
|
112
|
+
ranked = sorted(scores.items(), key=lambda kv: -kv[1])
|
|
113
|
+
best, best_score = ranked[0]
|
|
114
|
+
runner_score = ranked[1][1] if len(ranked) > 1 else 0
|
|
115
|
+
if best_score < 3 or best_score - runner_score < 2:
|
|
116
|
+
return "unknown", scores
|
|
117
|
+
return best, scores
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _read_head(path: Path, limit: int = 4000) -> str:
|
|
121
|
+
"""A little text from a file, for language detection only.
|
|
122
|
+
|
|
123
|
+
PDFs are read too, because a corpus of documents is usually a corpus of
|
|
124
|
+
PDFs. Reading only the plain-text files looks like it works and does not:
|
|
125
|
+
measured on a real 922-document archive, every file but one was a PDF, so
|
|
126
|
+
the language of the whole corpus was decided by a single stray markdown
|
|
127
|
+
file that happened to be lying in it.
|
|
128
|
+
|
|
129
|
+
Only the first page is taken, and a failure is silent — this informs a
|
|
130
|
+
question the user will answer anyway, so it must never be the reason a
|
|
131
|
+
survey fails.
|
|
132
|
+
"""
|
|
133
|
+
suffix = path.suffix.lower()
|
|
134
|
+
try:
|
|
135
|
+
if suffix in {".md", ".txt", ".html", ".htm"}:
|
|
136
|
+
return path.read_text(encoding="utf-8", errors="replace")[:limit]
|
|
137
|
+
if suffix == ".pdf":
|
|
138
|
+
import subprocess
|
|
139
|
+
|
|
140
|
+
out = subprocess.run(
|
|
141
|
+
["pdftotext", "-f", "1", "-l", "1", "-q", str(path), "-"],
|
|
142
|
+
capture_output=True, text=True, timeout=15,
|
|
143
|
+
)
|
|
144
|
+
return (out.stdout or "")[:limit]
|
|
145
|
+
except (OSError, subprocess.SubprocessError, ValueError):
|
|
146
|
+
return ""
|
|
147
|
+
return ""
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def survey(root, max_depth: int = 2, sample_files: int = 40) -> Survey:
|
|
151
|
+
"""What is in this folder, described so its owner can recognise it."""
|
|
152
|
+
root_path = Path(root)
|
|
153
|
+
result = Survey(root=str(root_path))
|
|
154
|
+
if not root_path.is_dir():
|
|
155
|
+
result.notes.append(f"{root_path} is not a folder")
|
|
156
|
+
return result
|
|
157
|
+
|
|
158
|
+
suffixes: Counter = Counter()
|
|
159
|
+
per_group: Counter = Counter()
|
|
160
|
+
group_paths: dict = {}
|
|
161
|
+
samples: list = []
|
|
162
|
+
group_samples: dict = {}
|
|
163
|
+
titles: list = []
|
|
164
|
+
|
|
165
|
+
for path in root_path.rglob("*"):
|
|
166
|
+
if not path.is_file():
|
|
167
|
+
continue
|
|
168
|
+
# Any hidden component, not just a hidden filename. A folder holding
|
|
169
|
+
# documents usually sits beside .git or .egregore, and counting those
|
|
170
|
+
# would report machinery as content.
|
|
171
|
+
if any(part.startswith(".") for part in path.relative_to(root_path).parts):
|
|
172
|
+
continue
|
|
173
|
+
suffix = path.suffix.lower()
|
|
174
|
+
if suffix in CATALOGUE_SUFFIXES:
|
|
175
|
+
result.catalogues.append(path.relative_to(root_path).as_posix())
|
|
176
|
+
continue
|
|
177
|
+
suffixes[suffix or "(no extension)"] += 1
|
|
178
|
+
if suffix not in DOCUMENT_SUFFIXES:
|
|
179
|
+
result.unreadable += 1
|
|
180
|
+
continue
|
|
181
|
+
result.documents += 1
|
|
182
|
+
|
|
183
|
+
relative = path.relative_to(root_path)
|
|
184
|
+
# The group is the outermost directory that is not the root itself. Files
|
|
185
|
+
# sitting loose at the top belong to no group.
|
|
186
|
+
if len(relative.parts) > 1:
|
|
187
|
+
depth = min(max_depth, len(relative.parts) - 1)
|
|
188
|
+
key = "/".join(relative.parts[:depth])
|
|
189
|
+
per_group[key] += 1
|
|
190
|
+
group_paths[key] = key
|
|
191
|
+
|
|
192
|
+
if len(titles) < 8:
|
|
193
|
+
titles.append(relative.as_posix())
|
|
194
|
+
if len(samples) < sample_files:
|
|
195
|
+
head = _read_head(path)
|
|
196
|
+
if head:
|
|
197
|
+
samples.append(head)
|
|
198
|
+
if len(relative.parts) > 1:
|
|
199
|
+
head = _read_head(path, limit=1500)
|
|
200
|
+
if head and len(group_samples.setdefault(key, [])) < 6:
|
|
201
|
+
group_samples[key].append(head)
|
|
202
|
+
|
|
203
|
+
result.by_suffix = dict(sorted(suffixes.items(), key=lambda kv: -kv[1]))
|
|
204
|
+
result.sample_titles = titles
|
|
205
|
+
result.groups = [
|
|
206
|
+
Group(name=key.split("/")[-1], path=group_paths[key], documents=count)
|
|
207
|
+
for key, count in sorted(per_group.items(), key=lambda kv: -kv[1])
|
|
208
|
+
if count >= MIN_GROUP
|
|
209
|
+
]
|
|
210
|
+
result.language, result.language_evidence = detect_language(samples)
|
|
211
|
+
for key, heads in group_samples.items():
|
|
212
|
+
lang, _ = detect_language(heads)
|
|
213
|
+
if lang != "unknown":
|
|
214
|
+
result.language_by_group[key] = lang
|
|
215
|
+
# A corpus in two languages needs two sets of grammar. Reporting the majority
|
|
216
|
+
# language would leave every document in the other one silently unread — and
|
|
217
|
+
# nothing downstream would say why they produced no advice.
|
|
218
|
+
distinct = set(result.language_by_group.values())
|
|
219
|
+
if len(distinct) > 1:
|
|
220
|
+
result.language = "mixed"
|
|
221
|
+
result.notes.append(
|
|
222
|
+
"documents are in more than one language (" + ", ".join(sorted(distinct)) +
|
|
223
|
+
"); each language needs its own grammar, or the others yield no advice")
|
|
224
|
+
|
|
225
|
+
if not result.documents:
|
|
226
|
+
result.notes.append("no readable documents found")
|
|
227
|
+
if result.unreadable:
|
|
228
|
+
result.notes.append(
|
|
229
|
+
f"{result.unreadable} files are not a document type this reads; they are ignored")
|
|
230
|
+
if result.documents and len(result.groups) < 2:
|
|
231
|
+
# Fewer than two groups means there is nothing to hold apart, whether
|
|
232
|
+
# that is because the folder is flat or because only one part of it is
|
|
233
|
+
# substantial.
|
|
234
|
+
result.notes.append(
|
|
235
|
+
"nothing here needs separating; one boundary value will cover everything")
|
|
236
|
+
if result.language == "unknown" and result.documents:
|
|
237
|
+
result.notes.append(
|
|
238
|
+
"could not tell the language from the text available — it must be stated, "
|
|
239
|
+
"because finding advice depends on the grammar of the language")
|
|
240
|
+
if result.catalogues:
|
|
241
|
+
result.notes.append(
|
|
242
|
+
f"found {len(result.catalogues)} spreadsheet(s) that may describe these documents")
|
|
243
|
+
return result
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def boundary_question(result: Survey) -> dict | None:
|
|
247
|
+
"""The separation question, phrased with the owner's own folder names.
|
|
248
|
+
|
|
249
|
+
Returns None when there is nothing to separate, so the caller asks nothing
|
|
250
|
+
rather than asking a question with one possible answer.
|
|
251
|
+
"""
|
|
252
|
+
if not result.needs_a_boundary_question:
|
|
253
|
+
return None
|
|
254
|
+
names = [g.name for g in result.groups[:3]]
|
|
255
|
+
return {
|
|
256
|
+
"found": [g.as_dict() for g in result.groups],
|
|
257
|
+
"question": (
|
|
258
|
+
f"Your folders are {', '.join(names)}. Are these different SUBJECTS, "
|
|
259
|
+
f"or things that must never be mixed?\n\n"
|
|
260
|
+
f"Separating them means a question about {names[0]} can never be answered "
|
|
261
|
+
f"from {names[1]} — not even when that is where the answer is."
|
|
262
|
+
),
|
|
263
|
+
# Together first: most folder structures are subjects, and separating
|
|
264
|
+
# subjects removes real answers. Keeping them apart is the choice that
|
|
265
|
+
# needs a reason, so it is the one stated second.
|
|
266
|
+
"options": [
|
|
267
|
+
{"label": "Subjects — keep them together",
|
|
268
|
+
"effect": "one boundary value for everything",
|
|
269
|
+
"example": "pruning, fertiliser, pests — a question may need any of them"},
|
|
270
|
+
{"label": f"Must not mix — separate {', '.join(names)}",
|
|
271
|
+
"effect": "one boundary value per folder",
|
|
272
|
+
"example": "one client's contract must never answer for another"},
|
|
273
|
+
],
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def trust_question(result: Survey) -> dict | None:
|
|
278
|
+
"""The ranking question, listing what was actually found."""
|
|
279
|
+
if not result.groups:
|
|
280
|
+
return None
|
|
281
|
+
return {
|
|
282
|
+
"found": [g.as_dict() for g in result.groups],
|
|
283
|
+
"question": ("Two of these disagree about the same thing. Which should win?"),
|
|
284
|
+
"options": [{"label": g.name, "documents": g.documents} for g in result.groups[:4]]
|
|
285
|
+
+ [{"label": "Don't know", "effect": "nothing is ranked above anything else"}],
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def summarise(result: Survey) -> str:
|
|
290
|
+
"""The survey as the owner reads it, before any question is asked."""
|
|
291
|
+
lines = [f"{result.documents:,} documents in {result.root}"]
|
|
292
|
+
if result.groups:
|
|
293
|
+
lines.append("")
|
|
294
|
+
lines.append("groups:")
|
|
295
|
+
for g in result.groups[:6]:
|
|
296
|
+
lines.append(f" {g.path:<40} {g.documents:>6,} documents")
|
|
297
|
+
if result.by_suffix:
|
|
298
|
+
kinds = ", ".join(f"{k} {v:,}" for k, v in list(result.by_suffix.items())[:5])
|
|
299
|
+
lines.append("")
|
|
300
|
+
lines.append(f"file types: {kinds}")
|
|
301
|
+
lines.append(f"language: {result.language}")
|
|
302
|
+
for note in result.notes:
|
|
303
|
+
lines.append(f" ! {note}")
|
|
304
|
+
return "\n".join(lines)
|
|
@@ -1,178 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# Usage: bash bin/dashboard-data.sh [username] [time_range]
|
|
4
|
-
# Returns a single JSON object with all query results.
|
|
5
|
-
#
|
|
6
|
-
# time_range: P1D (today), P7D (week, default), P30D (month), P365D (all)
|
|
2
|
+
# One bounded, authorized, canonical Runtime snapshot for the dashboard ritual.
|
|
7
3
|
set -euo pipefail
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
trap "rm -rf $TMPDIR" EXIT
|
|
5
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
6
|
+
TIME_RANGE="${2:-${1:-P7D}}"
|
|
12
7
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
API_KEY=$(grep '^EGREGORE_API_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2- || true)
|
|
16
|
-
ORG=$(jq -r '.org_name // "Egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "Egregore")
|
|
17
|
-
DATE=$(date '+%b %d')
|
|
18
|
-
|
|
19
|
-
# --- Detect user ---
|
|
20
|
-
GH_USER="${1:-}"
|
|
21
|
-
if [ -z "$GH_USER" ]; then
|
|
22
|
-
STATE_FILE="$SCRIPT_DIR/.egregore-state.json"
|
|
23
|
-
if [ -f "$STATE_FILE" ]; then
|
|
24
|
-
GH_USER=$(jq -r '.github_username // empty' "$STATE_FILE" 2>/dev/null)
|
|
25
|
-
fi
|
|
26
|
-
if [ -z "$GH_USER" ]; then
|
|
27
|
-
GH_USER=$(git -C "$SCRIPT_DIR" config user.name 2>/dev/null || echo "unknown")
|
|
28
|
-
fi
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
# --- Time range (default P7D) ---
|
|
32
|
-
TIME_RANGE="${2:-P7D}"
|
|
33
|
-
|
|
34
|
-
# --- Read current session ID (client-side fallback for WAL-not-yet-drained) ---
|
|
35
|
-
PROJ_HASH=$(echo -n "$SCRIPT_DIR" | md5 2>/dev/null || echo -n "$SCRIPT_DIR" | md5sum 2>/dev/null | cut -d' ' -f1)
|
|
36
|
-
SESSION_ID=$(cat "$HOME/.egregore/session-${PROJ_HASH}.id" 2>/dev/null || echo "")
|
|
37
|
-
|
|
38
|
-
# --- Fire API call + git ops in parallel ---
|
|
39
|
-
|
|
40
|
-
# Graph data: single API call (all queries run server-side)
|
|
41
|
-
(
|
|
42
|
-
GRAPH_STATUS="offline"
|
|
43
|
-
GRAPH_REASON=""
|
|
44
|
-
if [ -z "$API_URL" ] || [ -z "$API_KEY" ]; then
|
|
45
|
-
GRAPH_REASON="missing_config"
|
|
46
|
-
else
|
|
47
|
-
# Keep curl's transport status separate from %{http_code}; otherwise a
|
|
48
|
-
# failed request can concatenate 000 + fallback text and look like an
|
|
49
|
-
# unexpected API response.
|
|
50
|
-
CURL_STATUS=0
|
|
51
|
-
HTTP_CODE=$(curl -s -o "$TMPDIR/dashboard_raw.json" -w "%{http_code}" \
|
|
52
|
-
"${API_URL}/api/personal/dashboard?github_username=$(printf '%s' "$GH_USER" | jq -sRr @uri)&time_range=$(printf '%s' "$TIME_RANGE" | jq -sRr @uri)&session_id=$(printf '%s' "$SESSION_ID" | jq -sRr @uri)" \
|
|
53
|
-
-H "Authorization: Bearer $API_KEY" \
|
|
54
|
-
--connect-timeout 5 --max-time 15 2>/dev/null) || CURL_STATUS=$?
|
|
55
|
-
|
|
56
|
-
if [ "$CURL_STATUS" -ne 0 ] || [ "$HTTP_CODE" = "000" ] || ! [[ "$HTTP_CODE" =~ ^[0-9][0-9][0-9]$ ]]; then
|
|
57
|
-
GRAPH_REASON="unreachable"
|
|
58
|
-
elif [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
|
|
59
|
-
GRAPH_REASON="auth_error"
|
|
60
|
-
elif [ "$HTTP_CODE" -ge 500 ] 2>/dev/null; then
|
|
61
|
-
GRAPH_REASON="server_error"
|
|
62
|
-
elif [ -s "$TMPDIR/dashboard_raw.json" ] && jq -e '.me' "$TMPDIR/dashboard_raw.json" >/dev/null 2>&1; then
|
|
63
|
-
cp "$TMPDIR/dashboard_raw.json" "$TMPDIR/dashboard.json"
|
|
64
|
-
GRAPH_STATUS="connected"
|
|
65
|
-
else
|
|
66
|
-
GRAPH_REASON="invalid_response"
|
|
67
|
-
fi
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
# If not connected, write status-only response
|
|
71
|
-
if [ "$GRAPH_STATUS" != "connected" ]; then
|
|
72
|
-
jq -n --arg status "$GRAPH_STATUS" --arg reason "$GRAPH_REASON" \
|
|
73
|
-
'{graph_status: $status, graph_reason: $reason}' > "$TMPDIR/dashboard.json"
|
|
74
|
-
else
|
|
75
|
-
jq --arg status "$GRAPH_STATUS" '. + {graph_status: $status}' \
|
|
76
|
-
"$TMPDIR/dashboard.json" > "$TMPDIR/dashboard_merged.json" \
|
|
77
|
-
&& mv "$TMPDIR/dashboard_merged.json" "$TMPDIR/dashboard.json"
|
|
78
|
-
fi
|
|
79
|
-
) &
|
|
80
|
-
API_PID=$!
|
|
81
|
-
|
|
82
|
-
# Git: branch + dirty status (parallel, stays client-side)
|
|
83
|
-
(
|
|
84
|
-
CURRENT=$(git -C "$SCRIPT_DIR" branch --show-current 2>/dev/null || echo "unknown")
|
|
85
|
-
DIRTY="false"
|
|
86
|
-
if [ -n "$(git -C "$SCRIPT_DIR" status --porcelain 2>/dev/null | head -1)" ]; then
|
|
87
|
-
DIRTY="true"
|
|
88
|
-
fi
|
|
89
|
-
jq -n --arg branch "$CURRENT" --argjson dirty "$DIRTY" \
|
|
90
|
-
'{branch: $branch, dirty: $dirty}' > "$TMPDIR/git.json"
|
|
91
|
-
) &
|
|
92
|
-
GIT_PID=$!
|
|
93
|
-
|
|
94
|
-
# Local sessions: parse memory files when graph is offline (parallel)
|
|
95
|
-
(
|
|
96
|
-
GH_LC=$(echo "$GH_USER" | tr '[:upper:]' '[:lower:]')
|
|
97
|
-
DISPLAY_LC=""
|
|
98
|
-
if [ -f "$SCRIPT_DIR/.egregore-state.json" ]; then
|
|
99
|
-
DISPLAY_LC=$(jq -r '.display_name // empty' "$SCRIPT_DIR/.egregore-state.json" 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Compute cutoff date from time range
|
|
103
|
-
case "$TIME_RANGE" in
|
|
104
|
-
P1D) CUTOFF=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d '1 day ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
105
|
-
P7D) CUTOFF=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
106
|
-
P30D) CUTOFF=$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
107
|
-
P365D) CUTOFF="2000-01-01" ;;
|
|
108
|
-
*) CUTOFF=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
109
|
-
esac
|
|
110
|
-
|
|
111
|
-
# Scan sessions, wraps, and handoffs for this user
|
|
112
|
-
for DIR in "$SCRIPT_DIR/memory/sessions" "$SCRIPT_DIR/memory/wraps" "$SCRIPT_DIR/memory/handoffs"; do
|
|
113
|
-
[ -d "$DIR" ] || continue
|
|
114
|
-
TYPE=$(basename "$DIR")
|
|
115
|
-
find -L "$DIR" -name '*.md' -not -name 'index*' -type f 2>/dev/null | xargs ls -t 2>/dev/null | head -20 | while read -r MFILE; do
|
|
116
|
-
[ -z "$MFILE" ] && continue
|
|
117
|
-
M_AUTH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Author\*\*:' | sed 's/^\*\*Author\*\*:[[:space:]]*//' || true)
|
|
118
|
-
[ -z "$M_AUTH" ] && continue
|
|
119
|
-
M_AUTH_LC=$(echo "$M_AUTH" | tr '[:upper:]' '[:lower:]')
|
|
120
|
-
# Filter to this user only
|
|
121
|
-
[ "$M_AUTH_LC" != "$GH_LC" ] && { [ -z "$DISPLAY_LC" ] || [ "$M_AUTH_LC" != "$DISPLAY_LC" ]; } && continue
|
|
122
|
-
M_DATE=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Date\*\*:' | sed 's/^\*\*Date\*\*:[[:space:]]*//' || true)
|
|
123
|
-
M_DAY="${M_DATE%%T*}"
|
|
124
|
-
[ -n "$M_DAY" ] && [ "$M_DAY" \< "$CUTOFF" ] && continue
|
|
125
|
-
M_BRANCH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Branch\*\*:' | sed 's/^\*\*Branch\*\*:[[:space:]]*//' || true)
|
|
126
|
-
M_DURATION=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Duration\*\*:' | sed 's/^\*\*Duration\*\*:[[:space:]]*//' || true)
|
|
127
|
-
M_TOPIC=$(head -3 "$MFILE" 2>/dev/null | grep -m1 '^# ' | sed 's/^# [^:]*:[[:space:]]*//' || true)
|
|
128
|
-
echo "${M_DATE}|${M_TOPIC}|${M_BRANCH}|${M_DURATION}|${TYPE}"
|
|
129
|
-
done
|
|
130
|
-
done | jq -Rn '
|
|
131
|
-
[inputs | split("|") |
|
|
132
|
-
{date: .[0], topic: .[1], branch: .[2], duration: .[3], type: .[4]}
|
|
133
|
-
] | sort_by(.date) | reverse | {
|
|
134
|
-
sessions: .,
|
|
135
|
-
session_count: length
|
|
136
|
-
}
|
|
137
|
-
' 2>/dev/null > "$TMPDIR/local_sessions.json" || echo '{"sessions":[],"session_count":0}' > "$TMPDIR/local_sessions.json"
|
|
138
|
-
) &
|
|
139
|
-
LOCAL_PID=$!
|
|
140
|
-
|
|
141
|
-
# --- Wait for all ---
|
|
142
|
-
wait $API_PID $GIT_PID $LOCAL_PID 2>/dev/null || true
|
|
143
|
-
|
|
144
|
-
# --- Read results ---
|
|
145
|
-
GIT_INFO=$(cat "$TMPDIR/git.json" 2>/dev/null || echo '{"branch":"unknown","dirty":false}')
|
|
146
|
-
BRANCH=$(echo "$GIT_INFO" | jq -r '.branch' 2>/dev/null || echo "unknown")
|
|
147
|
-
LOCAL_SESSIONS=$(cat "$TMPDIR/local_sessions.json" 2>/dev/null || echo '{"sessions":[],"session_count":0}')
|
|
148
|
-
echo "$LOCAL_SESSIONS" | jq . >/dev/null 2>&1 || LOCAL_SESSIONS='{"sessions":[],"session_count":0}'
|
|
149
|
-
|
|
150
|
-
# --- Client-side current session fallback ---
|
|
151
|
-
# If the graph returned no current_session (WAL hasn't drained yet),
|
|
152
|
-
# inject one from the local session ID file so the TUI always renders it.
|
|
153
|
-
DASHBOARD=$(cat "$TMPDIR/dashboard.json" 2>/dev/null || echo '{"graph_status":"offline"}')
|
|
154
|
-
CS_ID=$(echo "$DASHBOARD" | jq -r '.current_session.id // empty' 2>/dev/null)
|
|
155
|
-
if [ -z "$CS_ID" ] && [ -n "$SESSION_ID" ]; then
|
|
156
|
-
DASHBOARD=$(echo "$DASHBOARD" | jq \
|
|
157
|
-
--arg sid "$SESSION_ID" \
|
|
158
|
-
--arg branch "$BRANCH" \
|
|
159
|
-
'.current_session = {id: $sid, status: "active", topic: null, branch: $branch}' 2>/dev/null || echo "$DASHBOARD")
|
|
160
|
-
fi
|
|
161
|
-
|
|
162
|
-
# --- Derive time range label ---
|
|
8
|
+
# Keep the historical `[username] [range]` shape without treating a provider
|
|
9
|
+
# alias as identity. A recognized range in argv[1] is the new compact form.
|
|
163
10
|
case "$TIME_RANGE" in
|
|
164
|
-
P1D)
|
|
165
|
-
|
|
166
|
-
P30D) RANGE_LABEL="last 30 days" ;;
|
|
167
|
-
P365D) RANGE_LABEL="all time" ;;
|
|
168
|
-
*) RANGE_LABEL="last 7 days" ;;
|
|
11
|
+
P1D|P7D|P30D|P365D) ;;
|
|
12
|
+
*) TIME_RANGE="P7D" ;;
|
|
169
13
|
esac
|
|
170
14
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
--arg range_label "$RANGE_LABEL" \
|
|
176
|
-
--argjson git "$GIT_INFO" \
|
|
177
|
-
--argjson local_sessions "$LOCAL_SESSIONS" \
|
|
178
|
-
'. + {org: $org, date: $date, range_label: $range_label, git: $git, local_sessions: $local_sessions}'
|
|
15
|
+
ARGS=(dashboard --time-range "$TIME_RANGE")
|
|
16
|
+
[ "${EGREGORE_STATUS_CONNECTED_ENRICH:-0}" = "1" ] && ARGS+=(--connected-enrichment)
|
|
17
|
+
EGREGORE_ROOT="$ROOT" PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
18
|
+
exec python3 -m egregore_runtime.status_cli "${ARGS[@]}"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
+
|
|
6
|
+
# Default: official Egregore GitHub App (Device Flow — Client ID is public by design)
|
|
7
|
+
# Override per-org via github_app_client_id in egregore.json
|
|
8
|
+
CLIENT_ID="Iv23li2obNsAjakoK2RE"
|
|
9
|
+
if [ -f "$SCRIPT_DIR/egregore.json" ]; then
|
|
10
|
+
_CUSTOM_ID=$(jq -r '.github_app_client_id // .github_oauth_client_id // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null || true)
|
|
11
|
+
[ -n "$_CUSTOM_ID" ] && CLIENT_ID="$_CUSTOM_ID"
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
SCOPE="" # GitHub App — permissions managed via installation, not OAuth scope
|
|
15
|
+
TIMEOUT=300
|
|
16
|
+
ENV_FILE="$SCRIPT_DIR/.env"
|
|
17
|
+
|
|
18
|
+
# Request device code
|
|
19
|
+
response=$(curl -s -X POST "https://github.com/login/device/code" \
|
|
20
|
+
-H "Accept: application/json" \
|
|
21
|
+
-d "client_id=$CLIENT_ID&scope=$SCOPE")
|
|
22
|
+
|
|
23
|
+
device_code=$(echo "$response" | jq -r '.device_code')
|
|
24
|
+
user_code=$(echo "$response" | jq -r '.user_code')
|
|
25
|
+
verification_uri=$(echo "$response" | jq -r '.verification_uri')
|
|
26
|
+
verification_uri_complete=$(echo "$response" | jq -r '.verification_uri_complete // empty')
|
|
27
|
+
interval=$(echo "$response" | jq -r '.interval')
|
|
28
|
+
|
|
29
|
+
if [ "$device_code" = "null" ] || [ -z "$device_code" ]; then
|
|
30
|
+
echo "Failed to get device code from GitHub."
|
|
31
|
+
echo "$response" | jq . 2>/dev/null || echo "$response"
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Copy code to clipboard
|
|
36
|
+
if command -v pbcopy >/dev/null 2>&1; then
|
|
37
|
+
printf '%s' "$user_code" | pbcopy
|
|
38
|
+
echo ""
|
|
39
|
+
echo " Code copied to clipboard: $user_code"
|
|
40
|
+
echo " Opening your browser — just paste and hit Continue."
|
|
41
|
+
echo ""
|
|
42
|
+
elif command -v xclip >/dev/null 2>&1; then
|
|
43
|
+
printf '%s' "$user_code" | xclip -selection clipboard
|
|
44
|
+
echo ""
|
|
45
|
+
echo " Code copied to clipboard: $user_code"
|
|
46
|
+
echo " Opening your browser — just paste and hit Continue."
|
|
47
|
+
echo ""
|
|
48
|
+
else
|
|
49
|
+
echo ""
|
|
50
|
+
echo " Your code: $user_code"
|
|
51
|
+
echo " Opening your browser — enter the code above."
|
|
52
|
+
echo ""
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Open browser — use verification_uri_complete if available, otherwise plain URI
|
|
56
|
+
url="${verification_uri_complete:-$verification_uri}"
|
|
57
|
+
echo " Opening your browser..."
|
|
58
|
+
echo " If it doesn't open, visit: $url"
|
|
59
|
+
echo ""
|
|
60
|
+
if command -v open >/dev/null 2>&1; then
|
|
61
|
+
open "$url"
|
|
62
|
+
elif command -v xdg-open >/dev/null 2>&1; then
|
|
63
|
+
xdg-open "$url"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Poll for authorization
|
|
67
|
+
elapsed=0
|
|
68
|
+
while [ "$elapsed" -lt "$TIMEOUT" ]; do
|
|
69
|
+
sleep "$interval"
|
|
70
|
+
elapsed=$((elapsed + interval))
|
|
71
|
+
|
|
72
|
+
token_response=$(curl -s -X POST "https://github.com/login/oauth/access_token" \
|
|
73
|
+
-H "Accept: application/json" \
|
|
74
|
+
-d "client_id=$CLIENT_ID&device_code=$device_code&grant_type=urn:ietf:params:oauth:grant-type:device_code")
|
|
75
|
+
|
|
76
|
+
error=$(echo "$token_response" | jq -r '.error // empty')
|
|
77
|
+
access_token=$(echo "$token_response" | jq -r '.access_token // empty')
|
|
78
|
+
|
|
79
|
+
if [ -n "$access_token" ]; then
|
|
80
|
+
# Write token to .env
|
|
81
|
+
if [ -f "$ENV_FILE" ] && grep -q '^GITHUB_TOKEN=' "$ENV_FILE"; then
|
|
82
|
+
# Replace existing token (portable: write to temp file, then move)
|
|
83
|
+
tmp="$ENV_FILE.tmp.$$"
|
|
84
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
85
|
+
case "$line" in
|
|
86
|
+
GITHUB_TOKEN=*) echo "GITHUB_TOKEN=$access_token" ;;
|
|
87
|
+
*) echo "$line" ;;
|
|
88
|
+
esac
|
|
89
|
+
done < "$ENV_FILE" > "$tmp"
|
|
90
|
+
mv "$tmp" "$ENV_FILE"
|
|
91
|
+
else
|
|
92
|
+
echo "GITHUB_TOKEN=$access_token" >> "$ENV_FILE"
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Configure git credential helper (local to this repo, not global)
|
|
96
|
+
git config credential.helper store
|
|
97
|
+
# Write credential for github.com
|
|
98
|
+
protocol_line="protocol=https
|
|
99
|
+
host=github.com
|
|
100
|
+
username=x-access-token
|
|
101
|
+
password=$access_token
|
|
102
|
+
"
|
|
103
|
+
echo "$protocol_line" | git credential-store store 2>/dev/null || true
|
|
104
|
+
|
|
105
|
+
echo " Authorized!"
|
|
106
|
+
exit 0
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
case "$error" in
|
|
110
|
+
authorization_pending) continue ;;
|
|
111
|
+
slow_down) interval=$((interval + 5)) ;;
|
|
112
|
+
*)
|
|
113
|
+
echo " Authorization failed: $error"
|
|
114
|
+
echo "$token_response" | jq -r '.error_description // empty'
|
|
115
|
+
exit 1
|
|
116
|
+
;;
|
|
117
|
+
esac
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
echo " Timed out waiting for authorization (${TIMEOUT}s)."
|
|
121
|
+
exit 1
|
|
@@ -17,6 +17,13 @@ if [ ! -f "$CONFIG" ]; then
|
|
|
17
17
|
exit 1
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
|
+
# shellcheck source=bin/lib/config.sh
|
|
21
|
+
source "$SCRIPT_DIR/bin/lib/config.sh"
|
|
22
|
+
if ! _graph_projection_enabled; then
|
|
23
|
+
echo '{"results":[],"status":"disabled","reason":"graph_projection_disabled"}'
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
20
27
|
# --- Local mode gate: bail immediately ---
|
|
21
28
|
_MODE=$(jq -r '.mode // "connected"' "$CONFIG" 2>/dev/null)
|
|
22
29
|
if [ "$_MODE" = "local" ]; then
|
|
@@ -70,6 +70,10 @@ fi
|
|
|
70
70
|
|
|
71
71
|
GS="$SCRIPT_DIR/bin/graph.sh"
|
|
72
72
|
|
|
73
|
+
# Named reads are explicit projection requests by definition — they pass the
|
|
74
|
+
# Runtime cutover gate that silences background graph callers.
|
|
75
|
+
export EGREGORE_GRAPH_EXPLICIT=1
|
|
76
|
+
|
|
73
77
|
OP="${1:-}"
|
|
74
78
|
shift || true
|
|
75
79
|
|