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,1106 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
# Named graph operations — clean interface over raw Cypher.
|
|
4
|
+
# Keeps implementation details out of the TUI.
|
|
5
|
+
#
|
|
6
|
+
# Usage: bash bin/graph-op.sh <operation> [args...]
|
|
7
|
+
#
|
|
8
|
+
# Operations:
|
|
9
|
+
# mark-read <session-id> [user] Mark a handoff as read
|
|
10
|
+
# mark-done <session-id> [user] Mark a handoff as done/resolved
|
|
11
|
+
# mark-expired <session-id> [user] Explicitly expire an open handoff
|
|
12
|
+
# reopen-handoff <session-id> [user] Reopen a terminal handoff
|
|
13
|
+
# answer-question <set-id> Mark a question set as answered
|
|
14
|
+
# resolve-handoffs <user> Resolve completed explicit implementation lineage
|
|
15
|
+
# set-topic <session-id> <topic> [branch]
|
|
16
|
+
# Set topic (and optionally branch) on a Session node
|
|
17
|
+
# record-focus <session-id> <shown-json> <selected> [dismissed-json]
|
|
18
|
+
# Track Focus option selection for adaptive options
|
|
19
|
+
# merge-person <keep-name> <alias-name>
|
|
20
|
+
# Reconcile two Person nodes — projects relationships
|
|
21
|
+
# to keep-name and retains alias-name append-only
|
|
22
|
+
# create-harvest <id> <topic> <intent> <initiator>
|
|
23
|
+
# Create a Harvest node and link to initiator (WAL-backed)
|
|
24
|
+
# create-harvest-session <harvest-id> <session-id> <person-name> [status]
|
|
25
|
+
# Create a HarvestSession linked to a Harvest and Person.
|
|
26
|
+
# status defaults to 'active' (back-compat). Valid values:
|
|
27
|
+
# pending | active | answered | complete | incorporated.
|
|
28
|
+
# Async respondents should be created with 'pending'.
|
|
29
|
+
# record-harvest-turn <session-id> <turn> <question> <intent> [answer] [eval]
|
|
30
|
+
# Record a question-answer turn in a HarvestSession
|
|
31
|
+
# complete-harvest <harvest-id> <artifact-path>
|
|
32
|
+
# Mark harvest complete and link synthesis artifact
|
|
33
|
+
# catalog List bounded read operations and their contracts
|
|
34
|
+
# open-handoffs <user> [limit] Read non-terminal handoffs addressed to a person
|
|
35
|
+
# pending-questions <user> [limit] Read active question sets awaiting a person
|
|
36
|
+
# lineage <topic> [limit] Trace matching sessions, handoffs, implementations,
|
|
37
|
+
# PRs, and canonical evidence files
|
|
38
|
+
# meeting-history <query> [limit]
|
|
39
|
+
# Find a meeting sequence, participants, derived
|
|
40
|
+
# knowledge, and unprojected canonical meeting files
|
|
41
|
+
|
|
42
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
43
|
+
|
|
44
|
+
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
|
45
|
+
echo "Usage: graph-op.sh <operation> [args...]"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Named graph operations — clean interface over raw Cypher."
|
|
48
|
+
echo ""
|
|
49
|
+
echo "Operations:"
|
|
50
|
+
echo " mark-read <sid> [user] Mark handoff as read"
|
|
51
|
+
echo " mark-done <sid> [user] Mark handoff as done"
|
|
52
|
+
echo " mark-expired <sid> [user] Explicitly expire an open handoff"
|
|
53
|
+
echo " reopen-handoff <sid> [user] Reopen a done/expired handoff"
|
|
54
|
+
echo " answer-question <qid> Mark question set as answered"
|
|
55
|
+
echo " resolve-handoffs <user> Resolve completed implementation lineage"
|
|
56
|
+
echo " set-topic <sid> <topic> Set topic on a Session node"
|
|
57
|
+
echo " merge-person <keep> <alias> Reconcile a Person as a canonical alias"
|
|
58
|
+
echo " claim-handoff <sid> <ho> Link implementing session to handoff"
|
|
59
|
+
echo " create-pr <sid> <num> <repo> <author> [title]"
|
|
60
|
+
echo " register-artifact <id> <url> <title> <type> <author> <topics> <excerpt>"
|
|
61
|
+
echo " create-harvest / complete-harvest / record-harvest-turn"
|
|
62
|
+
echo " catalog List bounded read operation contracts"
|
|
63
|
+
echo " open-handoffs <user> [n] Read recent non-terminal handoffs"
|
|
64
|
+
echo " pending-questions <user> [n] Read recent active question sets"
|
|
65
|
+
echo " lineage <topic> [n] Trace handoff/implementation/PR evidence"
|
|
66
|
+
echo " meeting-history <query> [n] Find meeting continuity and coverage gaps"
|
|
67
|
+
echo " wal-status Show WAL pending count"
|
|
68
|
+
exit 0
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
GS="$SCRIPT_DIR/bin/graph.sh"
|
|
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
|
+
|
|
77
|
+
OP="${1:-}"
|
|
78
|
+
shift || true
|
|
79
|
+
|
|
80
|
+
# --- Local mode gate: bail immediately ---
|
|
81
|
+
_MODE=$(jq -r '.mode // "connected"' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
82
|
+
|
|
83
|
+
# The catalog is static runtime metadata, not a graph read. Keep it available
|
|
84
|
+
# in local mode so every harness can route correctly without opening this file
|
|
85
|
+
# or guessing whether an operation exists.
|
|
86
|
+
if [ "$OP" = "catalog" ]; then
|
|
87
|
+
jq -n --arg mode "$_MODE" '{
|
|
88
|
+
schema: "egregore.graph-operation-catalog/v1",
|
|
89
|
+
definitionVersion: 1,
|
|
90
|
+
mode: $mode,
|
|
91
|
+
operations: [
|
|
92
|
+
{
|
|
93
|
+
name: "open-handoffs",
|
|
94
|
+
intent: "current non-terminal handoffs addressed to a person",
|
|
95
|
+
usage: "bash bin/graph-op.sh open-handoffs <user> [limit]",
|
|
96
|
+
availability: "connected",
|
|
97
|
+
maxResults: 25,
|
|
98
|
+
evidence: "live graph state"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "pending-questions",
|
|
102
|
+
intent: "current active question sets awaiting a person",
|
|
103
|
+
usage: "bash bin/graph-op.sh pending-questions <user> [limit]",
|
|
104
|
+
availability: "connected",
|
|
105
|
+
maxResults: 25,
|
|
106
|
+
evidence: "live graph state"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "lineage",
|
|
110
|
+
intent: "handoff to implementation, branch, PR, and superseding direction",
|
|
111
|
+
usage: "bash bin/graph-op.sh lineage <topic> [limit]",
|
|
112
|
+
availability: "connected",
|
|
113
|
+
maxResults: 15,
|
|
114
|
+
evidence: "graph relationships plus canonical file pointers"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "meeting-history",
|
|
118
|
+
intent: "cross-meeting continuity for a company, person, or topic",
|
|
119
|
+
usage: "bash bin/graph-op.sh meeting-history <query> [limit]",
|
|
120
|
+
availability: "connected",
|
|
121
|
+
maxResults: 15,
|
|
122
|
+
evidence: "projected meeting relationships plus canonical file coverage"
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}'
|
|
126
|
+
exit 0
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
if [ "$_MODE" = "local" ]; then
|
|
130
|
+
echo '{"results":[]}'
|
|
131
|
+
exit 0
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# Return a bounded set of exact canonical paths containing a literal query.
|
|
135
|
+
# This is intentionally a coverage check around graph results, not a second
|
|
136
|
+
# full-text answer corpus: agents still open only the relevant canonical files.
|
|
137
|
+
memory_file_candidates() {
|
|
138
|
+
local query="$1"
|
|
139
|
+
local limit="$2"
|
|
140
|
+
shift 2
|
|
141
|
+
local filename_hits=""
|
|
142
|
+
local content_hits=""
|
|
143
|
+
local hits=""
|
|
144
|
+
|
|
145
|
+
if command -v rg >/dev/null 2>&1; then
|
|
146
|
+
filename_hits="$(
|
|
147
|
+
rg --files --glob '*.md' --glob '!index.md' "$@" 2>/dev/null \
|
|
148
|
+
| sort \
|
|
149
|
+
| while IFS= read -r path; do
|
|
150
|
+
printf '%s' "$path" | grep -Fqi -- "$query" \
|
|
151
|
+
&& printf 'filename\t%s\n' "$path"
|
|
152
|
+
done || true
|
|
153
|
+
)"
|
|
154
|
+
content_hits="$(
|
|
155
|
+
rg -i -l -F --glob '*.md' --glob '!index.md' -- "$query" "$@" 2>/dev/null \
|
|
156
|
+
| sort \
|
|
157
|
+
| while IFS= read -r path; do printf 'content\t%s\n' "$path"; done || true
|
|
158
|
+
)"
|
|
159
|
+
else
|
|
160
|
+
content_hits="$(
|
|
161
|
+
find -L "$@" -type f -name '*.md' -print 2>/dev/null \
|
|
162
|
+
| while IFS= read -r path; do
|
|
163
|
+
[ "$(basename "$path")" = "index.md" ] && continue
|
|
164
|
+
printf '%s' "$path" | grep -Fqi -- "$query" \
|
|
165
|
+
&& printf 'filename\t%s\n' "$path"
|
|
166
|
+
grep -Fqi -- "$query" "$path" 2>/dev/null \
|
|
167
|
+
&& printf 'content\t%s\n' "$path"
|
|
168
|
+
done || true
|
|
169
|
+
)"
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
hits="$(
|
|
173
|
+
printf '%s\n%s\n' "$filename_hits" "$content_hits" \
|
|
174
|
+
| awk -F ' ' 'NF >= 2 && !seen[$2]++' \
|
|
175
|
+
| head -n "$limit"
|
|
176
|
+
)"
|
|
177
|
+
|
|
178
|
+
while IFS=$'\t' read -r match_kind path; do
|
|
179
|
+
[ -n "$path" ] || continue
|
|
180
|
+
case "$path" in
|
|
181
|
+
"$SCRIPT_DIR"/memory/*)
|
|
182
|
+
printf 'memory/%s\t%s\n' "${path#"$SCRIPT_DIR"/memory/}" "$match_kind"
|
|
183
|
+
;;
|
|
184
|
+
esac
|
|
185
|
+
done <<< "$hits" | jq -Rsc '
|
|
186
|
+
split("\n")
|
|
187
|
+
| map(select(length > 0))
|
|
188
|
+
| map(split("\t") | {evidencePath: .[0], matchKind: .[1]})
|
|
189
|
+
'
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# Reduce natural-language read queries to a small set of discriminative terms.
|
|
193
|
+
# Named reads should tolerate "42CAP Moritz partner call" without requiring that
|
|
194
|
+
# exact phrase to exist in a graph property or canonical Markdown file.
|
|
195
|
+
meaningful_query_terms() {
|
|
196
|
+
jq -Rn --arg query "$1" '
|
|
197
|
+
[
|
|
198
|
+
$query
|
|
199
|
+
| ascii_downcase
|
|
200
|
+
| scan("[a-z0-9][a-z0-9._+-]*")
|
|
201
|
+
| select(length >= 3)
|
|
202
|
+
| select(. as $term |
|
|
203
|
+
[
|
|
204
|
+
"about","across","after","before","between","call","calls",
|
|
205
|
+
"company","conversation","evolved","first","from","history",
|
|
206
|
+
"later","meeting","meetings","month","partner","partners",
|
|
207
|
+
"person","the","topic","transcript","transcripts","what","with"
|
|
208
|
+
]
|
|
209
|
+
| index($term) == null
|
|
210
|
+
)
|
|
211
|
+
]
|
|
212
|
+
| unique
|
|
213
|
+
| if length == 0 then [$query | ascii_downcase] else .[0:8] end
|
|
214
|
+
'
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# Build a bounded union of literal coverage checks for each meaningful term.
|
|
218
|
+
# The result remains a list of exact canonical paths, not a second answer corpus.
|
|
219
|
+
memory_file_candidates_for_terms() {
|
|
220
|
+
local terms_json="$1"
|
|
221
|
+
local limit="$2"
|
|
222
|
+
shift 2
|
|
223
|
+
local combined='[]'
|
|
224
|
+
local term=""
|
|
225
|
+
local term_hits=""
|
|
226
|
+
|
|
227
|
+
while IFS= read -r term; do
|
|
228
|
+
[ -n "$term" ] || continue
|
|
229
|
+
term_hits="$(memory_file_candidates "$term" "$limit" "$@")"
|
|
230
|
+
combined="$(
|
|
231
|
+
jq -n \
|
|
232
|
+
--argjson prior "$combined" \
|
|
233
|
+
--argjson next "$term_hits" \
|
|
234
|
+
--argjson limit "$limit" '
|
|
235
|
+
($prior + $next)
|
|
236
|
+
| unique_by(.evidencePath)
|
|
237
|
+
| .[0:$limit]
|
|
238
|
+
'
|
|
239
|
+
)"
|
|
240
|
+
done < <(printf '%s' "$terms_json" | jq -r '.[]')
|
|
241
|
+
|
|
242
|
+
printf '%s\n' "$combined"
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
case "$OP" in
|
|
246
|
+
|
|
247
|
+
mark-read)
|
|
248
|
+
SID="${1:?missing session-id}"
|
|
249
|
+
USER="${2:-}"
|
|
250
|
+
bash "$GS" query "
|
|
251
|
+
MATCH (s:Session {id: \$sid})
|
|
252
|
+
OPTIONAL MATCH (s)-[:HANDED_TO]->(recipient:Person)
|
|
253
|
+
WITH s, collect(DISTINCT recipient) AS recipients
|
|
254
|
+
WHERE (\$user = '' OR any(p IN recipients WHERE
|
|
255
|
+
toLower(p.name) = toLower(\$user)
|
|
256
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)))
|
|
257
|
+
AND coalesce(s.handoffStatus, 'pending') IN ['pending','read']
|
|
258
|
+
SET s.handoffReadDate = coalesce(s.handoffReadDate, date()),
|
|
259
|
+
s.handoffUpdatedAt = datetime(),
|
|
260
|
+
s.handoffLifecycleVersion = 1
|
|
261
|
+
FOREACH (_ IN CASE WHEN s.handoffIntent = 'fyi' THEN [1] ELSE [] END |
|
|
262
|
+
SET s.handoffStatus = 'done',
|
|
263
|
+
s.handoffDoneAt = coalesce(s.handoffDoneAt, datetime()),
|
|
264
|
+
s.handoffLifecycleReason = 'fyi_read')
|
|
265
|
+
FOREACH (_ IN CASE WHEN coalesce(s.handoffIntent, 'unclassified') <> 'fyi' THEN [1] ELSE [] END |
|
|
266
|
+
SET s.handoffStatus = 'read',
|
|
267
|
+
s.handoffLifecycleReason = 'recipient_read')
|
|
268
|
+
RETURN s.id AS id, s.topic AS topic, s.handoffStatus AS status,
|
|
269
|
+
coalesce(s.handoffIntent, 'unclassified') AS intent
|
|
270
|
+
" "$(jq -n --arg sid "$SID" --arg user "$USER" '{sid: $sid,user: $user}')"
|
|
271
|
+
;;
|
|
272
|
+
|
|
273
|
+
mark-done)
|
|
274
|
+
SID="${1:?missing session-id}"
|
|
275
|
+
USER="${2:-}"
|
|
276
|
+
bash "$GS" query "
|
|
277
|
+
MATCH (s:Session {id: \$sid})
|
|
278
|
+
OPTIONAL MATCH (s)-[:HANDED_TO]->(recipient:Person)
|
|
279
|
+
WITH s, collect(DISTINCT recipient) AS recipients
|
|
280
|
+
WHERE (\$user = '' OR any(p IN recipients WHERE
|
|
281
|
+
toLower(p.name) = toLower(\$user)
|
|
282
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)))
|
|
283
|
+
AND coalesce(s.handoffStatus, 'pending') IN ['pending','read','claimed']
|
|
284
|
+
SET s.handoffStatus = 'done',
|
|
285
|
+
s.handoffDoneAt = datetime(),
|
|
286
|
+
s.handoffUpdatedAt = datetime(),
|
|
287
|
+
s.handoffLifecycleReason = 'explicit_done',
|
|
288
|
+
s.handoffLifecycleVersion = 1
|
|
289
|
+
RETURN s.id AS id, s.topic AS topic, s.handoffStatus AS status
|
|
290
|
+
" "$(jq -n --arg sid "$SID" --arg user "$USER" '{sid: $sid,user: $user}')"
|
|
291
|
+
;;
|
|
292
|
+
|
|
293
|
+
mark-expired)
|
|
294
|
+
SID="${1:?missing session-id}"
|
|
295
|
+
USER="${2:-}"
|
|
296
|
+
bash "$GS" query "
|
|
297
|
+
MATCH (s:Session {id: \$sid})
|
|
298
|
+
OPTIONAL MATCH (s)-[:HANDED_TO]->(recipient:Person)
|
|
299
|
+
WITH s, collect(DISTINCT recipient) AS recipients
|
|
300
|
+
WHERE (\$user = '' OR any(p IN recipients WHERE
|
|
301
|
+
toLower(p.name) = toLower(\$user)
|
|
302
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)))
|
|
303
|
+
AND coalesce(s.handoffStatus, 'pending') IN ['pending','read','claimed']
|
|
304
|
+
SET s.handoffStatus = 'expired',
|
|
305
|
+
s.handoffExpiredAt = datetime(),
|
|
306
|
+
s.handoffUpdatedAt = datetime(),
|
|
307
|
+
s.handoffLifecycleReason = 'explicit_expired',
|
|
308
|
+
s.handoffLifecycleVersion = 1
|
|
309
|
+
RETURN s.id AS id, s.topic AS topic, s.handoffStatus AS status
|
|
310
|
+
" "$(jq -n --arg sid "$SID" --arg user "$USER" '{sid: $sid,user: $user}')"
|
|
311
|
+
;;
|
|
312
|
+
|
|
313
|
+
reopen-handoff)
|
|
314
|
+
SID="${1:?missing session-id}"
|
|
315
|
+
USER="${2:-}"
|
|
316
|
+
bash "$GS" query "
|
|
317
|
+
MATCH (s:Session {id: \$sid})
|
|
318
|
+
OPTIONAL MATCH (s)-[:HANDED_TO]->(recipient:Person)
|
|
319
|
+
WITH s, collect(DISTINCT recipient) AS recipients
|
|
320
|
+
WHERE (\$user = '' OR any(p IN recipients WHERE
|
|
321
|
+
toLower(p.name) = toLower(\$user)
|
|
322
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)))
|
|
323
|
+
AND s.handoffStatus IN ['done','expired','completed']
|
|
324
|
+
SET s.handoffLastDoneAt = s.handoffDoneAt,
|
|
325
|
+
s.handoffLastExpiredAt = s.handoffExpiredAt,
|
|
326
|
+
s.handoffDoneAt = null,
|
|
327
|
+
s.handoffExpiredAt = null,
|
|
328
|
+
s.handoffStatus = 'pending',
|
|
329
|
+
s.handoffReopenedAt = datetime(),
|
|
330
|
+
s.handoffUpdatedAt = datetime(),
|
|
331
|
+
s.handoffLifecycleReason = 'explicit_reopened',
|
|
332
|
+
s.handoffLifecycleVersion = 1
|
|
333
|
+
RETURN s.id AS id, s.topic AS topic, s.handoffStatus AS status
|
|
334
|
+
" "$(jq -n --arg sid "$SID" --arg user "$USER" '{sid: $sid,user: $user}')"
|
|
335
|
+
;;
|
|
336
|
+
|
|
337
|
+
answer-question)
|
|
338
|
+
QID="${1:?missing question-set-id}"
|
|
339
|
+
bash "$GS" query "
|
|
340
|
+
MATCH (qs:QuestionSet {id: \$qid})
|
|
341
|
+
SET qs.status = 'answered'
|
|
342
|
+
RETURN qs.id AS id, qs.topic AS topic
|
|
343
|
+
" "$(jq -n --arg qid "$QID" '{qid: $qid}')"
|
|
344
|
+
;;
|
|
345
|
+
|
|
346
|
+
resolve-handoffs)
|
|
347
|
+
USER="${1:?missing username}"
|
|
348
|
+
bash "$GS" query "
|
|
349
|
+
MATCH (s:Session)-[:HANDED_TO]->(p:Person {name: \$user})
|
|
350
|
+
WHERE s.handoffStatus IN ['read','claimed']
|
|
351
|
+
WITH DISTINCT s, p, size([(s)-[:HANDED_TO]->(:Person) | 1]) AS recipientCount
|
|
352
|
+
WHERE recipientCount = 1
|
|
353
|
+
MATCH (implementation:Session)-[:IMPLEMENTS]->(s)
|
|
354
|
+
MATCH (implementation)-[:BY]->(p)
|
|
355
|
+
WHERE implementation.wrappedAt IS NOT NULL
|
|
356
|
+
OR implementation.status IN ['completed','handed_off','wrapped']
|
|
357
|
+
WITH DISTINCT s, implementation
|
|
358
|
+
SET s.handoffStatus = 'done',
|
|
359
|
+
s.handoffDoneAt = coalesce(s.handoffDoneAt, datetime()),
|
|
360
|
+
s.handoffUpdatedAt = datetime(),
|
|
361
|
+
s.handoffLifecycleReason = 'single_recipient_implemented',
|
|
362
|
+
s.handoffLifecycleVersion = 1
|
|
363
|
+
RETURN s.id AS resolved, implementation.id AS implementation
|
|
364
|
+
" "$(jq -n --arg user "$USER" '{user: $user}')"
|
|
365
|
+
;;
|
|
366
|
+
|
|
367
|
+
set-topic)
|
|
368
|
+
SID="${1:?missing session-id}"
|
|
369
|
+
TOPIC="${2:?missing topic}"
|
|
370
|
+
BRANCH="${3:-}"
|
|
371
|
+
if [ -n "$BRANCH" ]; then
|
|
372
|
+
bash "$GS" query "
|
|
373
|
+
MATCH (s:Session {id: \$sid})
|
|
374
|
+
SET s.topic = \$topic, s.branch = \$branch
|
|
375
|
+
RETURN s.id AS id, s.topic AS topic, s.branch AS branch
|
|
376
|
+
" "$(jq -n --arg sid "$SID" --arg topic "$TOPIC" --arg branch "$BRANCH" '{sid: $sid, topic: $topic, branch: $branch}')"
|
|
377
|
+
else
|
|
378
|
+
bash "$GS" query "
|
|
379
|
+
MATCH (s:Session {id: \$sid})
|
|
380
|
+
SET s.topic = \$topic
|
|
381
|
+
RETURN s.id AS id, s.topic AS topic
|
|
382
|
+
" "$(jq -n --arg sid "$SID" --arg topic "$TOPIC" '{sid: $sid, topic: $topic}')"
|
|
383
|
+
fi
|
|
384
|
+
;;
|
|
385
|
+
|
|
386
|
+
record-focus)
|
|
387
|
+
SID="${1:?missing session-id}"
|
|
388
|
+
SHOWN="${2:?missing shown options}"
|
|
389
|
+
SELECTED="${3:?missing selected option}"
|
|
390
|
+
DISMISSED="${4:-[]}"
|
|
391
|
+
bash "$GS" query "
|
|
392
|
+
MATCH (s:Session {id: \$sid})
|
|
393
|
+
SET s.focusShown = \$shown,
|
|
394
|
+
s.focusSelected = \$selected,
|
|
395
|
+
s.focusDismissed = \$dismissed
|
|
396
|
+
RETURN s.id AS id
|
|
397
|
+
" "$(jq -n --arg sid "$SID" --argjson shown "$SHOWN" --arg selected "$SELECTED" --argjson dismissed "$DISMISSED" '{sid: $sid, shown: $shown, selected: $selected, dismissed: $dismissed}')"
|
|
398
|
+
;;
|
|
399
|
+
|
|
400
|
+
merge-person)
|
|
401
|
+
KEEP="${1:?missing keep-name (the Person to keep)}"
|
|
402
|
+
ALIAS="${2:?missing alias-name (the Person to reconcile)}"
|
|
403
|
+
bash "$GS" query "
|
|
404
|
+
MATCH (keep:Person) WHERE (toLower(keep.name) = toLower(\$keep) OR toLower(keep.github) = toLower(\$keep) OR keep.personId = \$keep OR toLower(\$keep) IN [x IN coalesce(keep.githubAliases, []) | toLower(x)] OR toLower(\$keep) IN [x IN coalesce(keep.emails, []) | toLower(x)])
|
|
405
|
+
AND NOT coalesce(keep.kind, '') IN ['external', 'identity_alias']
|
|
406
|
+
AND coalesce(keep.status, 'active') = 'active' AND keep.ingestRef IS NULL
|
|
407
|
+
MATCH (alias:Person) WHERE (toLower(alias.name) = toLower(\$alias) OR toLower(alias.github) = toLower(\$alias) OR alias.personId = \$alias OR toLower(\$alias) IN [x IN coalesce(alias.githubAliases, []) | toLower(x)] OR toLower(\$alias) IN [x IN coalesce(alias.emails, []) | toLower(x)])
|
|
408
|
+
AND NOT coalesce(alias.kind, '') IN ['external', 'identity_alias']
|
|
409
|
+
AND coalesce(alias.status, 'active') = 'active' AND alias.ingestRef IS NULL
|
|
410
|
+
WITH keep, alias WHERE keep <> alias
|
|
411
|
+
AND (
|
|
412
|
+
keep.githubId IS NULL OR alias.githubId IS NULL
|
|
413
|
+
OR toString(keep.githubId) = toString(alias.githubId)
|
|
414
|
+
)
|
|
415
|
+
AND NOT (
|
|
416
|
+
coalesce(keep.personId, '') STARTS WITH 'github:'
|
|
417
|
+
AND coalesce(alias.personId, '') STARTS WITH 'github:'
|
|
418
|
+
AND keep.personId <> alias.personId
|
|
419
|
+
)
|
|
420
|
+
SET keep.previousNames = reduce(
|
|
421
|
+
acc = coalesce(keep.previousNames, []),
|
|
422
|
+
value IN coalesce(alias.previousNames, []) + [alias.name, alias.displayName] |
|
|
423
|
+
CASE WHEN value IS NULL OR toLower(value) = toLower(keep.name) OR value IN acc
|
|
424
|
+
THEN acc ELSE acc + value END
|
|
425
|
+
),
|
|
426
|
+
keep.githubAliases = reduce(
|
|
427
|
+
acc = coalesce(keep.githubAliases, []),
|
|
428
|
+
value IN coalesce(alias.githubAliases, []) + [alias.github] |
|
|
429
|
+
CASE WHEN value IS NULL OR toLower(value) = toLower(keep.github) OR value IN acc
|
|
430
|
+
THEN acc ELSE acc + value END
|
|
431
|
+
),
|
|
432
|
+
keep.emails = reduce(
|
|
433
|
+
acc = coalesce(keep.emails, []),
|
|
434
|
+
value IN coalesce(alias.emails, []) + [alias.email] |
|
|
435
|
+
CASE WHEN value IS NULL OR value IN acc THEN acc ELSE acc + value END
|
|
436
|
+
),
|
|
437
|
+
keep.joined = coalesce(alias.joined, keep.joined),
|
|
438
|
+
keep.invited = coalesce(keep.invited, alias.invited),
|
|
439
|
+
keep.invitedBy = coalesce(keep.invitedBy, alias.invitedBy),
|
|
440
|
+
keep.role = coalesce(keep.role, alias.role),
|
|
441
|
+
keep.domain = coalesce(keep.domain, alias.domain),
|
|
442
|
+
keep.focus = coalesce(keep.focus, alias.focus),
|
|
443
|
+
keep.workStyle = coalesce(keep.workStyle, alias.workStyle),
|
|
444
|
+
keep.telegramId = coalesce(keep.telegramId, alias.telegramId),
|
|
445
|
+
keep.lastBrief = coalesce(keep.lastBrief, alias.lastBrief),
|
|
446
|
+
keep.lastBriefDate = coalesce(keep.lastBriefDate, alias.lastBriefDate),
|
|
447
|
+
keep.lastRecommendations = coalesce(keep.lastRecommendations, alias.lastRecommendations)
|
|
448
|
+
WITH keep, alias
|
|
449
|
+
OPTIONAL MATCH (s1:Session)-[:BY]->(alias)
|
|
450
|
+
FOREACH (_ IN CASE WHEN s1 IS NOT NULL THEN [1] ELSE [] END | MERGE (s1)-[:BY]->(keep))
|
|
451
|
+
WITH keep, alias
|
|
452
|
+
OPTIONAL MATCH (s2:Session)-[:HANDED_TO]->(alias)
|
|
453
|
+
FOREACH (_ IN CASE WHEN s2 IS NOT NULL THEN [1] ELSE [] END | MERGE (s2)-[:HANDED_TO]->(keep))
|
|
454
|
+
WITH keep, alias
|
|
455
|
+
OPTIONAL MATCH (m:Meeting)-[:INVOLVES]->(alias)
|
|
456
|
+
FOREACH (_ IN CASE WHEN m IS NOT NULL THEN [1] ELSE [] END | MERGE (m)-[:INVOLVES]->(keep))
|
|
457
|
+
WITH keep, alias
|
|
458
|
+
OPTIONAL MATCH (a:Artifact)-[:CONTRIBUTED_BY]->(alias)
|
|
459
|
+
FOREACH (_ IN CASE WHEN a IS NOT NULL THEN [1] ELSE [] END | MERGE (a)-[:CONTRIBUTED_BY]->(keep))
|
|
460
|
+
WITH keep, alias
|
|
461
|
+
OPTIONAL MATCH (i:Interview)-[:CONDUCTED_BY]->(alias)
|
|
462
|
+
FOREACH (_ IN CASE WHEN i IS NOT NULL THEN [1] ELSE [] END | MERGE (i)-[:CONDUCTED_BY]->(keep))
|
|
463
|
+
WITH keep, alias
|
|
464
|
+
OPTIONAL MATCH (t:Todo)-[:BY]->(alias)
|
|
465
|
+
FOREACH (_ IN CASE WHEN t IS NOT NULL THEN [1] ELSE [] END | MERGE (t)-[:BY]->(keep))
|
|
466
|
+
WITH keep, alias
|
|
467
|
+
OPTIONAL MATCH (mentionedArtifact:Artifact)-[:MENTIONS]->(alias)
|
|
468
|
+
FOREACH (_ IN CASE WHEN mentionedArtifact IS NOT NULL THEN [1] ELSE [] END | MERGE (mentionedArtifact)-[:MENTIONS]->(keep))
|
|
469
|
+
WITH keep, alias
|
|
470
|
+
OPTIONAL MATCH (mentionedTodo:Todo)-[:MENTIONS]->(alias)
|
|
471
|
+
FOREACH (_ IN CASE WHEN mentionedTodo IS NOT NULL THEN [1] ELSE [] END | MERGE (mentionedTodo)-[:MENTIONS]->(keep))
|
|
472
|
+
WITH keep, alias
|
|
473
|
+
OPTIONAL MATCH (q:Quest)-[:STARTED_BY]->(alias)
|
|
474
|
+
FOREACH (_ IN CASE WHEN q IS NOT NULL THEN [1] ELSE [] END | MERGE (q)-[:STARTED_BY]->(keep))
|
|
475
|
+
WITH keep, alias
|
|
476
|
+
OPTIONAL MATCH (askedBy:QuestionSet)-[:ASKED_BY]->(alias)
|
|
477
|
+
FOREACH (_ IN CASE WHEN askedBy IS NOT NULL THEN [1] ELSE [] END | MERGE (askedBy)-[:ASKED_BY]->(keep))
|
|
478
|
+
WITH keep, alias
|
|
479
|
+
OPTIONAL MATCH (askedTo:QuestionSet)-[:ASKED_TO]->(alias)
|
|
480
|
+
FOREACH (_ IN CASE WHEN askedTo IS NOT NULL THEN [1] ELSE [] END | MERGE (askedTo)-[:ASKED_TO]->(keep))
|
|
481
|
+
WITH keep, alias
|
|
482
|
+
OPTIONAL MATCH (tu:TelegramUser)-[:IDENTIFIES]->(alias)
|
|
483
|
+
FOREACH (_ IN CASE WHEN tu IS NOT NULL THEN [1] ELSE [] END | MERGE (tu)-[:IDENTIFIES]->(keep))
|
|
484
|
+
WITH keep, alias
|
|
485
|
+
OPTIONAL MATCH (reported:Issue)-[:REPORTED_BY]->(alias)
|
|
486
|
+
FOREACH (_ IN CASE WHEN reported IS NOT NULL THEN [1] ELSE [] END | MERGE (reported)-[:REPORTED_BY]->(keep))
|
|
487
|
+
WITH keep, alias
|
|
488
|
+
OPTIONAL MATCH (initiated:Harvest)-[:INITIATED_BY]->(alias)
|
|
489
|
+
FOREACH (_ IN CASE WHEN initiated IS NOT NULL THEN [1] ELSE [] END | MERGE (initiated)-[:INITIATED_BY]->(keep))
|
|
490
|
+
WITH keep, alias
|
|
491
|
+
OPTIONAL MATCH (withPerson:HarvestSession)-[:WITH]->(alias)
|
|
492
|
+
FOREACH (_ IN CASE WHEN withPerson IS NOT NULL THEN [1] ELSE [] END | MERGE (withPerson)-[:WITH]->(keep))
|
|
493
|
+
WITH keep, alias
|
|
494
|
+
OPTIONAL MATCH (alias)-[:SENT_EMISSARY]->(emissary:Emissary)
|
|
495
|
+
FOREACH (_ IN CASE WHEN emissary IS NOT NULL THEN [1] ELSE [] END | MERGE (keep)-[:SENT_EMISSARY]->(emissary))
|
|
496
|
+
WITH keep, alias
|
|
497
|
+
OPTIONAL MATCH (alias)-[:MEMBER_OF]->(o:Org)
|
|
498
|
+
FOREACH (_ IN CASE WHEN o IS NOT NULL THEN [1] ELSE [] END | MERGE (keep)-[:MEMBER_OF]->(o))
|
|
499
|
+
WITH keep, alias
|
|
500
|
+
MERGE (alias)-[:ALIAS_OF]->(keep)
|
|
501
|
+
SET alias.kind = 'identity_alias',
|
|
502
|
+
alias.canonicalPersonId = keep.personId,
|
|
503
|
+
alias.identityStatus = 'alias'
|
|
504
|
+
RETURN keep.name AS name, keep.github AS github, keep.previousNames AS aliases
|
|
505
|
+
" "$(jq -n --arg keep "$KEEP" --arg alias "$ALIAS" '{keep: $keep, alias: $alias}')"
|
|
506
|
+
;;
|
|
507
|
+
|
|
508
|
+
claim-handoff)
|
|
509
|
+
IMPL_SID="${1:?missing implementing-session-id}"
|
|
510
|
+
HO_SID="${2:?missing handoff-session-id}"
|
|
511
|
+
CYPHER="
|
|
512
|
+
MATCH (impl:Session {id: \$implSid}), (ho:Session {id: \$hoSid})
|
|
513
|
+
MATCH (impl)-[:BY]->(claimant:Person)
|
|
514
|
+
MATCH (ho)-[:HANDED_TO]->(claimant)
|
|
515
|
+
WHERE ho.handoffStatus IN ['pending','read','claimed']
|
|
516
|
+
MERGE (impl)-[:IMPLEMENTS]->(ho)
|
|
517
|
+
WITH impl, ho, size([(ho)-[:HANDED_TO]->(:Person) | 1]) AS recipientCount
|
|
518
|
+
FOREACH (_ IN CASE WHEN recipientCount = 1 THEN [1] ELSE [] END |
|
|
519
|
+
SET ho.handoffStatus = 'claimed',
|
|
520
|
+
ho.handoffClaimedAt = coalesce(ho.handoffClaimedAt, datetime()),
|
|
521
|
+
ho.handoffUpdatedAt = datetime(),
|
|
522
|
+
ho.handoffLifecycleReason = 'implementation_claimed',
|
|
523
|
+
ho.handoffLifecycleVersion = 1)
|
|
524
|
+
RETURN impl.id AS implementor, ho.id AS handoff, ho.topic AS topic,
|
|
525
|
+
ho.handoffStatus AS status, recipientCount
|
|
526
|
+
"
|
|
527
|
+
PARAMS="$(jq -n --arg implSid "$IMPL_SID" --arg hoSid "$HO_SID" '{implSid: $implSid, hoSid: $hoSid}')"
|
|
528
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
529
|
+
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
530
|
+
;;
|
|
531
|
+
|
|
532
|
+
claim-handoff-nudge)
|
|
533
|
+
SID="${1:?missing handoff-session-id}"
|
|
534
|
+
bash "$GS" query "
|
|
535
|
+
MATCH (s:Session {id: \$sid})-[:HANDED_TO]->(recipient:Person)
|
|
536
|
+
WHERE coalesce(s.handoffStatus, 'pending') IN ['pending','read','claimed']
|
|
537
|
+
AND coalesce(s.handoffLifecycleVersion, 0) >= 1
|
|
538
|
+
AND coalesce(s.handoffIntent, 'unclassified') IN ['action','feedback','fyi']
|
|
539
|
+
AND s.handoffNudgedAt IS NULL
|
|
540
|
+
AND (s.handoffNudgeClaimedAt IS NULL
|
|
541
|
+
OR s.handoffNudgeClaimedAt < datetime() - duration('PT1H'))
|
|
542
|
+
WITH s, collect(DISTINCT recipient.name) AS recipients
|
|
543
|
+
WHERE size(recipients) = 1
|
|
544
|
+
SET s.handoffNudgeClaimedAt = datetime(),
|
|
545
|
+
s.handoffNudgeStatus = 'claimed'
|
|
546
|
+
RETURN s.id AS id, s.topic AS topic, recipients
|
|
547
|
+
" "$(jq -n --arg sid "$SID" '{sid:$sid}')"
|
|
548
|
+
;;
|
|
549
|
+
|
|
550
|
+
mark-handoff-nudged)
|
|
551
|
+
SID="${1:?missing handoff-session-id}"
|
|
552
|
+
bash "$GS" query "
|
|
553
|
+
MATCH (s:Session {id: \$sid})
|
|
554
|
+
WHERE s.handoffNudgeStatus = 'claimed' AND s.handoffNudgedAt IS NULL
|
|
555
|
+
SET s.handoffNudgedAt = datetime(),
|
|
556
|
+
s.handoffNudgeStatus = 'sent',
|
|
557
|
+
s.handoffUpdatedAt = datetime(),
|
|
558
|
+
s.handoffLifecycleReason = 'recipient_nudged',
|
|
559
|
+
s.handoffLifecycleVersion = 1
|
|
560
|
+
RETURN s.id AS id, s.handoffNudgeStatus AS status
|
|
561
|
+
" "$(jq -n --arg sid "$SID" '{sid:$sid}')"
|
|
562
|
+
;;
|
|
563
|
+
|
|
564
|
+
release-handoff-nudge)
|
|
565
|
+
SID="${1:?missing handoff-session-id}"
|
|
566
|
+
bash "$GS" query "
|
|
567
|
+
MATCH (s:Session {id: \$sid})
|
|
568
|
+
WHERE s.handoffNudgeStatus = 'claimed' AND s.handoffNudgedAt IS NULL
|
|
569
|
+
SET s.handoffNudgeClaimedAt = null,
|
|
570
|
+
s.handoffNudgeStatus = 'failed',
|
|
571
|
+
s.handoffNudgeFailedAt = datetime()
|
|
572
|
+
RETURN s.id AS id, s.handoffNudgeStatus AS status
|
|
573
|
+
" "$(jq -n --arg sid "$SID" '{sid:$sid}')"
|
|
574
|
+
;;
|
|
575
|
+
|
|
576
|
+
create-pr)
|
|
577
|
+
SID="${1:?missing session-id}"
|
|
578
|
+
PR_NUM="${2:?missing pr-number}"
|
|
579
|
+
REPO="${3:?missing repo}"
|
|
580
|
+
AUTHOR_GH="${4:?missing author-github}"
|
|
581
|
+
TITLE="${5:-}"
|
|
582
|
+
CYPHER="
|
|
583
|
+
MERGE (pr:PR {number: toInteger(\$num), repo: \$repo})
|
|
584
|
+
ON CREATE SET pr.author = \$author, pr.status = 'open',
|
|
585
|
+
pr.createdAt = datetime(), pr.title = \$title
|
|
586
|
+
WITH pr
|
|
587
|
+
OPTIONAL MATCH (s:Session {id: \$sid})
|
|
588
|
+
FOREACH (_ IN CASE WHEN s IS NOT NULL THEN [1] ELSE [] END |
|
|
589
|
+
MERGE (s)-[:PRODUCED]->(pr))
|
|
590
|
+
RETURN pr.number AS number, pr.repo AS repo
|
|
591
|
+
"
|
|
592
|
+
PARAMS="$(jq -n --arg sid "$SID" --argjson num "$PR_NUM" --arg repo "$REPO" --arg author "$AUTHOR_GH" --arg title "$TITLE" '{sid: $sid, num: $num, repo: $repo, author: $author, title: $title}')"
|
|
593
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
594
|
+
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
595
|
+
;;
|
|
596
|
+
|
|
597
|
+
register-artifact)
|
|
598
|
+
# Index a published (hosted) artifact as an Artifact node so the finder can
|
|
599
|
+
# retrieve it from the graph in connected mode — by content (title/topics/
|
|
600
|
+
# excerpt CONTAINS) and by relationship (who made it, which quest). The node
|
|
601
|
+
# id is the registry FILENAME STEM (date-author-slug), matching sync-graph.sh
|
|
602
|
+
# so a later /save sync upserts the same node instead of duplicating it.
|
|
603
|
+
# args: <id> <url> <title> <type> <author-handle> <topics-csv> <excerpt>
|
|
604
|
+
A_ID="${1:?missing id}"
|
|
605
|
+
A_URL="${2:?missing url}"
|
|
606
|
+
A_TITLE="${3:-}"
|
|
607
|
+
A_TYPE="${4:-artifact}"
|
|
608
|
+
A_AUTHOR="$(printf '%s' "${5:-}" | tr '[:upper:]' '[:lower:]' | awk '{print $1}')"
|
|
609
|
+
A_TOPICS_JSON="$(printf '%s' "${6:-}" | jq -Rc 'split(",") | map(gsub("^\\s+|\\s+$";"")) | map(select(length > 0))' 2>/dev/null || echo '[]')"
|
|
610
|
+
A_EXCERPT="$(printf '%s' "${7:-}" | tr '\n' ' ' | cut -c1-2000)"
|
|
611
|
+
CYPHER="
|
|
612
|
+
MERGE (a:Artifact {id: \$id})
|
|
613
|
+
ON CREATE SET a.created = datetime()
|
|
614
|
+
SET a.title = \$title, a.type = \$type, a.url = \$url,
|
|
615
|
+
a.topics = \$topics, a.excerpt = \$excerpt, a.published = true
|
|
616
|
+
WITH a
|
|
617
|
+
OPTIONAL MATCH (p:Person)
|
|
618
|
+
WHERE \$author <> '' AND (toLower(p.name) = \$author OR p.github = \$author)
|
|
619
|
+
FOREACH (_ IN CASE WHEN p IS NOT NULL THEN [1] ELSE [] END |
|
|
620
|
+
MERGE (a)-[:CONTRIBUTED_BY]->(p))
|
|
621
|
+
RETURN a.id AS id
|
|
622
|
+
"
|
|
623
|
+
PARAMS="$(jq -n --arg id "$A_ID" --arg url "$A_URL" --arg title "$A_TITLE" --arg type "$A_TYPE" \
|
|
624
|
+
--arg author "$A_AUTHOR" --argjson topics "$A_TOPICS_JSON" --arg excerpt "$A_EXCERPT" \
|
|
625
|
+
'{id: $id, url: $url, title: $title, type: $type, author: $author, topics: $topics, excerpt: $excerpt}')"
|
|
626
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
627
|
+
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
628
|
+
;;
|
|
629
|
+
|
|
630
|
+
check-implements)
|
|
631
|
+
SID="${1:?missing session-id}"
|
|
632
|
+
bash "$GS" query "
|
|
633
|
+
MATCH (impl:Session {id: \$sid})-[:IMPLEMENTS]->(ho:Session)-[:BY]->(author:Person)
|
|
634
|
+
RETURN ho.id AS handoffId, ho.topic AS topic, author.name AS author,
|
|
635
|
+
author.github AS authorGithub
|
|
636
|
+
" "$(jq -n --arg sid "$SID" '{sid: $sid}')"
|
|
637
|
+
;;
|
|
638
|
+
|
|
639
|
+
update-pr)
|
|
640
|
+
PR_NUM="${1:?missing pr-number}"
|
|
641
|
+
REPO="${2:?missing repo}"
|
|
642
|
+
STATUS="${3:?missing status}"
|
|
643
|
+
MERGED_AT="${4:-}"
|
|
644
|
+
if [ -n "$MERGED_AT" ]; then
|
|
645
|
+
bash "$GS" query "
|
|
646
|
+
MATCH (pr:PR {number: toInteger(\$num), repo: \$repo})
|
|
647
|
+
SET pr.status = \$status, pr.mergedAt = datetime(\$mergedAt)
|
|
648
|
+
RETURN pr.number AS number, pr.status AS status
|
|
649
|
+
" "$(jq -n --argjson num "$PR_NUM" --arg repo "$REPO" --arg status "$STATUS" --arg mergedAt "$MERGED_AT" '{num: $num, repo: $repo, status: $status, mergedAt: $mergedAt}')"
|
|
650
|
+
else
|
|
651
|
+
bash "$GS" query "
|
|
652
|
+
MATCH (pr:PR {number: toInteger(\$num), repo: \$repo})
|
|
653
|
+
SET pr.status = \$status
|
|
654
|
+
RETURN pr.number AS number, pr.status AS status
|
|
655
|
+
" "$(jq -n --argjson num "$PR_NUM" --arg repo "$REPO" --arg status "$STATUS" '{num: $num, repo: $repo, status: $status}')"
|
|
656
|
+
fi
|
|
657
|
+
;;
|
|
658
|
+
|
|
659
|
+
my-merged-prs)
|
|
660
|
+
AUTHOR_GH="${1:?missing author-github}"
|
|
661
|
+
SINCE="${2:-}"
|
|
662
|
+
if [ -n "$SINCE" ]; then
|
|
663
|
+
bash "$GS" query "
|
|
664
|
+
MATCH (pr:PR {author: \$author})
|
|
665
|
+
WHERE pr.status = 'merged' AND pr.mergedAt >= datetime(\$since)
|
|
666
|
+
RETURN pr.number AS number, pr.repo AS repo, pr.title AS title,
|
|
667
|
+
toString(pr.mergedAt) AS mergedAt
|
|
668
|
+
ORDER BY pr.mergedAt DESC LIMIT 10
|
|
669
|
+
" "$(jq -n --arg author "$AUTHOR_GH" --arg since "${SINCE}T00:00:00Z" '{author: $author, since: $since}')"
|
|
670
|
+
else
|
|
671
|
+
bash "$GS" query "
|
|
672
|
+
MATCH (pr:PR {author: \$author})
|
|
673
|
+
WHERE pr.status = 'merged'
|
|
674
|
+
RETURN pr.number AS number, pr.repo AS repo, pr.title AS title,
|
|
675
|
+
toString(pr.mergedAt) AS mergedAt
|
|
676
|
+
ORDER BY pr.mergedAt DESC LIMIT 5
|
|
677
|
+
" "$(jq -n --arg author "$AUTHOR_GH" '{author: $author}')"
|
|
678
|
+
fi
|
|
679
|
+
;;
|
|
680
|
+
|
|
681
|
+
my-implemented-handoffs)
|
|
682
|
+
AUTHOR_NAME="${1:?missing author-name}"
|
|
683
|
+
SINCE="${2:-}"
|
|
684
|
+
if [ -n "$SINCE" ]; then
|
|
685
|
+
bash "$GS" query "
|
|
686
|
+
MATCH (impl:Session)-[:IMPLEMENTS]->(ho:Session)-[:BY]->(author:Person)
|
|
687
|
+
WHERE toLower(author.name) = toLower(\$author)
|
|
688
|
+
AND impl.wrappedAt >= datetime(\$since)
|
|
689
|
+
MATCH (impl)-[:BY]->(implementor:Person)
|
|
690
|
+
RETURN ho.topic AS handoffTopic, implementor.name AS implementedBy,
|
|
691
|
+
toString(impl.wrappedAt) AS completedAt, impl.summary AS summary
|
|
692
|
+
ORDER BY impl.wrappedAt DESC LIMIT 10
|
|
693
|
+
" "$(jq -n --arg author "$AUTHOR_NAME" --arg since "${SINCE}T00:00:00Z" '{author: $author, since: $since}')"
|
|
694
|
+
else
|
|
695
|
+
bash "$GS" query "
|
|
696
|
+
MATCH (impl:Session)-[:IMPLEMENTS]->(ho:Session)-[:BY]->(author:Person)
|
|
697
|
+
WHERE toLower(author.name) = toLower(\$author)
|
|
698
|
+
MATCH (impl)-[:BY]->(implementor:Person)
|
|
699
|
+
RETURN ho.topic AS handoffTopic, implementor.name AS implementedBy,
|
|
700
|
+
toString(impl.wrappedAt) AS completedAt, impl.summary AS summary
|
|
701
|
+
ORDER BY impl.wrappedAt DESC LIMIT 5
|
|
702
|
+
" "$(jq -n --arg author "$AUTHOR_NAME" '{author: $author}')"
|
|
703
|
+
fi
|
|
704
|
+
;;
|
|
705
|
+
|
|
706
|
+
open-handoffs)
|
|
707
|
+
USER="${1:?missing username}"
|
|
708
|
+
LIMIT="${2:-10}"
|
|
709
|
+
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || [ "$LIMIT" -lt 1 ] || [ "$LIMIT" -gt 25 ]; then
|
|
710
|
+
echo '{"error":"limit must be between 1 and 25"}'
|
|
711
|
+
exit 2
|
|
712
|
+
fi
|
|
713
|
+
bash "$GS" query "
|
|
714
|
+
MATCH (s:Session)-[:HANDED_TO]->(p:Person)
|
|
715
|
+
WHERE NOT coalesce(p.kind, '') IN ['identity_alias']
|
|
716
|
+
AND (
|
|
717
|
+
toLower(coalesce(p.name, '')) = toLower(\$user)
|
|
718
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)
|
|
719
|
+
OR toLower(coalesce(p.githubUsername, '')) = toLower(\$user)
|
|
720
|
+
OR any(alias IN coalesce(p.previousNames, [])
|
|
721
|
+
WHERE toLower(alias) = toLower(\$user))
|
|
722
|
+
)
|
|
723
|
+
AND coalesce(s.handoffStatus, 'pending')
|
|
724
|
+
IN ['pending','unread','read','claimed']
|
|
725
|
+
WITH DISTINCT s
|
|
726
|
+
WITH s, head([(s)-[:BY]->(author:Person)
|
|
727
|
+
WHERE NOT coalesce(author.kind, '') IN ['identity_alias'] | author.name]) AS authorName,
|
|
728
|
+
CASE WHEN s.date IS NULL THEN null
|
|
729
|
+
ELSE duration.inDays(date(s.date), date()).days END AS ageDays
|
|
730
|
+
RETURN s.id AS id,
|
|
731
|
+
coalesce(s.topic, s.summary, s.branch) AS topic,
|
|
732
|
+
coalesce(authorName, s.author, 'unknown') AS author,
|
|
733
|
+
toString(s.date) AS date,
|
|
734
|
+
coalesce(s.handoffStatus, 'pending') AS status,
|
|
735
|
+
coalesce(s.handoffIntent, 'unclassified') AS intent,
|
|
736
|
+
ageDays,
|
|
737
|
+
CASE WHEN ageDays IS NULL THEN 'unknown'
|
|
738
|
+
WHEN ageDays <= 14 THEN 'current'
|
|
739
|
+
WHEN ageDays <= 30 THEN 'aging'
|
|
740
|
+
ELSE 'stale' END AS freshness,
|
|
741
|
+
1 AS definitionVersion
|
|
742
|
+
ORDER BY s.date DESC, s.id
|
|
743
|
+
LIMIT \$limit
|
|
744
|
+
" "$(jq -n --arg user "$USER" --argjson limit "$LIMIT" '{user: $user, limit: $limit}')"
|
|
745
|
+
;;
|
|
746
|
+
|
|
747
|
+
pending-questions)
|
|
748
|
+
USER="${1:?missing username}"
|
|
749
|
+
LIMIT="${2:-10}"
|
|
750
|
+
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || [ "$LIMIT" -lt 1 ] || [ "$LIMIT" -gt 25 ]; then
|
|
751
|
+
echo '{"error":"limit must be between 1 and 25"}'
|
|
752
|
+
exit 2
|
|
753
|
+
fi
|
|
754
|
+
bash "$GS" query "
|
|
755
|
+
MATCH (qs:QuestionSet)-[:ASKED_TO]->(p:Person)
|
|
756
|
+
WHERE (
|
|
757
|
+
toLower(coalesce(p.name, '')) = toLower(\$user)
|
|
758
|
+
OR toLower(coalesce(p.github, '')) = toLower(\$user)
|
|
759
|
+
OR toLower(coalesce(p.githubUsername, '')) = toLower(\$user)
|
|
760
|
+
OR any(alias IN coalesce(p.previousNames, [])
|
|
761
|
+
WHERE toLower(alias) = toLower(\$user))
|
|
762
|
+
)
|
|
763
|
+
AND coalesce(qs.status, 'pending') IN ['pending','active']
|
|
764
|
+
WITH DISTINCT qs
|
|
765
|
+
OPTIONAL MATCH (q:Question)-[:PART_OF]->(qs)
|
|
766
|
+
OPTIONAL MATCH (qs)-[:ASKED_BY]->(asker:Person)
|
|
767
|
+
WITH qs, asker, count(DISTINCT q) AS questions,
|
|
768
|
+
CASE WHEN qs.created IS NULL THEN null
|
|
769
|
+
ELSE duration.inDays(date(datetime(qs.created)), date()).days END AS ageDays
|
|
770
|
+
RETURN qs.id AS id,
|
|
771
|
+
qs.topic AS topic,
|
|
772
|
+
coalesce(asker.name, qs.askedBy, qs.from, 'unknown') AS askedBy,
|
|
773
|
+
questions,
|
|
774
|
+
toString(qs.created) AS created,
|
|
775
|
+
ageDays,
|
|
776
|
+
CASE WHEN ageDays IS NULL THEN 'unknown'
|
|
777
|
+
WHEN ageDays <= 14 THEN 'current'
|
|
778
|
+
WHEN ageDays <= 30 THEN 'aging'
|
|
779
|
+
ELSE 'stale-open' END AS freshness,
|
|
780
|
+
1 AS definitionVersion
|
|
781
|
+
ORDER BY qs.created DESC, qs.id
|
|
782
|
+
LIMIT \$limit
|
|
783
|
+
" "$(jq -n --arg user "$USER" --argjson limit "$LIMIT" '{user: $user, limit: $limit}')"
|
|
784
|
+
;;
|
|
785
|
+
|
|
786
|
+
lineage)
|
|
787
|
+
QUERY="${1:?missing topic}"
|
|
788
|
+
LIMIT="${2:-10}"
|
|
789
|
+
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || [ "$LIMIT" -lt 1 ] || [ "$LIMIT" -gt 15 ]; then
|
|
790
|
+
echo '{"error":"limit must be between 1 and 15"}'
|
|
791
|
+
exit 2
|
|
792
|
+
fi
|
|
793
|
+
GRAPH_RAW="$(bash "$GS" query "
|
|
794
|
+
MATCH (s:Session)
|
|
795
|
+
WHERE toLower(coalesce(s.topic, '')) CONTAINS toLower(\$query)
|
|
796
|
+
OR toLower(coalesce(s.summary, '')) CONTAINS toLower(\$query)
|
|
797
|
+
OR toLower(coalesce(s.branch, '')) CONTAINS toLower(\$query)
|
|
798
|
+
OPTIONAL MATCH (s)-[:BY]->(author:Person)
|
|
799
|
+
OPTIONAL MATCH (s)-[:HANDED_TO]->(recipient:Person)
|
|
800
|
+
OPTIONAL MATCH (implementation:Session)-[:IMPLEMENTS]->(s)
|
|
801
|
+
OPTIONAL MATCH (implementation)-[:BY]->(implementer:Person)
|
|
802
|
+
OPTIONAL MATCH (s)-[:IMPLEMENTS]->(prior:Session)
|
|
803
|
+
OPTIONAL MATCH (prior)-[:BY]->(priorAuthor:Person)
|
|
804
|
+
OPTIONAL MATCH (s)-[:PRODUCED]->(pr:PR)
|
|
805
|
+
OPTIONAL MATCH (implementation)-[:PRODUCED]->(implementationPr:PR)
|
|
806
|
+
WITH s, author,
|
|
807
|
+
collect(DISTINCT coalesce(recipient.name, recipient.github)) AS recipients,
|
|
808
|
+
collect(DISTINCT CASE WHEN implementation IS NULL THEN null ELSE {
|
|
809
|
+
id: implementation.id,
|
|
810
|
+
topic: implementation.topic,
|
|
811
|
+
summary: implementation.summary,
|
|
812
|
+
branch: implementation.branch,
|
|
813
|
+
date: toString(implementation.date),
|
|
814
|
+
evidencePath: CASE
|
|
815
|
+
WHEN implementation.filePath IS NULL THEN null
|
|
816
|
+
WHEN implementation.filePath STARTS WITH 'memory/' THEN implementation.filePath
|
|
817
|
+
ELSE 'memory/' + implementation.filePath END,
|
|
818
|
+
implementedBy: coalesce(implementer.name, implementer.github)
|
|
819
|
+
} END) AS implementations,
|
|
820
|
+
collect(DISTINCT CASE WHEN prior IS NULL THEN null ELSE {
|
|
821
|
+
id: prior.id,
|
|
822
|
+
topic: prior.topic,
|
|
823
|
+
summary: prior.summary,
|
|
824
|
+
branch: prior.branch,
|
|
825
|
+
date: toString(prior.date),
|
|
826
|
+
evidencePath: CASE
|
|
827
|
+
WHEN prior.filePath IS NULL THEN null
|
|
828
|
+
WHEN prior.filePath STARTS WITH 'memory/' THEN prior.filePath
|
|
829
|
+
ELSE 'memory/' + prior.filePath END,
|
|
830
|
+
author: coalesce(priorAuthor.name, priorAuthor.github)
|
|
831
|
+
} END) AS implements,
|
|
832
|
+
collect(DISTINCT CASE WHEN pr IS NULL THEN null ELSE {
|
|
833
|
+
number: pr.number, repo: pr.repo, title: pr.title,
|
|
834
|
+
status: pr.status, mergedAt: toString(pr.mergedAt)
|
|
835
|
+
} END)
|
|
836
|
+
+ collect(DISTINCT CASE WHEN implementationPr IS NULL THEN null ELSE {
|
|
837
|
+
number: implementationPr.number, repo: implementationPr.repo,
|
|
838
|
+
title: implementationPr.title, status: implementationPr.status,
|
|
839
|
+
mergedAt: toString(implementationPr.mergedAt)
|
|
840
|
+
} END) AS prs
|
|
841
|
+
RETURN s.id AS sessionId,
|
|
842
|
+
s.topic AS topic,
|
|
843
|
+
s.summary AS summary,
|
|
844
|
+
s.branch AS branch,
|
|
845
|
+
toString(s.date) AS date,
|
|
846
|
+
CASE WHEN s.filePath IS NULL THEN null
|
|
847
|
+
WHEN s.filePath STARTS WITH 'memory/' THEN s.filePath
|
|
848
|
+
ELSE 'memory/' + s.filePath END AS evidencePath,
|
|
849
|
+
coalesce(author.name, author.github, s.author, 'unknown') AS author,
|
|
850
|
+
recipients[0..20] AS recipients,
|
|
851
|
+
implementations[0..10] AS implementations,
|
|
852
|
+
implements[0..10] AS implements,
|
|
853
|
+
prs[0..10] AS prs
|
|
854
|
+
ORDER BY s.date DESC, s.id
|
|
855
|
+
LIMIT \$limit
|
|
856
|
+
" "$(jq -n --arg query "$QUERY" --argjson limit "$LIMIT" '{query:$query,limit:$limit}')")"
|
|
857
|
+
FILES_RAW="$(memory_file_candidates "$QUERY" "$LIMIT" \
|
|
858
|
+
"$SCRIPT_DIR/memory/handoffs" \
|
|
859
|
+
"$SCRIPT_DIR/memory/wraps" \
|
|
860
|
+
"$SCRIPT_DIR/memory/sessions")"
|
|
861
|
+
jq -n \
|
|
862
|
+
--arg query "$QUERY" \
|
|
863
|
+
--argjson limit "$LIMIT" \
|
|
864
|
+
--argjson graph "$GRAPH_RAW" \
|
|
865
|
+
--argjson files "$FILES_RAW" '
|
|
866
|
+
($graph.values // [] | map({
|
|
867
|
+
sessionId: .[0], topic: .[1], summary: .[2], branch: .[3],
|
|
868
|
+
date: .[4], evidencePath: .[5], author: .[6],
|
|
869
|
+
recipients: (.[7] // []), implementations: (.[8] // []),
|
|
870
|
+
implements: (.[9] // []), prs: (.[10] // [])
|
|
871
|
+
})) as $matches
|
|
872
|
+
| ($matches | map(.evidencePath) | map(select(. != null)) | unique) as $graphPaths
|
|
873
|
+
| ($files | map(.evidencePath) | unique) as $filePaths
|
|
874
|
+
| ($filePaths - $graphPaths) as $unprojected
|
|
875
|
+
| {
|
|
876
|
+
schema: "egregore.graph-read/v1",
|
|
877
|
+
operation: "lineage",
|
|
878
|
+
definitionVersion: 1,
|
|
879
|
+
query: $query,
|
|
880
|
+
limit: $limit,
|
|
881
|
+
coverage:
|
|
882
|
+
(if ($graphPaths | length) == 0 then
|
|
883
|
+
(if ($filePaths | length) == 0 then "none" else "filesystem-only" end)
|
|
884
|
+
elif ($unprojected | length) > 0 then "partial"
|
|
885
|
+
else "complete" end),
|
|
886
|
+
graphMatches: $matches,
|
|
887
|
+
fileCandidates:
|
|
888
|
+
($files | map(
|
|
889
|
+
. as $candidate
|
|
890
|
+
| . + {
|
|
891
|
+
projection:
|
|
892
|
+
(if ($graphPaths | index($candidate.evidencePath)) != null
|
|
893
|
+
then "projected" else "unprojected" end)
|
|
894
|
+
}
|
|
895
|
+
)),
|
|
896
|
+
unprojectedPaths: $unprojected
|
|
897
|
+
}
|
|
898
|
+
'
|
|
899
|
+
;;
|
|
900
|
+
|
|
901
|
+
meeting-history)
|
|
902
|
+
QUERY="${1:?missing company, person, or topic}"
|
|
903
|
+
LIMIT="${2:-10}"
|
|
904
|
+
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || [ "$LIMIT" -lt 1 ] || [ "$LIMIT" -gt 15 ]; then
|
|
905
|
+
echo '{"error":"limit must be between 1 and 15"}'
|
|
906
|
+
exit 2
|
|
907
|
+
fi
|
|
908
|
+
QUERY_TERMS="$(meaningful_query_terms "$QUERY")"
|
|
909
|
+
GRAPH_RAW="$(bash "$GS" query "
|
|
910
|
+
MATCH (m:Meeting)
|
|
911
|
+
OPTIONAL MATCH (m)-[:INVOLVES|CONDUCTED_BY]->(participant:Person)
|
|
912
|
+
WITH m, collect(DISTINCT participant) AS participants
|
|
913
|
+
WITH m, participants,
|
|
914
|
+
[term IN \$terms WHERE
|
|
915
|
+
toLower(coalesce(m.title, '')) CONTAINS term
|
|
916
|
+
OR toLower(coalesce(m.name, '')) CONTAINS term
|
|
917
|
+
OR toLower(coalesce(m.id, '')) CONTAINS term
|
|
918
|
+
OR any(p IN participants WHERE
|
|
919
|
+
toLower(coalesce(p.name, '')) CONTAINS term
|
|
920
|
+
OR toLower(coalesce(p.github, '')) CONTAINS term)
|
|
921
|
+
] AS matchedTerms
|
|
922
|
+
WHERE size(matchedTerms) > 0
|
|
923
|
+
OPTIONAL MATCH (artifact:Artifact)-[:FROM_MEETING]->(m)
|
|
924
|
+
RETURN m.id AS meetingId,
|
|
925
|
+
coalesce(m.title, m.name, m.id) AS title,
|
|
926
|
+
toString(m.date) AS date,
|
|
927
|
+
CASE WHEN m.filePath IS NULL THEN null
|
|
928
|
+
WHEN m.filePath STARTS WITH 'memory/' THEN m.filePath
|
|
929
|
+
ELSE 'memory/' + m.filePath END AS evidencePath,
|
|
930
|
+
([p IN participants | coalesce(p.name, p.github)])[0..20] AS participants,
|
|
931
|
+
(collect(DISTINCT CASE WHEN artifact IS NULL THEN null ELSE {
|
|
932
|
+
id: artifact.id,
|
|
933
|
+
type: artifact.type,
|
|
934
|
+
title: artifact.title,
|
|
935
|
+
summary: artifact.summary,
|
|
936
|
+
evidencePath: CASE
|
|
937
|
+
WHEN artifact.filePath IS NULL THEN null
|
|
938
|
+
WHEN artifact.filePath STARTS WITH 'memory/' THEN artifact.filePath
|
|
939
|
+
ELSE 'memory/' + artifact.filePath END
|
|
940
|
+
} END))[0..10] AS derivedKnowledge,
|
|
941
|
+
coalesce(m.verificationStatus, 'legacy') AS verificationStatus,
|
|
942
|
+
m.ingestManifestId AS ingestManifestId,
|
|
943
|
+
matchedTerms,
|
|
944
|
+
size(matchedTerms) AS matchScore
|
|
945
|
+
ORDER BY matchScore DESC, date ASC, meetingId
|
|
946
|
+
LIMIT \$limit
|
|
947
|
+
" "$(jq -n --arg query "$QUERY" --argjson terms "$QUERY_TERMS" --argjson limit "$LIMIT" \
|
|
948
|
+
'{query:$query,terms:$terms,limit:$limit}')")"
|
|
949
|
+
FILES_RAW="$(memory_file_candidates_for_terms \
|
|
950
|
+
"$QUERY_TERMS" "$LIMIT" "$SCRIPT_DIR/memory/meetings")"
|
|
951
|
+
jq -n \
|
|
952
|
+
--arg query "$QUERY" \
|
|
953
|
+
--argjson queryTerms "$QUERY_TERMS" \
|
|
954
|
+
--argjson limit "$LIMIT" \
|
|
955
|
+
--argjson graph "$GRAPH_RAW" \
|
|
956
|
+
--argjson files "$FILES_RAW" '
|
|
957
|
+
($graph.values // [] | map({
|
|
958
|
+
meetingId: .[0], title: .[1], date: .[2], evidencePath: .[3],
|
|
959
|
+
participants: (.[4] // []), derivedKnowledge: (.[5] // []),
|
|
960
|
+
verificationStatus: .[6], ingestManifestId: .[7],
|
|
961
|
+
matchedTerms: (.[8] // []), matchScore: (.[9] // 0)
|
|
962
|
+
})) as $meetings
|
|
963
|
+
| ($meetings | map(.evidencePath) | map(select(. != null)) | unique) as $graphPaths
|
|
964
|
+
| ($files | map(.evidencePath) | unique) as $filePaths
|
|
965
|
+
| ($filePaths - $graphPaths) as $unprojected
|
|
966
|
+
| {
|
|
967
|
+
schema: "egregore.graph-read/v1",
|
|
968
|
+
operation: "meeting-history",
|
|
969
|
+
definitionVersion: 1,
|
|
970
|
+
query: $query,
|
|
971
|
+
queryTerms: $queryTerms,
|
|
972
|
+
limit: $limit,
|
|
973
|
+
coverage:
|
|
974
|
+
(if ($graphPaths | length) == 0 then
|
|
975
|
+
(if ($filePaths | length) == 0 then "none" else "filesystem-only" end)
|
|
976
|
+
elif ($unprojected | length) > 0 then "partial"
|
|
977
|
+
else "complete" end),
|
|
978
|
+
graphMeetings: $meetings,
|
|
979
|
+
fileCandidates:
|
|
980
|
+
($files | map(
|
|
981
|
+
. as $candidate
|
|
982
|
+
| . + {
|
|
983
|
+
projection:
|
|
984
|
+
(if ($graphPaths | index($candidate.evidencePath)) != null
|
|
985
|
+
then "projected" else "unprojected" end)
|
|
986
|
+
}
|
|
987
|
+
)),
|
|
988
|
+
unprojectedPaths: $unprojected
|
|
989
|
+
}
|
|
990
|
+
'
|
|
991
|
+
;;
|
|
992
|
+
|
|
993
|
+
wal-status)
|
|
994
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" status
|
|
995
|
+
;;
|
|
996
|
+
|
|
997
|
+
create-harvest)
|
|
998
|
+
HID="${1:?missing harvest-id}"
|
|
999
|
+
TOPIC="${2:?missing topic}"
|
|
1000
|
+
INTENT="${3:?missing intent}"
|
|
1001
|
+
INITIATOR="${4:?missing initiator}"
|
|
1002
|
+
CYPHER="
|
|
1003
|
+
MERGE (h:Harvest {id: \$hid})
|
|
1004
|
+
ON CREATE SET h.topic = \$topic, h.intent = \$intent,
|
|
1005
|
+
h.status = 'active', h.created = datetime()
|
|
1006
|
+
WITH h
|
|
1007
|
+
MATCH (p:Person) WHERE toLower(p.name) = toLower(\$initiator) OR p.github = \$initiator
|
|
1008
|
+
MERGE (h)-[:INITIATED_BY]->(p)
|
|
1009
|
+
RETURN h.id AS id, h.topic AS topic, h.status AS status
|
|
1010
|
+
"
|
|
1011
|
+
PARAMS="$(jq -n --arg hid "$HID" --arg topic "$TOPIC" --arg intent "$INTENT" --arg initiator "$INITIATOR" '{hid: $hid, topic: $topic, intent: $intent, initiator: $initiator}')"
|
|
1012
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
1013
|
+
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
1014
|
+
;;
|
|
1015
|
+
|
|
1016
|
+
create-harvest-session)
|
|
1017
|
+
HID="${1:?missing harvest-id}"
|
|
1018
|
+
HSID="${2:?missing session-id}"
|
|
1019
|
+
PERSON="${3:?missing person-name}"
|
|
1020
|
+
STATUS="${4:-active}"
|
|
1021
|
+
case "$STATUS" in
|
|
1022
|
+
pending|active|answered|complete|incorporated) ;;
|
|
1023
|
+
*) jq -n --arg s "$STATUS" '{error:("invalid status: "+$s),valid:["pending","active","answered","complete","incorporated"]}' >&2; exit 2 ;;
|
|
1024
|
+
esac
|
|
1025
|
+
CYPHER="
|
|
1026
|
+
MATCH (h:Harvest {id: \$hid})
|
|
1027
|
+
MERGE (hs:HarvestSession {id: \$hsid})
|
|
1028
|
+
ON CREATE SET hs.status = \$status, hs.created = datetime()
|
|
1029
|
+
MERGE (h)-[:HAS_SESSION]->(hs)
|
|
1030
|
+
WITH hs
|
|
1031
|
+
MATCH (p:Person) WHERE toLower(p.name) = toLower(\$person) OR p.github = \$person
|
|
1032
|
+
MERGE (hs)-[:WITH]->(p)
|
|
1033
|
+
RETURN hs.id AS id, hs.status AS status
|
|
1034
|
+
"
|
|
1035
|
+
PARAMS="$(jq -n --arg hid "$HID" --arg hsid "$HSID" --arg person "$PERSON" --arg status "$STATUS" '{hid: $hid, hsid: $hsid, person: $person, status: $status}')"
|
|
1036
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
1037
|
+
OUT="$(bash "$GS" query "$CYPHER" "$PARAMS")"
|
|
1038
|
+
if [ "$(echo "$OUT" | jq -r '.results | length' 2>/dev/null)" = "0" ]; then
|
|
1039
|
+
jq -n --arg hid "$HID" --arg hsid "$HSID" --arg person "$PERSON" \
|
|
1040
|
+
'{error:"create-harvest-session: harvest or person not found",hid:$hid,hsid:$hsid,person:$person}' >&2
|
|
1041
|
+
exit 3
|
|
1042
|
+
fi
|
|
1043
|
+
echo "$OUT"
|
|
1044
|
+
;;
|
|
1045
|
+
|
|
1046
|
+
record-harvest-turn)
|
|
1047
|
+
HSID="${1:?missing session-id}"
|
|
1048
|
+
TURN="${2:?missing turn-number}"
|
|
1049
|
+
QUESTION="${3:?missing question}"
|
|
1050
|
+
QINTENT="${4:?missing question-intent}"
|
|
1051
|
+
ANSWER="${5:-}"
|
|
1052
|
+
EVAL="${6:-}"
|
|
1053
|
+
TURN_ID="${HSID}-turn-${TURN}"
|
|
1054
|
+
PARAMS=$(jq -n \
|
|
1055
|
+
--arg hsid "$HSID" --arg tid "$TURN_ID" --arg turn "$TURN" \
|
|
1056
|
+
--arg question "$QUESTION" --arg qintent "$QINTENT" \
|
|
1057
|
+
--arg answer "$ANSWER" --arg eval "$EVAL" \
|
|
1058
|
+
'{hsid:$hsid, tid:$tid, turn:$turn, question:$question, qintent:$qintent, answer:$answer, eval:$eval}')
|
|
1059
|
+
if [ -n "$ANSWER" ]; then
|
|
1060
|
+
bash "$GS" query "
|
|
1061
|
+
MATCH (hs:HarvestSession {id: \$hsid})
|
|
1062
|
+
MERGE (t:HarvestTurn {id: \$tid})
|
|
1063
|
+
ON CREATE SET t.turnNumber = toInteger(\$turn), t.question = \$question,
|
|
1064
|
+
t.questionIntent = \$qintent, t.created = datetime()
|
|
1065
|
+
SET t.answer = \$answer, t.answeredAt = datetime()
|
|
1066
|
+
SET t.evaluation = CASE WHEN \$eval <> '' THEN \$eval ELSE t.evaluation END
|
|
1067
|
+
MERGE (hs)-[:HAS_TURN]->(t)
|
|
1068
|
+
RETURN t.id AS id, t.turnNumber AS turnNumber
|
|
1069
|
+
" "$PARAMS"
|
|
1070
|
+
else
|
|
1071
|
+
bash "$GS" query "
|
|
1072
|
+
MATCH (hs:HarvestSession {id: \$hsid})
|
|
1073
|
+
MERGE (t:HarvestTurn {id: \$tid})
|
|
1074
|
+
ON CREATE SET t.turnNumber = toInteger(\$turn), t.question = \$question,
|
|
1075
|
+
t.questionIntent = \$qintent, t.created = datetime()
|
|
1076
|
+
MERGE (hs)-[:HAS_TURN]->(t)
|
|
1077
|
+
RETURN t.id AS id, t.turnNumber AS turnNumber
|
|
1078
|
+
" "$PARAMS"
|
|
1079
|
+
fi
|
|
1080
|
+
;;
|
|
1081
|
+
|
|
1082
|
+
complete-harvest)
|
|
1083
|
+
HID="${1:?missing harvest-id}"
|
|
1084
|
+
ARTIFACT_PATH="${2:?missing artifact-path}"
|
|
1085
|
+
bash "$GS" query "
|
|
1086
|
+
MATCH (h:Harvest {id: \$hid})
|
|
1087
|
+
SET h.status = 'complete', h.completedAt = datetime(), h.synthesisPath = \$path
|
|
1088
|
+
WITH h
|
|
1089
|
+
OPTIONAL MATCH (h)-[:HAS_SESSION]->(hs:HarvestSession)
|
|
1090
|
+
WHERE hs.status <> 'complete'
|
|
1091
|
+
SET hs.status = 'complete', hs.completedAt = datetime()
|
|
1092
|
+
WITH h
|
|
1093
|
+
MERGE (a:Artifact {id: \$hid + '-synthesis'})
|
|
1094
|
+
ON CREATE SET a.type = 'harvest', a.title = h.topic, a.filePath = \$path,
|
|
1095
|
+
a.created = datetime(), a.topics = coalesce([h.topic], [])
|
|
1096
|
+
MERGE (h)-[:PRODUCED]->(a)
|
|
1097
|
+
RETURN h.id AS id, h.status AS status, a.id AS artifact
|
|
1098
|
+
" "$(jq -n --arg hid "$HID" --arg path "$ARTIFACT_PATH" '{hid: $hid, path: $path}')"
|
|
1099
|
+
;;
|
|
1100
|
+
|
|
1101
|
+
*)
|
|
1102
|
+
echo '{"error":"unknown operation: '"$OP"'","operations":["catalog","mark-read","mark-done","mark-expired","reopen-handoff","answer-question","resolve-handoffs","set-topic","record-focus","merge-person","claim-handoff","claim-handoff-nudge","mark-handoff-nudged","release-handoff-nudge","check-implements","create-pr","update-pr","my-merged-prs","my-implemented-handoffs","open-handoffs","pending-questions","lineage","meeting-history","wal-status","create-harvest","create-harvest-session","record-harvest-turn","complete-harvest"]}'
|
|
1103
|
+
exit 1
|
|
1104
|
+
;;
|
|
1105
|
+
|
|
1106
|
+
esac
|