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,356 @@
|
|
|
1
|
+
"""Optional graph projection adapter for the Egregore Runtime.
|
|
2
|
+
|
|
3
|
+
The graph is a disposable projection of canonical Markdown. This module never
|
|
4
|
+
reads graph values back into canonical artifacts and never enables the graph by
|
|
5
|
+
configuration discovery: callers must explicitly request the legacy adapter.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from hashlib import sha256
|
|
12
|
+
import json
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
import re
|
|
15
|
+
import subprocess
|
|
16
|
+
from typing import Callable, Sequence
|
|
17
|
+
|
|
18
|
+
from .contracts import CanonicalArtifact, GraphProjectionHealth
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True, slots=True)
|
|
22
|
+
class CommandResult:
|
|
23
|
+
returncode: int
|
|
24
|
+
stdout: str = ""
|
|
25
|
+
stderr: str = ""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
CommandRunner = Callable[[Sequence[str], Path, int], CommandResult]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _run(command: Sequence[str], cwd: Path, timeout: int) -> CommandResult:
|
|
32
|
+
completed = subprocess.run(
|
|
33
|
+
command,
|
|
34
|
+
cwd=cwd,
|
|
35
|
+
capture_output=True,
|
|
36
|
+
text=True,
|
|
37
|
+
timeout=timeout,
|
|
38
|
+
check=False,
|
|
39
|
+
)
|
|
40
|
+
return CommandResult(completed.returncode, completed.stdout, completed.stderr)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _canonical_inventory(memory_root: Path) -> dict[str, str]:
|
|
44
|
+
if not memory_root.is_dir():
|
|
45
|
+
return {}
|
|
46
|
+
return {
|
|
47
|
+
f"memory/{path.relative_to(memory_root).as_posix()}": sha256(
|
|
48
|
+
path.read_bytes()
|
|
49
|
+
).hexdigest()
|
|
50
|
+
for path in sorted(memory_root.rglob("*.md"))
|
|
51
|
+
if path.is_file()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _projection_inventory(memory_root: Path) -> dict[str, str]:
|
|
56
|
+
"""Inventory only canonical families covered by the legacy projector."""
|
|
57
|
+
|
|
58
|
+
inventory = _canonical_inventory(memory_root)
|
|
59
|
+
projected_prefixes = (
|
|
60
|
+
"memory/handoffs/",
|
|
61
|
+
"memory/wraps/",
|
|
62
|
+
"memory/knowledge/decisions/",
|
|
63
|
+
"memory/knowledge/findings/",
|
|
64
|
+
"memory/knowledge/patterns/",
|
|
65
|
+
"memory/knowledge/research/",
|
|
66
|
+
"memory/artifacts/",
|
|
67
|
+
"memory/quests/",
|
|
68
|
+
)
|
|
69
|
+
return {
|
|
70
|
+
path: digest
|
|
71
|
+
for path, digest in inventory.items()
|
|
72
|
+
if path.startswith(projected_prefixes)
|
|
73
|
+
and Path(path).name not in {"index.md", "index.md.bak"}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _snapshot_revision(inventory: dict[str, str]) -> str:
|
|
78
|
+
payload = json.dumps(inventory, sort_keys=True, separators=(",", ":"))
|
|
79
|
+
return f"snapshot:{sha256(payload.encode()).hexdigest()}"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _canonical_revision(root: Path, memory_root: Path) -> str:
|
|
83
|
+
completed = subprocess.run(
|
|
84
|
+
["git", "-C", str(memory_root), "rev-parse", "HEAD"],
|
|
85
|
+
cwd=root,
|
|
86
|
+
capture_output=True,
|
|
87
|
+
text=True,
|
|
88
|
+
check=False,
|
|
89
|
+
)
|
|
90
|
+
revision = completed.stdout.strip()
|
|
91
|
+
if completed.returncode == 0 and revision:
|
|
92
|
+
status = subprocess.run(
|
|
93
|
+
["git", "-C", str(memory_root), "status", "--porcelain"],
|
|
94
|
+
cwd=root,
|
|
95
|
+
capture_output=True,
|
|
96
|
+
text=True,
|
|
97
|
+
check=False,
|
|
98
|
+
)
|
|
99
|
+
if status.returncode == 0 and status.stdout.strip():
|
|
100
|
+
snapshot = _snapshot_revision(_canonical_inventory(memory_root))
|
|
101
|
+
return f"{revision}+dirty:{snapshot.removeprefix('snapshot:')[:12]}"
|
|
102
|
+
return revision
|
|
103
|
+
return _snapshot_revision(_canonical_inventory(memory_root))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _declared_content_hash(path: Path) -> str | None:
|
|
107
|
+
"""Read a canonical v1 hash without treating arbitrary body text as schema."""
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
text = path.read_text(encoding="utf-8")
|
|
111
|
+
except (OSError, UnicodeDecodeError):
|
|
112
|
+
return None
|
|
113
|
+
if not text.startswith("---\n"):
|
|
114
|
+
return None
|
|
115
|
+
frontmatter = text[4:].split("\n---", 1)[0]
|
|
116
|
+
match = re.search(
|
|
117
|
+
r"(?m)^(?:content_hash|contentHash):\s*['\"]?([a-fA-F0-9]{32,128})['\"]?\s*$",
|
|
118
|
+
frontmatter,
|
|
119
|
+
)
|
|
120
|
+
return match.group(1).lower() if match else None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _canonical_path(raw_path: str, memory_root: Path) -> str | None:
|
|
124
|
+
"""Normalize graph file pointers without allowing paths outside memory/."""
|
|
125
|
+
|
|
126
|
+
value = raw_path.strip().replace("\\", "/")
|
|
127
|
+
if not value:
|
|
128
|
+
return None
|
|
129
|
+
resolved_prefix = memory_root.resolve().as_posix().rstrip("/") + "/"
|
|
130
|
+
if value.startswith(resolved_prefix):
|
|
131
|
+
value = "memory/" + value[len(resolved_prefix) :]
|
|
132
|
+
elif Path(value).is_absolute():
|
|
133
|
+
return None
|
|
134
|
+
elif value.startswith("qmd://"):
|
|
135
|
+
parts = value.split("/", 3)
|
|
136
|
+
value = "memory/" + parts[3] if len(parts) == 4 else ""
|
|
137
|
+
elif not value.startswith("memory/"):
|
|
138
|
+
value = "memory/" + value.lstrip("/")
|
|
139
|
+
relative = value.removeprefix("memory/")
|
|
140
|
+
if not relative or ".." in Path(relative).parts:
|
|
141
|
+
return None
|
|
142
|
+
return "memory/" + Path(relative).as_posix()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class DisabledGraphProjection:
|
|
146
|
+
"""Safe default: a complete no-op with explicit health reporting."""
|
|
147
|
+
|
|
148
|
+
def __init__(self, root: Path) -> None:
|
|
149
|
+
self.root = root.resolve()
|
|
150
|
+
self.memory_root = (self.root / "memory").resolve()
|
|
151
|
+
|
|
152
|
+
def health(self) -> GraphProjectionHealth:
|
|
153
|
+
return GraphProjectionHealth(
|
|
154
|
+
enabled=False,
|
|
155
|
+
adapter="disabled",
|
|
156
|
+
projection_revision=None,
|
|
157
|
+
canonical_revision=_canonical_revision(self.root, self.memory_root),
|
|
158
|
+
coverage=None,
|
|
159
|
+
consistent=None,
|
|
160
|
+
warnings=(
|
|
161
|
+
"graph projection is disabled; canonical Markdown is authoritative",
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def project(
|
|
166
|
+
self, artifacts: Sequence[CanonicalArtifact]
|
|
167
|
+
) -> GraphProjectionHealth:
|
|
168
|
+
del artifacts
|
|
169
|
+
return self.health()
|
|
170
|
+
|
|
171
|
+
def rebuild(self) -> GraphProjectionHealth:
|
|
172
|
+
return self.health()
|
|
173
|
+
|
|
174
|
+
def verify(self) -> GraphProjectionHealth:
|
|
175
|
+
return self.health()
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class LegacyGraphProjection:
|
|
179
|
+
"""Explicit compatibility adapter over the preserved graph shell tools.
|
|
180
|
+
|
|
181
|
+
`project` currently delegates to the repository-wide idempotent projector
|
|
182
|
+
because the legacy implementation does not expose an artifact-scoped
|
|
183
|
+
operation. Inputs are nevertheless checked against canonical memory first.
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
_INVENTORY_QUERY = """MATCH (n)
|
|
187
|
+
WHERE n.filePath IS NOT NULL
|
|
188
|
+
RETURN n.filePath AS path,
|
|
189
|
+
coalesce(n.contentHash, '') AS contentHash,
|
|
190
|
+
coalesce(n.canonicalRevision, n.gitRevision, n.commit, '') AS canonicalRevision
|
|
191
|
+
ORDER BY path"""
|
|
192
|
+
|
|
193
|
+
def __init__(
|
|
194
|
+
self,
|
|
195
|
+
root: Path,
|
|
196
|
+
*,
|
|
197
|
+
runner: CommandRunner | None = None,
|
|
198
|
+
timeout: int = 120,
|
|
199
|
+
) -> None:
|
|
200
|
+
self.root = root.resolve()
|
|
201
|
+
self.memory_root = (self.root / "memory").resolve()
|
|
202
|
+
self.runner = runner or _run
|
|
203
|
+
self.timeout = timeout
|
|
204
|
+
|
|
205
|
+
def _base_health(self, *warnings: str) -> GraphProjectionHealth:
|
|
206
|
+
return GraphProjectionHealth(
|
|
207
|
+
enabled=True,
|
|
208
|
+
adapter="legacy-shell-v1",
|
|
209
|
+
projection_revision=None,
|
|
210
|
+
canonical_revision=_canonical_revision(self.root, self.memory_root),
|
|
211
|
+
coverage=None,
|
|
212
|
+
consistent=None,
|
|
213
|
+
warnings=tuple(warnings),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def _inventory(self) -> tuple[dict[str, tuple[str, str]], tuple[str, ...]]:
|
|
217
|
+
result = self.runner(
|
|
218
|
+
["bash", "bin/graph.sh", "query", self._INVENTORY_QUERY],
|
|
219
|
+
self.root,
|
|
220
|
+
self.timeout,
|
|
221
|
+
)
|
|
222
|
+
if result.returncode != 0:
|
|
223
|
+
detail = (result.stderr or result.stdout).strip()
|
|
224
|
+
return {}, (f"graph projection unavailable: {detail or 'query failed'}",)
|
|
225
|
+
try:
|
|
226
|
+
payload = json.loads(result.stdout)
|
|
227
|
+
except json.JSONDecodeError:
|
|
228
|
+
return {}, ("graph projection returned an invalid health response",)
|
|
229
|
+
if "values" not in payload:
|
|
230
|
+
reason = payload.get("reason") or "no projection inventory envelope"
|
|
231
|
+
return {}, (f"graph projection unavailable: {reason}",)
|
|
232
|
+
|
|
233
|
+
entries: dict[str, tuple[str, str]] = {}
|
|
234
|
+
for row in payload.get("values", []):
|
|
235
|
+
if not isinstance(row, list) or not row:
|
|
236
|
+
continue
|
|
237
|
+
path = _canonical_path(str(row[0] or ""), self.memory_root)
|
|
238
|
+
if path is None:
|
|
239
|
+
continue
|
|
240
|
+
content_hash = str(row[1] or "") if len(row) > 1 else ""
|
|
241
|
+
revision = str(row[2] or "") if len(row) > 2 else ""
|
|
242
|
+
entries[path] = (content_hash, revision)
|
|
243
|
+
return entries, ()
|
|
244
|
+
|
|
245
|
+
def health(self) -> GraphProjectionHealth:
|
|
246
|
+
return self.verify()
|
|
247
|
+
|
|
248
|
+
def verify(self) -> GraphProjectionHealth:
|
|
249
|
+
canonical = _projection_inventory(self.memory_root)
|
|
250
|
+
canonical_revision = _canonical_revision(self.root, self.memory_root)
|
|
251
|
+
projected, warnings = self._inventory()
|
|
252
|
+
if warnings:
|
|
253
|
+
return self._base_health(*warnings)
|
|
254
|
+
|
|
255
|
+
canonical_paths = set(canonical)
|
|
256
|
+
projected_paths = set(projected)
|
|
257
|
+
present = canonical_paths & projected_paths
|
|
258
|
+
coverage = len(present) / len(canonical_paths) if canonical_paths else 1.0
|
|
259
|
+
missing = canonical_paths - projected_paths
|
|
260
|
+
extra = projected_paths - canonical_paths
|
|
261
|
+
declared_hashes = {
|
|
262
|
+
path: _declared_content_hash(self.root / path)
|
|
263
|
+
for path in present
|
|
264
|
+
}
|
|
265
|
+
comparable = {
|
|
266
|
+
path
|
|
267
|
+
for path in present
|
|
268
|
+
if projected[path][0] and declared_hashes[path]
|
|
269
|
+
}
|
|
270
|
+
mismatched = {
|
|
271
|
+
path
|
|
272
|
+
for path in comparable
|
|
273
|
+
if projected[path][0].lower() != declared_hashes[path]
|
|
274
|
+
}
|
|
275
|
+
consistent = None if not comparable else not mismatched
|
|
276
|
+
|
|
277
|
+
graph_shape = {
|
|
278
|
+
path: {"content_hash": values[0], "canonical_revision": values[1]}
|
|
279
|
+
for path, values in sorted(projected.items())
|
|
280
|
+
}
|
|
281
|
+
graph_payload = json.dumps(graph_shape, sort_keys=True, separators=(",", ":"))
|
|
282
|
+
projection_revision = f"graph:{sha256(graph_payload.encode()).hexdigest()}"
|
|
283
|
+
|
|
284
|
+
notices = list(warnings)
|
|
285
|
+
if missing:
|
|
286
|
+
notices.append(f"projection missing {len(missing)} canonical artifact(s)")
|
|
287
|
+
if extra:
|
|
288
|
+
notices.append(
|
|
289
|
+
f"projection has {len(extra)} path(s) without canonical artifacts; ignored"
|
|
290
|
+
)
|
|
291
|
+
if mismatched:
|
|
292
|
+
notices.append(
|
|
293
|
+
f"projection disagrees with {len(mismatched)} canonical artifact(s); canonical wins"
|
|
294
|
+
)
|
|
295
|
+
projected_revisions = {
|
|
296
|
+
revision for _, revision in projected.values() if revision
|
|
297
|
+
}
|
|
298
|
+
if projected_revisions and canonical_revision not in projected_revisions:
|
|
299
|
+
notices.append("projection source revision differs from canonical revision")
|
|
300
|
+
|
|
301
|
+
return GraphProjectionHealth(
|
|
302
|
+
enabled=True,
|
|
303
|
+
adapter="legacy-shell-v1",
|
|
304
|
+
projection_revision=projection_revision,
|
|
305
|
+
canonical_revision=canonical_revision,
|
|
306
|
+
coverage=coverage,
|
|
307
|
+
consistent=consistent,
|
|
308
|
+
warnings=tuple(notices),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
def _validate_artifacts(self, artifacts: Sequence[CanonicalArtifact]) -> None:
|
|
312
|
+
for artifact in artifacts:
|
|
313
|
+
relative = artifact.canonical_path.removeprefix("memory/")
|
|
314
|
+
candidate = (self.memory_root / relative).resolve()
|
|
315
|
+
if self.memory_root not in candidate.parents:
|
|
316
|
+
raise ValueError(
|
|
317
|
+
f"artifact {artifact.artifact_id!r} is outside canonical memory"
|
|
318
|
+
)
|
|
319
|
+
if not candidate.is_file():
|
|
320
|
+
raise ValueError(
|
|
321
|
+
f"artifact {artifact.artifact_id!r} has no canonical file"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def project(
|
|
325
|
+
self, artifacts: Sequence[CanonicalArtifact]
|
|
326
|
+
) -> GraphProjectionHealth:
|
|
327
|
+
self._validate_artifacts(artifacts)
|
|
328
|
+
return self._sync("project")
|
|
329
|
+
|
|
330
|
+
def rebuild(self) -> GraphProjectionHealth:
|
|
331
|
+
return self._sync("rebuild")
|
|
332
|
+
|
|
333
|
+
def _sync(self, operation: str) -> GraphProjectionHealth:
|
|
334
|
+
result = self.runner(
|
|
335
|
+
["bash", "bin/sync-graph.sh"], self.root, self.timeout
|
|
336
|
+
)
|
|
337
|
+
if result.returncode != 0:
|
|
338
|
+
detail = (result.stderr or result.stdout).strip()
|
|
339
|
+
return self._base_health(
|
|
340
|
+
f"graph {operation} failed: {detail or 'sync-graph exited nonzero'}",
|
|
341
|
+
"canonical Markdown was preserved and remains authoritative",
|
|
342
|
+
)
|
|
343
|
+
return self.verify()
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def graph_projection(
|
|
347
|
+
root: Path,
|
|
348
|
+
*,
|
|
349
|
+
enabled: bool = False,
|
|
350
|
+
runner: CommandRunner | None = None,
|
|
351
|
+
) -> DisabledGraphProjection | LegacyGraphProjection:
|
|
352
|
+
"""Build the projection adapter; callers must opt in on every construction."""
|
|
353
|
+
|
|
354
|
+
if not enabled:
|
|
355
|
+
return DisabledGraphProjection(root)
|
|
356
|
+
return LegacyGraphProjection(root, runner=runner)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""Deterministic lifecycle lookup for exact handoff questions.
|
|
2
|
+
|
|
3
|
+
QMD answers fuzzy topical recall; this service answers exact
|
|
4
|
+
organizational-state questions — "latest handoff addressed to me", "oldest
|
|
5
|
+
unresolved handoff", "what did I last hand off to X" — as a typed operation
|
|
6
|
+
over canonical artifact metadata. No QMD, no graph, no ranking: iterate the
|
|
7
|
+
canonical handoff repository, filter by stable identity, order by canonical
|
|
8
|
+
creation time with a deterministic tie-breaker.
|
|
9
|
+
|
|
10
|
+
Identity: "me" is the resolved ActorContext. The stable actor id matches
|
|
11
|
+
``created_by``/``to_actor_id`` directly; addressing fields written as
|
|
12
|
+
handles (``to: oz``) resolve through the actor's own alias set or, for a
|
|
13
|
+
named member, through the organization member presentations — addressing
|
|
14
|
+
resolution, never authorization. Authorization stays with the Runtime READ
|
|
15
|
+
decision, and admin-marked handoffs are withheld from non-admins exactly as
|
|
16
|
+
on every other surface.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any, Iterable
|
|
24
|
+
|
|
25
|
+
from .artifacts import split_frontmatter
|
|
26
|
+
from .contracts import ActorContext, Permission
|
|
27
|
+
from .errors import AuthorizationDenied
|
|
28
|
+
from .identity import organization_member_presentations
|
|
29
|
+
from .policy import scope_allows_path
|
|
30
|
+
from .questions import actor_aliases
|
|
31
|
+
|
|
32
|
+
_CLOSED_STATUSES = frozenset(
|
|
33
|
+
{"done", "completed", "closed", "resolved", "superseded", "cancelled", "archived"}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True, slots=True)
|
|
38
|
+
class HandoffRecord:
|
|
39
|
+
canonical_path: str
|
|
40
|
+
topic: str
|
|
41
|
+
sender: str
|
|
42
|
+
recipient: str
|
|
43
|
+
status: str
|
|
44
|
+
occurred_at: str
|
|
45
|
+
claim: str
|
|
46
|
+
ask: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _scalar(fields: Any, *names: str) -> str:
|
|
50
|
+
for name in names:
|
|
51
|
+
value = fields.get(name)
|
|
52
|
+
if value is None:
|
|
53
|
+
continue
|
|
54
|
+
if isinstance(value, list):
|
|
55
|
+
value = ", ".join(str(item) for item in value)
|
|
56
|
+
text = str(value).strip()
|
|
57
|
+
if text:
|
|
58
|
+
return text
|
|
59
|
+
return ""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _occurred_at(fields: Any, path_stem: str) -> str:
|
|
63
|
+
created = _scalar(fields, "created_at")
|
|
64
|
+
if created:
|
|
65
|
+
return created
|
|
66
|
+
date = _scalar(fields, "date")
|
|
67
|
+
if date:
|
|
68
|
+
# A date-only stamp sorts before any same-day ISO timestamp; suffix
|
|
69
|
+
# with the day's start so date-only records order stably among
|
|
70
|
+
# themselves and the path tie-breaker decides within one day.
|
|
71
|
+
return f"{date}T00:00:00Z"
|
|
72
|
+
return f"0000-00-00T00:00:00Z:{path_stem}"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _member_terms(root: Path, actor: ActorContext, name: str) -> frozenset[str]:
|
|
76
|
+
"""Stable-identity terms for a NAMED member (addressing resolution)."""
|
|
77
|
+
|
|
78
|
+
needle = name.strip().removeprefix("@").casefold()
|
|
79
|
+
if not needle:
|
|
80
|
+
return frozenset()
|
|
81
|
+
for member in organization_member_presentations(root, actor):
|
|
82
|
+
values = {
|
|
83
|
+
str(member.display_name).casefold(),
|
|
84
|
+
*(str(alias).casefold() for alias in member.aliases),
|
|
85
|
+
}
|
|
86
|
+
if needle in values:
|
|
87
|
+
return frozenset(values)
|
|
88
|
+
return frozenset({needle})
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _self_terms(actor: ActorContext) -> frozenset[str]:
|
|
92
|
+
return frozenset({actor.actor.actor_id.casefold(), *actor_aliases(actor)})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class HandoffLookupService:
|
|
96
|
+
"""Typed lifecycle lookup over the canonical handoff repository."""
|
|
97
|
+
|
|
98
|
+
def __init__(self, runtime: Any, root: Path):
|
|
99
|
+
self.runtime = runtime
|
|
100
|
+
self.root = Path(root)
|
|
101
|
+
self.memory_root = (self.root / "memory").resolve()
|
|
102
|
+
|
|
103
|
+
def query(
|
|
104
|
+
self,
|
|
105
|
+
actor: ActorContext,
|
|
106
|
+
*,
|
|
107
|
+
addressed_to: str | None = None,
|
|
108
|
+
sent_by: str | None = None,
|
|
109
|
+
status_filter: str = "any",
|
|
110
|
+
order: str = "newest",
|
|
111
|
+
limit: int = 1,
|
|
112
|
+
) -> list[HandoffRecord]:
|
|
113
|
+
decision = self.runtime.authorize(actor, Permission.READ)
|
|
114
|
+
if not decision.allowed:
|
|
115
|
+
raise AuthorizationDenied("; ".join(decision.reasons))
|
|
116
|
+
scopes = tuple(decision.scopes)
|
|
117
|
+
|
|
118
|
+
gate = getattr(self.runtime, "admin_gate", None)
|
|
119
|
+
admin_visible = True
|
|
120
|
+
if gate is not None:
|
|
121
|
+
try:
|
|
122
|
+
admin_visible = bool(gate.actor_is_admin(actor))
|
|
123
|
+
except Exception:
|
|
124
|
+
admin_visible = False
|
|
125
|
+
|
|
126
|
+
recipient_terms = self._terms(actor, addressed_to)
|
|
127
|
+
sender_terms = self._terms(actor, sent_by)
|
|
128
|
+
|
|
129
|
+
records: list[tuple[str, str, HandoffRecord]] = []
|
|
130
|
+
base = self.memory_root / "handoffs"
|
|
131
|
+
if not base.is_dir():
|
|
132
|
+
return []
|
|
133
|
+
for path in base.rglob("*.md"):
|
|
134
|
+
if path.name.startswith("index"):
|
|
135
|
+
continue
|
|
136
|
+
relative = path.relative_to(self.memory_root).as_posix()
|
|
137
|
+
canonical = f"memory/{relative}"
|
|
138
|
+
if not scope_allows_path(canonical, scopes):
|
|
139
|
+
continue
|
|
140
|
+
if not admin_visible and gate is not None and gate.path_is_admin(canonical):
|
|
141
|
+
continue
|
|
142
|
+
try:
|
|
143
|
+
fields, _ = split_frontmatter(path.read_text(encoding="utf-8"))
|
|
144
|
+
except (OSError, ValueError):
|
|
145
|
+
continue
|
|
146
|
+
status = (_scalar(fields, "status") or "active").casefold()
|
|
147
|
+
if status_filter in ("open", "unresolved") and status in _CLOSED_STATUSES:
|
|
148
|
+
continue
|
|
149
|
+
if recipient_terms is not None:
|
|
150
|
+
recipient_actor = _scalar(fields, "to_actor_id").casefold()
|
|
151
|
+
recipient_text = _scalar(fields, "addressed_to", "to").casefold()
|
|
152
|
+
if recipient_actor:
|
|
153
|
+
if recipient_actor not in recipient_terms:
|
|
154
|
+
continue
|
|
155
|
+
elif not self._addressed_match(recipient_text, recipient_terms):
|
|
156
|
+
continue
|
|
157
|
+
if sender_terms is not None:
|
|
158
|
+
sender_actor = _scalar(fields, "created_by").casefold()
|
|
159
|
+
sender_text = _scalar(fields, "from", "author").casefold()
|
|
160
|
+
if sender_actor and sender_actor in sender_terms:
|
|
161
|
+
pass
|
|
162
|
+
elif not self._addressed_match(sender_text, sender_terms):
|
|
163
|
+
continue
|
|
164
|
+
record = HandoffRecord(
|
|
165
|
+
canonical_path=canonical,
|
|
166
|
+
topic=_scalar(fields, "topic", "title") or path.stem,
|
|
167
|
+
sender=_scalar(fields, "from", "author", "created_by") or "unknown",
|
|
168
|
+
recipient=_scalar(fields, "addressed_to", "to") or "unaddressed",
|
|
169
|
+
status=status,
|
|
170
|
+
occurred_at=_occurred_at(fields, path.stem),
|
|
171
|
+
claim=_scalar(fields, "claim"),
|
|
172
|
+
ask=_scalar(fields, "ask"),
|
|
173
|
+
)
|
|
174
|
+
records.append((record.occurred_at, canonical, record))
|
|
175
|
+
|
|
176
|
+
records.sort(key=lambda item: (item[0], item[1]), reverse=(order == "newest"))
|
|
177
|
+
return [record for _, _, record in records[: max(1, limit)]]
|
|
178
|
+
|
|
179
|
+
def _terms(self, actor: ActorContext, who: str | None) -> frozenset[str] | None:
|
|
180
|
+
if who is None:
|
|
181
|
+
return None
|
|
182
|
+
if who.strip().casefold() in ("me", "self", actor.actor.actor_id.casefold()):
|
|
183
|
+
return _self_terms(actor)
|
|
184
|
+
return _member_terms(self.root, actor, who)
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def _addressed_match(text: str, terms: frozenset[str]) -> bool:
|
|
188
|
+
if not text:
|
|
189
|
+
return False
|
|
190
|
+
parts = {
|
|
191
|
+
piece.strip().removeprefix("@").casefold()
|
|
192
|
+
for chunk in text.split(",")
|
|
193
|
+
for piece in chunk.split()
|
|
194
|
+
}
|
|
195
|
+
parts.add(text.strip().casefold())
|
|
196
|
+
return bool(parts & terms)
|