create-egregore 0.21.6 → 0.22.0
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 +58 -6
- package/assets/egregore-launcher.sh +15 -2
- package/lib/claude-runtime.js +2 -0
- package/lib/codex-runtime.js +2 -0
- package/lib/setup.js +20 -3
- package/package.json +2 -2
- package/runtime/claude/.claude/context/commit-format.md +7 -4
- package/runtime/claude/.claude/context/handoff-claiming.md +32 -0
- package/runtime/claude/.claude/context/notification-consent.md +12 -9
- package/runtime/claude/.claude/hooks/boundary-check.sh +14 -331
- package/runtime/claude/.claude/hooks/memory-read-guard.sh +9 -1
- package/runtime/claude/.claude/rules/voice-bedrock.md +6 -2
- package/runtime/claude/.claude/settings.json +1 -1
- package/runtime/claude/.claude/skills/commit/SKILL.md +5 -3
- package/runtime/claude/.claude/skills/dark-mode/SKILL.md +48 -369
- package/runtime/claude/.claude/skills/records/SKILL.md +158 -0
- package/runtime/claude/.claude/skills/reflect/SKILL.md +50 -21
- package/runtime/claude/.claude/skills/review-pr/SKILL.md +4 -2
- package/runtime/claude/.claude/skills/save/SKILL.md +9 -3
- package/runtime/claude/.claude/skills/summon/SKILL.md +138 -207
- package/runtime/claude/.claude/skills/tui-design/SKILL.md +1 -1
- package/runtime/claude/.claude/skills/update/SKILL.md +1 -1
- package/runtime/claude/.claude/skills/view/SKILL.md +52 -16
- package/runtime/claude/.claude/skills/view/compose-scaffold.html +19 -13
- package/runtime/claude/CLAUDE.md +59 -95
- package/runtime/claude/bin/agent.sh +231 -7
- package/runtime/claude/bin/api-call.sh +44 -23
- package/runtime/claude/bin/artifact-register.sh +7 -1
- package/runtime/claude/bin/artifact-writeback.sh +1 -1
- package/runtime/claude/bin/artifacts.sh +66 -265
- package/runtime/claude/bin/attendant.sh +4 -1
- package/runtime/claude/bin/boundary-guard.cjs +1848 -0
- package/runtime/claude/bin/boundary-hook.sh +41 -0
- package/runtime/claude/bin/boundary.sh +15 -155
- package/runtime/claude/bin/capture-run.sh +32 -2
- package/runtime/claude/bin/codex-render-spec.mjs +24 -46
- package/runtime/claude/bin/codex-session-start.sh +19 -0
- package/runtime/claude/bin/codex-skill-render.mjs +18 -0
- package/runtime/claude/bin/config-get.sh +10 -1
- package/runtime/claude/bin/connect-refresh.sh +16 -0
- package/runtime/claude/bin/corpus_map.py +5 -0
- package/runtime/claude/bin/data/capabilities/claude.json +1480 -0
- package/runtime/claude/bin/genui.sh +19 -0
- package/runtime/claude/bin/graph-batch.sh +1 -1
- package/runtime/claude/bin/graph-op.sh +14 -0
- package/runtime/claude/bin/graph.sh +1 -1
- package/runtime/claude/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/claude/bin/handoff-run.sh +11 -6
- package/runtime/claude/bin/ingest-item.sh +1 -1
- package/runtime/claude/bin/ingest-surface.html +22 -4
- package/runtime/claude/bin/issue.sh +1 -1
- package/runtime/claude/bin/knowledge.sh +1 -1
- package/runtime/claude/bin/lib/card-delivery.sh +329 -0
- package/runtime/claude/bin/lib/config.sh +148 -3
- package/runtime/claude/bin/lib/context.sh +38 -67
- package/runtime/claude/bin/lib/genui-entry.py +36 -0
- package/runtime/claude/bin/lib/git-message.sh +25 -6
- package/runtime/claude/bin/lib/git-sync.sh +12 -4
- package/runtime/claude/bin/lib/greeting.sh +255 -28
- package/runtime/claude/bin/lib/handoff_meta.py +294 -0
- package/runtime/claude/bin/lib/health-footer.sh +83 -2
- package/runtime/claude/bin/lib/identity.sh +31 -10
- package/runtime/claude/bin/lib/instance-registry.sh +71 -0
- package/runtime/claude/bin/lib/local_ci_receipt.py +249 -0
- package/runtime/claude/bin/lib/metrics.sh +121 -8
- package/runtime/claude/bin/lib/notices.sh +36 -0
- package/runtime/claude/bin/lib/record_outcomes.py +729 -0
- package/runtime/claude/bin/lib/reflexes.py +267 -0
- package/runtime/claude/bin/lib/retrieval_scorecard.py +624 -0
- package/runtime/claude/bin/lib/session-record-prompt.txt +18 -0
- package/runtime/claude/bin/lib/session_record.py +3747 -0
- package/runtime/claude/bin/lib/session_trail.py +1983 -0
- package/runtime/claude/bin/lib/settings-drift.sh +8 -5
- package/runtime/claude/bin/lib/startup-restart.sh +41 -0
- package/runtime/claude/bin/lib/worktree-links.sh +92 -0
- package/runtime/claude/bin/memory-push.sh +6 -0
- package/runtime/claude/bin/merge-gate.sh +498 -0
- package/runtime/claude/bin/notify.sh +5 -2
- package/runtime/claude/bin/page-access.sh +103 -0
- package/runtime/claude/bin/person.sh +13 -2
- package/runtime/claude/bin/pi-render-spec.mjs +0 -1
- package/runtime/claude/bin/pi-spirit-discovery.mjs +34 -0
- package/runtime/claude/bin/post-update.sh +181 -0
- package/runtime/claude/bin/prime-render-spec.mjs +0 -1
- package/runtime/claude/bin/publish-artifact.sh +89 -42
- package/runtime/claude/bin/qa-inventory.sh +2 -2
- package/runtime/claude/bin/quest.sh +1 -1
- package/runtime/claude/bin/records.sh +11 -0
- package/runtime/claude/bin/reflexes/05-vitals.sh +9 -0
- package/runtime/claude/bin/reflexes/10-open-items.sh +12 -0
- package/runtime/claude/bin/reflexes/15-retrieval.sh +8 -0
- package/runtime/claude/bin/reflexes/20-nightly.sh +100 -0
- package/runtime/claude/bin/reflexes/20-sandbox.sh +85 -0
- package/runtime/claude/bin/reflexes/30-cost.py +116 -0
- package/runtime/claude/bin/reflexes/40-shells.py +51 -0
- package/runtime/claude/bin/reflexes/README.md +61 -0
- package/runtime/claude/bin/reflexes.sh +7 -0
- package/runtime/claude/bin/runtime-identity.sh +140 -42
- package/runtime/claude/bin/screenshot.sh +77 -0
- package/runtime/claude/bin/scroll.sh +1 -1
- package/runtime/claude/bin/search.sh +31 -5
- package/runtime/claude/bin/session-autosave.sh +6 -3
- package/runtime/claude/bin/session-id.sh +147 -0
- package/runtime/claude/bin/session-log.sh +19 -0
- package/runtime/claude/bin/session-record.sh +26 -0
- package/runtime/claude/bin/session-start.sh +121 -151
- package/runtime/claude/bin/settings.sh +13 -8
- package/runtime/claude/bin/spirit-discovery-claude.sh +4 -0
- package/runtime/claude/bin/spirit-discovery-codex.sh +4 -0
- package/runtime/claude/bin/spirit-discovery-pi.sh +4 -0
- package/runtime/claude/bin/spirit-discovery-prime.sh +4 -0
- package/runtime/claude/bin/spirit-discovery.sh +4 -0
- package/runtime/claude/bin/startup-check.sh +1 -1
- package/runtime/claude/bin/telemetry.sh +11 -4
- package/runtime/claude/bin/test-baseline.sh +33 -5
- package/runtime/claude/bin/todo.sh +1 -1
- package/runtime/claude/bin/worktree-create.sh +15 -45
- package/runtime/claude/bin/worktree.sh +6 -0
- package/runtime/claude/docs/spirit-discovery.md +96 -0
- package/runtime/claude/egregore_runtime/__init__.py +18 -12
- package/runtime/claude/egregore_runtime/access.py +608 -0
- package/runtime/claude/egregore_runtime/access_cli.py +190 -0
- package/runtime/claude/egregore_runtime/adapters/invitation.py +5 -3
- package/runtime/claude/egregore_runtime/adapters/qmd.py +521 -47
- package/runtime/claude/egregore_runtime/admin_entry.py +56 -0
- package/runtime/claude/egregore_runtime/artifacts.py +222 -16
- package/runtime/claude/egregore_runtime/contracts.py +27 -0
- package/runtime/claude/egregore_runtime/eligibility.py +5 -12
- package/runtime/claude/egregore_runtime/episode_binding.py +16 -5
- package/runtime/claude/egregore_runtime/github_issues.py +2 -2
- package/runtime/claude/egregore_runtime/handoff_lookup.py +9 -20
- package/runtime/claude/egregore_runtime/harness_cli.py +674 -149
- package/runtime/claude/egregore_runtime/held.py +2436 -0
- package/runtime/claude/egregore_runtime/hosted_api.py +137 -0
- package/runtime/claude/egregore_runtime/identity.py +196 -65
- package/runtime/claude/egregore_runtime/identity_transfer.py +6 -2
- package/runtime/claude/egregore_runtime/ingest_cli.py +2 -2
- package/runtime/claude/egregore_runtime/ingest_index_cli.py +4 -16
- package/runtime/claude/egregore_runtime/installation.py +119 -0
- package/runtime/claude/egregore_runtime/investigation.py +64 -41
- package/runtime/claude/egregore_runtime/investigation_guidance.py +16 -11
- package/runtime/claude/egregore_runtime/issue_cli.py +51 -32
- package/runtime/claude/egregore_runtime/issue_reporting.py +4 -3
- package/runtime/claude/egregore_runtime/issue_triage_service.py +2 -2
- package/runtime/claude/egregore_runtime/issues.py +12 -6
- package/runtime/claude/egregore_runtime/knowledge.py +331 -5
- package/runtime/claude/egregore_runtime/knowledge_cli.py +57 -17
- package/runtime/claude/egregore_runtime/lifecycle.py +88 -22
- package/runtime/claude/egregore_runtime/lifecycle_cli.py +21 -13
- package/runtime/claude/egregore_runtime/line_ids.py +10 -0
- package/runtime/claude/egregore_runtime/memory_push.py +349 -0
- package/runtime/claude/egregore_runtime/observe.py +64 -25
- package/runtime/claude/egregore_runtime/observers.py +19 -0
- package/runtime/claude/egregore_runtime/optional_modules.py +13 -0
- package/runtime/claude/egregore_runtime/outputs_cli.py +321 -0
- package/runtime/claude/egregore_runtime/policy.py +651 -24
- package/runtime/claude/egregore_runtime/private_result.py +2 -1
- package/runtime/claude/egregore_runtime/projection.py +946 -0
- package/runtime/claude/egregore_runtime/quest_cli.py +20 -23
- package/runtime/claude/egregore_runtime/question_cli.py +15 -11
- package/runtime/claude/egregore_runtime/questions.py +10 -10
- package/runtime/claude/egregore_runtime/quests.py +10 -10
- package/runtime/claude/egregore_runtime/record_publish.py +548 -0
- package/runtime/claude/egregore_runtime/record_subject.py +564 -0
- package/runtime/claude/egregore_runtime/research_ingest.py +2 -4
- package/runtime/claude/egregore_runtime/runtime.py +169 -60
- package/runtime/claude/egregore_runtime/sandbox.py +194 -0
- package/runtime/claude/egregore_runtime/scroll_cli.py +22 -32
- package/runtime/claude/egregore_runtime/scrolls.py +23 -15
- package/runtime/claude/egregore_runtime/shadow.py +262 -0
- package/runtime/claude/egregore_runtime/spirit_discovery.py +487 -0
- package/runtime/claude/egregore_runtime/spirit_discovery_cli.py +25 -0
- package/runtime/claude/egregore_runtime/spirit_discovery_transport.py +18 -0
- package/runtime/claude/egregore_runtime/status.py +101 -44
- package/runtime/claude/egregore_runtime/status_cli.py +13 -5
- package/runtime/claude/egregore_runtime/sync.py +39 -21
- package/runtime/claude/egregore_runtime/taste.py +934 -0
- package/runtime/claude/egregore_runtime/taste_cli.py +242 -0
- package/runtime/claude/egregore_runtime/taste_rules.py +91 -0
- package/runtime/claude/egregore_runtime/telemetry.py +26 -3
- package/runtime/claude/egregore_runtime/todo_cli.py +15 -12
- package/runtime/claude/egregore_runtime/todos.py +3 -2
- package/runtime/claude/egregore_runtime/upgrade.py +85 -58
- package/runtime/claude/egregore_runtime/writeback.py +330 -24
- package/runtime/claude/manifest.json +65 -5
- package/runtime/codex/.claude/context/handoff-claiming.md +32 -0
- package/runtime/codex/.claude/context/notification-consent.md +12 -9
- package/runtime/codex/.claude/skills/view/SKILL.md +438 -0
- package/runtime/codex/.codex/hooks.json +11 -0
- package/runtime/codex/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/records/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/summon/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/view/assets/compose-scaffold.html +19 -13
- package/runtime/codex/.codex/spec-manifest.json +13 -19
- package/runtime/codex/AGENTS.md +54 -105
- package/runtime/codex/bin/agent.sh +231 -7
- package/runtime/codex/bin/api-call.sh +44 -23
- package/runtime/codex/bin/artifact-register.sh +7 -1
- package/runtime/codex/bin/artifact-writeback.sh +1 -1
- package/runtime/codex/bin/artifacts.sh +66 -265
- package/runtime/codex/bin/attendant.sh +4 -1
- package/runtime/codex/bin/boundary-guard.cjs +1848 -0
- package/runtime/codex/bin/boundary-hook.sh +41 -0
- package/runtime/codex/bin/capture-run.sh +32 -2
- package/runtime/codex/bin/codex-render-spec.mjs +24 -46
- package/runtime/codex/bin/codex-session-start.sh +19 -0
- package/runtime/codex/bin/codex-skill-render.mjs +18 -0
- package/runtime/codex/bin/config-get.sh +10 -1
- package/runtime/codex/bin/connect-refresh.sh +16 -0
- package/runtime/codex/bin/corpus_map.py +5 -0
- package/runtime/codex/bin/data/capabilities/codex.json +1458 -0
- package/runtime/codex/bin/genui.sh +19 -0
- package/runtime/codex/bin/graph-batch.sh +1 -1
- package/runtime/codex/bin/graph-op.sh +14 -0
- package/runtime/codex/bin/graph.sh +1 -1
- package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/codex/bin/handoff-run.sh +11 -6
- package/runtime/codex/bin/ingest-item.sh +1 -1
- package/runtime/codex/bin/ingest-surface.html +22 -4
- package/runtime/codex/bin/issue.sh +1 -1
- package/runtime/codex/bin/knowledge.sh +1 -1
- package/runtime/codex/bin/lib/card-delivery.sh +329 -0
- package/runtime/codex/bin/lib/config.sh +148 -3
- package/runtime/codex/bin/lib/context.sh +38 -67
- package/runtime/codex/bin/lib/genui-entry.py +36 -0
- package/runtime/codex/bin/lib/git-message.sh +25 -6
- package/runtime/codex/bin/lib/git-sync.sh +12 -4
- package/runtime/codex/bin/lib/greeting.sh +255 -28
- package/runtime/codex/bin/lib/handoff_meta.py +294 -0
- package/runtime/codex/bin/lib/health-footer.sh +83 -2
- package/runtime/codex/bin/lib/identity.sh +31 -10
- package/runtime/codex/bin/lib/instance-registry.sh +71 -0
- package/runtime/codex/bin/lib/local_ci_receipt.py +249 -0
- package/runtime/codex/bin/lib/metrics.sh +121 -8
- package/runtime/codex/bin/lib/notices.sh +36 -0
- package/runtime/codex/bin/lib/record_outcomes.py +729 -0
- package/runtime/codex/bin/lib/reflexes.py +267 -0
- package/runtime/codex/bin/lib/retrieval_scorecard.py +624 -0
- package/runtime/codex/bin/lib/session-record-prompt.txt +18 -0
- package/runtime/codex/bin/lib/session_record.py +3747 -0
- package/runtime/codex/bin/lib/session_trail.py +1983 -0
- package/runtime/codex/bin/lib/settings-drift.sh +8 -5
- package/runtime/codex/bin/lib/startup-restart.sh +41 -0
- package/runtime/codex/bin/lib/worktree-links.sh +92 -0
- package/runtime/codex/bin/memory-push.sh +6 -0
- package/runtime/codex/bin/merge-gate.sh +498 -0
- package/runtime/codex/bin/notify.sh +5 -2
- package/runtime/codex/bin/page-access.sh +103 -0
- package/runtime/codex/bin/person.sh +13 -2
- package/runtime/codex/bin/pi-render-spec.mjs +0 -1
- package/runtime/codex/bin/pi-spirit-discovery.mjs +34 -0
- package/runtime/codex/bin/post-update.sh +181 -0
- package/runtime/codex/bin/prime-render-spec.mjs +0 -1
- package/runtime/codex/bin/publish-artifact.sh +89 -42
- package/runtime/codex/bin/qa-inventory.sh +2 -2
- package/runtime/codex/bin/quest.sh +1 -1
- package/runtime/codex/bin/records.sh +11 -0
- package/runtime/codex/bin/reflexes/05-vitals.sh +9 -0
- package/runtime/codex/bin/reflexes/10-open-items.sh +12 -0
- package/runtime/codex/bin/reflexes/15-retrieval.sh +8 -0
- package/runtime/codex/bin/reflexes/20-nightly.sh +100 -0
- package/runtime/codex/bin/reflexes/20-sandbox.sh +85 -0
- package/runtime/codex/bin/reflexes/30-cost.py +116 -0
- package/runtime/codex/bin/reflexes/40-shells.py +51 -0
- package/runtime/codex/bin/reflexes/README.md +61 -0
- package/runtime/codex/bin/reflexes.sh +7 -0
- package/runtime/codex/bin/runtime-identity.sh +140 -42
- package/runtime/codex/bin/screenshot.sh +77 -0
- package/runtime/codex/bin/scroll.sh +1 -1
- package/runtime/codex/bin/search.sh +31 -5
- package/runtime/codex/bin/session-autosave.sh +6 -3
- package/runtime/codex/bin/session-id.sh +147 -0
- package/runtime/codex/bin/session-log.sh +19 -0
- package/runtime/codex/bin/session-record.sh +26 -0
- package/runtime/codex/bin/settings.sh +13 -8
- package/runtime/codex/bin/spirit-discovery-claude.sh +4 -0
- package/runtime/codex/bin/spirit-discovery-codex.sh +4 -0
- package/runtime/codex/bin/spirit-discovery-pi.sh +4 -0
- package/runtime/codex/bin/spirit-discovery-prime.sh +4 -0
- package/runtime/codex/bin/spirit-discovery.sh +4 -0
- package/runtime/codex/bin/startup-check.sh +1 -1
- package/runtime/codex/bin/telemetry.sh +11 -4
- package/runtime/codex/bin/test-baseline.sh +33 -5
- package/runtime/codex/bin/todo.sh +1 -1
- package/runtime/codex/bin/worktree-create.sh +15 -45
- package/runtime/codex/bin/worktree.sh +6 -0
- package/runtime/codex/docs/spirit-discovery.md +96 -0
- package/runtime/codex/egregore_runtime/__init__.py +18 -12
- package/runtime/codex/egregore_runtime/access.py +608 -0
- package/runtime/codex/egregore_runtime/access_cli.py +190 -0
- package/runtime/codex/egregore_runtime/adapters/invitation.py +5 -3
- package/runtime/codex/egregore_runtime/adapters/qmd.py +521 -47
- package/runtime/codex/egregore_runtime/admin_entry.py +56 -0
- package/runtime/codex/egregore_runtime/artifacts.py +222 -16
- package/runtime/codex/egregore_runtime/contracts.py +27 -0
- package/runtime/codex/egregore_runtime/eligibility.py +5 -12
- package/runtime/codex/egregore_runtime/episode_binding.py +16 -5
- package/runtime/codex/egregore_runtime/github_issues.py +2 -2
- package/runtime/codex/egregore_runtime/handoff_lookup.py +9 -20
- package/runtime/codex/egregore_runtime/harness_cli.py +674 -149
- package/runtime/codex/egregore_runtime/held.py +2436 -0
- package/runtime/codex/egregore_runtime/hosted_api.py +137 -0
- package/runtime/codex/egregore_runtime/identity.py +196 -65
- package/runtime/codex/egregore_runtime/identity_transfer.py +6 -2
- package/runtime/codex/egregore_runtime/ingest_cli.py +2 -2
- package/runtime/codex/egregore_runtime/ingest_index_cli.py +4 -16
- package/runtime/codex/egregore_runtime/installation.py +119 -0
- package/runtime/codex/egregore_runtime/investigation.py +64 -41
- package/runtime/codex/egregore_runtime/investigation_guidance.py +16 -11
- package/runtime/codex/egregore_runtime/issue_cli.py +51 -32
- package/runtime/codex/egregore_runtime/issue_reporting.py +4 -3
- package/runtime/codex/egregore_runtime/issue_triage_service.py +2 -2
- package/runtime/codex/egregore_runtime/issues.py +12 -6
- package/runtime/codex/egregore_runtime/knowledge.py +331 -5
- package/runtime/codex/egregore_runtime/knowledge_cli.py +57 -17
- package/runtime/codex/egregore_runtime/lifecycle.py +88 -22
- package/runtime/codex/egregore_runtime/lifecycle_cli.py +21 -13
- package/runtime/codex/egregore_runtime/line_ids.py +10 -0
- package/runtime/codex/egregore_runtime/memory_push.py +349 -0
- package/runtime/codex/egregore_runtime/observe.py +64 -25
- package/runtime/codex/egregore_runtime/observers.py +19 -0
- package/runtime/codex/egregore_runtime/optional_modules.py +13 -0
- package/runtime/codex/egregore_runtime/outputs_cli.py +321 -0
- package/runtime/codex/egregore_runtime/policy.py +651 -24
- package/runtime/codex/egregore_runtime/private_result.py +2 -1
- package/runtime/codex/egregore_runtime/projection.py +946 -0
- package/runtime/codex/egregore_runtime/quest_cli.py +20 -23
- package/runtime/codex/egregore_runtime/question_cli.py +15 -11
- package/runtime/codex/egregore_runtime/questions.py +10 -10
- package/runtime/codex/egregore_runtime/quests.py +10 -10
- package/runtime/codex/egregore_runtime/record_publish.py +548 -0
- package/runtime/codex/egregore_runtime/record_subject.py +564 -0
- package/runtime/codex/egregore_runtime/research_ingest.py +2 -4
- package/runtime/codex/egregore_runtime/runtime.py +169 -60
- package/runtime/codex/egregore_runtime/sandbox.py +194 -0
- package/runtime/codex/egregore_runtime/scroll_cli.py +22 -32
- package/runtime/codex/egregore_runtime/scrolls.py +23 -15
- package/runtime/codex/egregore_runtime/shadow.py +262 -0
- package/runtime/codex/egregore_runtime/spirit_discovery.py +487 -0
- package/runtime/codex/egregore_runtime/spirit_discovery_cli.py +25 -0
- package/runtime/codex/egregore_runtime/spirit_discovery_transport.py +18 -0
- package/runtime/codex/egregore_runtime/status.py +101 -44
- package/runtime/codex/egregore_runtime/status_cli.py +13 -5
- package/runtime/codex/egregore_runtime/sync.py +39 -21
- package/runtime/codex/egregore_runtime/taste.py +934 -0
- package/runtime/codex/egregore_runtime/taste_cli.py +242 -0
- package/runtime/codex/egregore_runtime/taste_rules.py +91 -0
- package/runtime/codex/egregore_runtime/telemetry.py +26 -3
- package/runtime/codex/egregore_runtime/todo_cli.py +15 -12
- package/runtime/codex/egregore_runtime/todos.py +3 -2
- package/runtime/codex/egregore_runtime/upgrade.py +85 -58
- package/runtime/codex/egregore_runtime/writeback.py +330 -24
- package/runtime/codex/manifest.json +66 -5
- package/runtime/pi/.claude/context/handoff-claiming.md +32 -0
- package/runtime/pi/.claude/context/notification-consent.md +12 -9
- package/runtime/pi/.claude/skills/view/SKILL.md +438 -0
- package/runtime/pi/.codex/hooks.json +11 -0
- package/runtime/pi/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/records/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/summon/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +19 -13
- package/runtime/pi/.codex/spec-manifest.json +13 -19
- package/runtime/pi/.pi/APPEND_SYSTEM.md +53 -99
- package/runtime/pi/.pi/extensions/egregore.ts +13 -1
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +54 -105
- package/runtime/pi/bin/agent.sh +231 -7
- package/runtime/pi/bin/api-call.sh +44 -23
- package/runtime/pi/bin/artifact-register.sh +7 -1
- package/runtime/pi/bin/artifact-writeback.sh +1 -1
- package/runtime/pi/bin/artifacts.sh +66 -265
- package/runtime/pi/bin/attendant.sh +4 -1
- package/runtime/pi/bin/boundary-guard.cjs +1848 -0
- package/runtime/pi/bin/boundary-hook.sh +41 -0
- package/runtime/pi/bin/capture-run.sh +32 -2
- package/runtime/pi/bin/codex-render-spec.mjs +24 -46
- package/runtime/pi/bin/codex-session-start.sh +19 -0
- package/runtime/pi/bin/codex-skill-render.mjs +18 -0
- package/runtime/pi/bin/config-get.sh +10 -1
- package/runtime/pi/bin/connect-refresh.sh +16 -0
- package/runtime/pi/bin/corpus_map.py +5 -0
- package/runtime/pi/bin/data/capabilities/pi.json +1458 -0
- package/runtime/pi/bin/genui.sh +19 -0
- package/runtime/pi/bin/graph-batch.sh +1 -1
- package/runtime/pi/bin/graph-op.sh +14 -0
- package/runtime/pi/bin/graph.sh +1 -1
- package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/pi/bin/handoff-run.sh +11 -6
- package/runtime/pi/bin/ingest-item.sh +1 -1
- package/runtime/pi/bin/ingest-surface.html +22 -4
- package/runtime/pi/bin/issue.sh +1 -1
- package/runtime/pi/bin/knowledge.sh +1 -1
- package/runtime/pi/bin/lib/card-delivery.sh +329 -0
- package/runtime/pi/bin/lib/config.sh +148 -3
- package/runtime/pi/bin/lib/context.sh +38 -67
- package/runtime/pi/bin/lib/genui-entry.py +36 -0
- package/runtime/pi/bin/lib/git-message.sh +25 -6
- package/runtime/pi/bin/lib/git-sync.sh +12 -4
- package/runtime/pi/bin/lib/greeting.sh +255 -28
- package/runtime/pi/bin/lib/handoff_meta.py +294 -0
- package/runtime/pi/bin/lib/health-footer.sh +83 -2
- package/runtime/pi/bin/lib/identity.sh +31 -10
- package/runtime/pi/bin/lib/instance-registry.sh +71 -0
- package/runtime/pi/bin/lib/local_ci_receipt.py +249 -0
- package/runtime/pi/bin/lib/metrics.sh +121 -8
- package/runtime/pi/bin/lib/notices.sh +36 -0
- package/runtime/pi/bin/lib/record_outcomes.py +729 -0
- package/runtime/pi/bin/lib/reflexes.py +267 -0
- package/runtime/pi/bin/lib/retrieval_scorecard.py +624 -0
- package/runtime/pi/bin/lib/session-record-prompt.txt +18 -0
- package/runtime/pi/bin/lib/session_record.py +3747 -0
- package/runtime/pi/bin/lib/session_trail.py +1983 -0
- package/runtime/pi/bin/lib/settings-drift.sh +8 -5
- package/runtime/pi/bin/lib/startup-restart.sh +41 -0
- package/runtime/pi/bin/lib/worktree-links.sh +92 -0
- package/runtime/pi/bin/memory-push.sh +6 -0
- package/runtime/pi/bin/merge-gate.sh +498 -0
- package/runtime/pi/bin/notify.sh +5 -2
- package/runtime/pi/bin/page-access.sh +103 -0
- package/runtime/pi/bin/person.sh +13 -2
- package/runtime/pi/bin/pi-branch-policy.mjs +37 -0
- package/runtime/pi/bin/pi-observe-context.mjs +97 -4
- package/runtime/pi/bin/pi-render-spec.mjs +0 -1
- package/runtime/pi/bin/pi-session-start.sh +4 -1
- package/runtime/pi/bin/pi-spirit-discovery.mjs +34 -0
- package/runtime/pi/bin/post-update.sh +181 -0
- package/runtime/pi/bin/prime-render-spec.mjs +0 -1
- package/runtime/pi/bin/publish-artifact.sh +89 -42
- package/runtime/pi/bin/qa-inventory.sh +2 -2
- package/runtime/pi/bin/quest.sh +1 -1
- package/runtime/pi/bin/records.sh +11 -0
- package/runtime/pi/bin/reflexes/05-vitals.sh +9 -0
- package/runtime/pi/bin/reflexes/10-open-items.sh +12 -0
- package/runtime/pi/bin/reflexes/15-retrieval.sh +8 -0
- package/runtime/pi/bin/reflexes/20-nightly.sh +100 -0
- package/runtime/pi/bin/reflexes/20-sandbox.sh +85 -0
- package/runtime/pi/bin/reflexes/30-cost.py +116 -0
- package/runtime/pi/bin/reflexes/40-shells.py +51 -0
- package/runtime/pi/bin/reflexes/README.md +61 -0
- package/runtime/pi/bin/reflexes.sh +7 -0
- package/runtime/pi/bin/runtime-identity.sh +140 -42
- package/runtime/pi/bin/screenshot.sh +77 -0
- package/runtime/pi/bin/scroll.sh +1 -1
- package/runtime/pi/bin/search.sh +31 -5
- package/runtime/pi/bin/session-autosave.sh +6 -3
- package/runtime/pi/bin/session-id.sh +147 -0
- package/runtime/pi/bin/session-log.sh +19 -0
- package/runtime/pi/bin/session-record.sh +26 -0
- package/runtime/pi/bin/settings.sh +13 -8
- package/runtime/pi/bin/spirit-discovery-claude.sh +4 -0
- package/runtime/pi/bin/spirit-discovery-codex.sh +4 -0
- package/runtime/pi/bin/spirit-discovery-pi.sh +4 -0
- package/runtime/pi/bin/spirit-discovery-prime.sh +4 -0
- package/runtime/pi/bin/spirit-discovery.sh +4 -0
- package/runtime/pi/bin/startup-check.sh +1 -1
- package/runtime/pi/bin/telemetry.sh +11 -4
- package/runtime/pi/bin/test-baseline.sh +33 -5
- package/runtime/pi/bin/todo.sh +1 -1
- package/runtime/pi/bin/worktree-create.sh +15 -45
- package/runtime/pi/bin/worktree.sh +6 -0
- package/runtime/pi/docs/spirit-discovery.md +96 -0
- package/runtime/pi/egregore_runtime/__init__.py +18 -12
- package/runtime/pi/egregore_runtime/access.py +608 -0
- package/runtime/pi/egregore_runtime/access_cli.py +190 -0
- package/runtime/pi/egregore_runtime/adapters/invitation.py +5 -3
- package/runtime/pi/egregore_runtime/adapters/qmd.py +521 -47
- package/runtime/pi/egregore_runtime/admin_entry.py +56 -0
- package/runtime/pi/egregore_runtime/artifacts.py +222 -16
- package/runtime/pi/egregore_runtime/contracts.py +27 -0
- package/runtime/pi/egregore_runtime/eligibility.py +5 -12
- package/runtime/pi/egregore_runtime/episode_binding.py +16 -5
- package/runtime/pi/egregore_runtime/github_issues.py +2 -2
- package/runtime/pi/egregore_runtime/handoff_lookup.py +9 -20
- package/runtime/pi/egregore_runtime/harness_cli.py +674 -149
- package/runtime/pi/egregore_runtime/held.py +2436 -0
- package/runtime/pi/egregore_runtime/hosted_api.py +137 -0
- package/runtime/pi/egregore_runtime/identity.py +196 -65
- package/runtime/pi/egregore_runtime/identity_transfer.py +6 -2
- package/runtime/pi/egregore_runtime/ingest_cli.py +2 -2
- package/runtime/pi/egregore_runtime/ingest_index_cli.py +4 -16
- package/runtime/pi/egregore_runtime/installation.py +119 -0
- package/runtime/pi/egregore_runtime/investigation.py +64 -41
- package/runtime/pi/egregore_runtime/investigation_guidance.py +16 -11
- package/runtime/pi/egregore_runtime/issue_cli.py +51 -32
- package/runtime/pi/egregore_runtime/issue_reporting.py +4 -3
- package/runtime/pi/egregore_runtime/issue_triage_service.py +2 -2
- package/runtime/pi/egregore_runtime/issues.py +12 -6
- package/runtime/pi/egregore_runtime/knowledge.py +331 -5
- package/runtime/pi/egregore_runtime/knowledge_cli.py +57 -17
- package/runtime/pi/egregore_runtime/lifecycle.py +88 -22
- package/runtime/pi/egregore_runtime/lifecycle_cli.py +21 -13
- package/runtime/pi/egregore_runtime/line_ids.py +10 -0
- package/runtime/pi/egregore_runtime/memory_push.py +349 -0
- package/runtime/pi/egregore_runtime/observe.py +64 -25
- package/runtime/pi/egregore_runtime/observers.py +19 -0
- package/runtime/pi/egregore_runtime/optional_modules.py +13 -0
- package/runtime/pi/egregore_runtime/outputs_cli.py +321 -0
- package/runtime/pi/egregore_runtime/policy.py +651 -24
- package/runtime/pi/egregore_runtime/private_result.py +2 -1
- package/runtime/pi/egregore_runtime/projection.py +946 -0
- package/runtime/pi/egregore_runtime/quest_cli.py +20 -23
- package/runtime/pi/egregore_runtime/question_cli.py +15 -11
- package/runtime/pi/egregore_runtime/questions.py +10 -10
- package/runtime/pi/egregore_runtime/quests.py +10 -10
- package/runtime/pi/egregore_runtime/record_publish.py +548 -0
- package/runtime/pi/egregore_runtime/record_subject.py +564 -0
- package/runtime/pi/egregore_runtime/research_ingest.py +2 -4
- package/runtime/pi/egregore_runtime/runtime.py +169 -60
- package/runtime/pi/egregore_runtime/sandbox.py +194 -0
- package/runtime/pi/egregore_runtime/scroll_cli.py +22 -32
- package/runtime/pi/egregore_runtime/scrolls.py +23 -15
- package/runtime/pi/egregore_runtime/shadow.py +262 -0
- package/runtime/pi/egregore_runtime/spirit_discovery.py +487 -0
- package/runtime/pi/egregore_runtime/spirit_discovery_cli.py +25 -0
- package/runtime/pi/egregore_runtime/spirit_discovery_transport.py +18 -0
- package/runtime/pi/egregore_runtime/status.py +101 -44
- package/runtime/pi/egregore_runtime/status_cli.py +13 -5
- package/runtime/pi/egregore_runtime/sync.py +39 -21
- package/runtime/pi/egregore_runtime/taste.py +934 -0
- package/runtime/pi/egregore_runtime/taste_cli.py +242 -0
- package/runtime/pi/egregore_runtime/taste_rules.py +91 -0
- package/runtime/pi/egregore_runtime/telemetry.py +26 -3
- package/runtime/pi/egregore_runtime/todo_cli.py +15 -12
- package/runtime/pi/egregore_runtime/todos.py +3 -2
- package/runtime/pi/egregore_runtime/upgrade.py +85 -58
- package/runtime/pi/egregore_runtime/writeback.py +330 -24
- package/runtime/pi/manifest.json +66 -5
- package/runtime/prime/.claude/context/handoff-claiming.md +32 -0
- package/runtime/prime/.claude/context/notification-consent.md +12 -9
- package/runtime/prime/.claude/skills/view/SKILL.md +438 -0
- package/runtime/prime/.codex/hooks.json +11 -0
- package/runtime/prime/.codex/skills/dark-mode/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/records/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/summon/SKILL.md +1 -1
- package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +19 -13
- package/runtime/prime/.codex/spec-manifest.json +13 -19
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +53 -99
- package/runtime/prime/.prime/agent/extensions/egregore.ts +14 -1
- package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +14 -6
- package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +66 -1
- package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
- package/runtime/prime/AGENTS.md +54 -105
- package/runtime/prime/bin/agent.sh +231 -7
- package/runtime/prime/bin/api-call.sh +44 -23
- package/runtime/prime/bin/artifact-register.sh +7 -1
- package/runtime/prime/bin/artifact-writeback.sh +1 -1
- package/runtime/prime/bin/artifacts.sh +66 -265
- package/runtime/prime/bin/attendant.sh +4 -1
- package/runtime/prime/bin/boundary-guard.cjs +1848 -0
- package/runtime/prime/bin/boundary-hook.sh +41 -0
- package/runtime/prime/bin/capture-run.sh +32 -2
- package/runtime/prime/bin/codex-render-spec.mjs +24 -46
- package/runtime/prime/bin/codex-session-start.sh +19 -0
- package/runtime/prime/bin/codex-skill-render.mjs +18 -0
- package/runtime/prime/bin/config-get.sh +10 -1
- package/runtime/prime/bin/connect-refresh.sh +16 -0
- package/runtime/prime/bin/corpus_map.py +5 -0
- package/runtime/prime/bin/data/capabilities/prime.json +1458 -0
- package/runtime/prime/bin/genui.sh +19 -0
- package/runtime/prime/bin/graph-batch.sh +1 -1
- package/runtime/prime/bin/graph-op.sh +14 -0
- package/runtime/prime/bin/graph.sh +1 -1
- package/runtime/prime/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/prime/bin/handoff-run.sh +11 -6
- package/runtime/prime/bin/ingest-item.sh +1 -1
- package/runtime/prime/bin/ingest-surface.html +22 -4
- package/runtime/prime/bin/issue.sh +1 -1
- package/runtime/prime/bin/knowledge.sh +1 -1
- package/runtime/prime/bin/lib/card-delivery.sh +329 -0
- package/runtime/prime/bin/lib/config.sh +148 -3
- package/runtime/prime/bin/lib/context.sh +38 -67
- package/runtime/prime/bin/lib/genui-entry.py +36 -0
- package/runtime/prime/bin/lib/git-message.sh +25 -6
- package/runtime/prime/bin/lib/git-sync.sh +12 -4
- package/runtime/prime/bin/lib/greeting.sh +255 -28
- package/runtime/prime/bin/lib/handoff_meta.py +294 -0
- package/runtime/prime/bin/lib/health-footer.sh +83 -2
- package/runtime/prime/bin/lib/identity.sh +31 -10
- package/runtime/prime/bin/lib/instance-registry.sh +71 -0
- package/runtime/prime/bin/lib/local_ci_receipt.py +249 -0
- package/runtime/prime/bin/lib/metrics.sh +121 -8
- package/runtime/prime/bin/lib/notices.sh +36 -0
- package/runtime/prime/bin/lib/record_outcomes.py +729 -0
- package/runtime/prime/bin/lib/reflexes.py +267 -0
- package/runtime/prime/bin/lib/retrieval_scorecard.py +624 -0
- package/runtime/prime/bin/lib/session-record-prompt.txt +18 -0
- package/runtime/prime/bin/lib/session_record.py +3747 -0
- package/runtime/prime/bin/lib/session_trail.py +1983 -0
- package/runtime/prime/bin/lib/settings-drift.sh +8 -5
- package/runtime/prime/bin/lib/startup-restart.sh +41 -0
- package/runtime/prime/bin/lib/worktree-links.sh +92 -0
- package/runtime/prime/bin/memory-push.sh +6 -0
- package/runtime/prime/bin/merge-gate.sh +498 -0
- package/runtime/prime/bin/notify.sh +5 -2
- package/runtime/prime/bin/page-access.sh +103 -0
- package/runtime/prime/bin/person.sh +13 -2
- package/runtime/prime/bin/pi-branch-policy.mjs +37 -0
- package/runtime/prime/bin/pi-observe-context.mjs +97 -4
- package/runtime/prime/bin/pi-render-spec.mjs +0 -1
- package/runtime/prime/bin/pi-spirit-discovery.mjs +34 -0
- package/runtime/prime/bin/post-update.sh +181 -0
- package/runtime/prime/bin/prime-render-spec.mjs +0 -1
- package/runtime/prime/bin/prime-session-start.sh +3 -1
- package/runtime/prime/bin/publish-artifact.sh +89 -42
- package/runtime/prime/bin/qa-inventory.sh +2 -2
- package/runtime/prime/bin/quest.sh +1 -1
- package/runtime/prime/bin/records.sh +11 -0
- package/runtime/prime/bin/reflexes/05-vitals.sh +9 -0
- package/runtime/prime/bin/reflexes/10-open-items.sh +12 -0
- package/runtime/prime/bin/reflexes/15-retrieval.sh +8 -0
- package/runtime/prime/bin/reflexes/20-nightly.sh +100 -0
- package/runtime/prime/bin/reflexes/20-sandbox.sh +85 -0
- package/runtime/prime/bin/reflexes/30-cost.py +116 -0
- package/runtime/prime/bin/reflexes/40-shells.py +51 -0
- package/runtime/prime/bin/reflexes/README.md +61 -0
- package/runtime/prime/bin/reflexes.sh +7 -0
- package/runtime/prime/bin/runtime-identity.sh +140 -42
- package/runtime/prime/bin/screenshot.sh +77 -0
- package/runtime/prime/bin/scroll.sh +1 -1
- package/runtime/prime/bin/search.sh +31 -5
- package/runtime/prime/bin/session-autosave.sh +6 -3
- package/runtime/prime/bin/session-id.sh +147 -0
- package/runtime/prime/bin/session-log.sh +19 -0
- package/runtime/prime/bin/session-record.sh +26 -0
- package/runtime/prime/bin/settings.sh +13 -8
- package/runtime/prime/bin/spirit-discovery-claude.sh +4 -0
- package/runtime/prime/bin/spirit-discovery-codex.sh +4 -0
- package/runtime/prime/bin/spirit-discovery-pi.sh +4 -0
- package/runtime/prime/bin/spirit-discovery-prime.sh +4 -0
- package/runtime/prime/bin/spirit-discovery.sh +4 -0
- package/runtime/prime/bin/startup-check.sh +1 -1
- package/runtime/prime/bin/telemetry.sh +11 -4
- package/runtime/prime/bin/test-baseline.sh +33 -5
- package/runtime/prime/bin/todo.sh +1 -1
- package/runtime/prime/bin/worktree-create.sh +15 -45
- package/runtime/prime/bin/worktree.sh +6 -0
- package/runtime/prime/docs/spirit-discovery.md +96 -0
- package/runtime/prime/egregore_runtime/__init__.py +18 -12
- package/runtime/prime/egregore_runtime/access.py +608 -0
- package/runtime/prime/egregore_runtime/access_cli.py +190 -0
- package/runtime/prime/egregore_runtime/adapters/invitation.py +5 -3
- package/runtime/prime/egregore_runtime/adapters/qmd.py +521 -47
- package/runtime/prime/egregore_runtime/admin_entry.py +56 -0
- package/runtime/prime/egregore_runtime/artifacts.py +222 -16
- package/runtime/prime/egregore_runtime/contracts.py +27 -0
- package/runtime/prime/egregore_runtime/eligibility.py +5 -12
- package/runtime/prime/egregore_runtime/episode_binding.py +16 -5
- package/runtime/prime/egregore_runtime/github_issues.py +2 -2
- package/runtime/prime/egregore_runtime/handoff_lookup.py +9 -20
- package/runtime/prime/egregore_runtime/harness_cli.py +674 -149
- package/runtime/prime/egregore_runtime/held.py +2436 -0
- package/runtime/prime/egregore_runtime/hosted_api.py +137 -0
- package/runtime/prime/egregore_runtime/identity.py +196 -65
- package/runtime/prime/egregore_runtime/identity_transfer.py +6 -2
- package/runtime/prime/egregore_runtime/ingest_cli.py +2 -2
- package/runtime/prime/egregore_runtime/ingest_index_cli.py +4 -16
- package/runtime/prime/egregore_runtime/installation.py +119 -0
- package/runtime/prime/egregore_runtime/investigation.py +64 -41
- package/runtime/prime/egregore_runtime/investigation_guidance.py +16 -11
- package/runtime/prime/egregore_runtime/issue_cli.py +51 -32
- package/runtime/prime/egregore_runtime/issue_reporting.py +4 -3
- package/runtime/prime/egregore_runtime/issue_triage_service.py +2 -2
- package/runtime/prime/egregore_runtime/issues.py +12 -6
- package/runtime/prime/egregore_runtime/knowledge.py +331 -5
- package/runtime/prime/egregore_runtime/knowledge_cli.py +57 -17
- package/runtime/prime/egregore_runtime/lifecycle.py +88 -22
- package/runtime/prime/egregore_runtime/lifecycle_cli.py +21 -13
- package/runtime/prime/egregore_runtime/line_ids.py +10 -0
- package/runtime/prime/egregore_runtime/memory_push.py +349 -0
- package/runtime/prime/egregore_runtime/observe.py +64 -25
- package/runtime/prime/egregore_runtime/observers.py +19 -0
- package/runtime/prime/egregore_runtime/optional_modules.py +13 -0
- package/runtime/prime/egregore_runtime/outputs_cli.py +321 -0
- package/runtime/prime/egregore_runtime/policy.py +651 -24
- package/runtime/prime/egregore_runtime/private_result.py +2 -1
- package/runtime/prime/egregore_runtime/projection.py +946 -0
- package/runtime/prime/egregore_runtime/quest_cli.py +20 -23
- package/runtime/prime/egregore_runtime/question_cli.py +15 -11
- package/runtime/prime/egregore_runtime/questions.py +10 -10
- package/runtime/prime/egregore_runtime/quests.py +10 -10
- package/runtime/prime/egregore_runtime/record_publish.py +548 -0
- package/runtime/prime/egregore_runtime/record_subject.py +564 -0
- package/runtime/prime/egregore_runtime/research_ingest.py +2 -4
- package/runtime/prime/egregore_runtime/runtime.py +169 -60
- package/runtime/prime/egregore_runtime/sandbox.py +194 -0
- package/runtime/prime/egregore_runtime/scroll_cli.py +22 -32
- package/runtime/prime/egregore_runtime/scrolls.py +23 -15
- package/runtime/prime/egregore_runtime/shadow.py +262 -0
- package/runtime/prime/egregore_runtime/spirit_discovery.py +487 -0
- package/runtime/prime/egregore_runtime/spirit_discovery_cli.py +25 -0
- package/runtime/prime/egregore_runtime/spirit_discovery_transport.py +18 -0
- package/runtime/prime/egregore_runtime/status.py +101 -44
- package/runtime/prime/egregore_runtime/status_cli.py +13 -5
- package/runtime/prime/egregore_runtime/sync.py +39 -21
- package/runtime/prime/egregore_runtime/taste.py +934 -0
- package/runtime/prime/egregore_runtime/taste_cli.py +242 -0
- package/runtime/prime/egregore_runtime/taste_rules.py +91 -0
- package/runtime/prime/egregore_runtime/telemetry.py +26 -3
- package/runtime/prime/egregore_runtime/todo_cli.py +15 -12
- package/runtime/prime/egregore_runtime/todos.py +3 -2
- package/runtime/prime/egregore_runtime/upgrade.py +85 -58
- package/runtime/prime/egregore_runtime/writeback.py +330 -24
- package/runtime/prime/manifest.json +66 -5
- package/runtime/claude/bin/thread.sh +0 -9
- package/runtime/claude/egregore_runtime/admin_gate.py +0 -102
- package/runtime/claude/egregore_runtime/thread_cli.py +0 -173
- package/runtime/claude/egregore_runtime/threads.py +0 -521
- package/runtime/codex/bin/thread.sh +0 -9
- package/runtime/codex/egregore_runtime/admin_gate.py +0 -102
- package/runtime/codex/egregore_runtime/thread_cli.py +0 -173
- package/runtime/codex/egregore_runtime/threads.py +0 -521
- package/runtime/pi/bin/thread.sh +0 -9
- package/runtime/pi/egregore_runtime/admin_gate.py +0 -102
- package/runtime/pi/egregore_runtime/thread_cli.py +0 -173
- package/runtime/pi/egregore_runtime/threads.py +0 -521
- package/runtime/prime/bin/thread.sh +0 -9
- package/runtime/prime/egregore_runtime/admin_gate.py +0 -102
- package/runtime/prime/egregore_runtime/thread_cli.py +0 -173
- package/runtime/prime/egregore_runtime/threads.py +0 -521
|
@@ -8,18 +8,19 @@ knowledge artifact.
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
-
from dataclasses import dataclass
|
|
11
|
+
from dataclasses import dataclass, replace
|
|
12
12
|
from datetime import UTC, datetime
|
|
13
13
|
import json
|
|
14
14
|
import os
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
import re
|
|
17
|
-
from typing import Callable, Iterable
|
|
17
|
+
from typing import Any, Callable, Iterable, Iterator, Mapping
|
|
18
18
|
|
|
19
19
|
from .artifacts import (
|
|
20
20
|
ARTIFACT_SCHEMA_VERSION,
|
|
21
21
|
CanonicalDocument,
|
|
22
22
|
artifact_id_from_path,
|
|
23
|
+
canonical_artifact_id,
|
|
23
24
|
content_digest,
|
|
24
25
|
normalize_markdown_body,
|
|
25
26
|
split_frontmatter,
|
|
@@ -32,8 +33,9 @@ from .contracts import (
|
|
|
32
33
|
SourceProvenance,
|
|
33
34
|
WritebackEvent,
|
|
34
35
|
)
|
|
36
|
+
from . import held
|
|
35
37
|
from .errors import AuthorizationDenied
|
|
36
|
-
from .policy import
|
|
38
|
+
from .policy import allows, check, action_for
|
|
37
39
|
from .runtime import EgregoreRuntime
|
|
38
40
|
|
|
39
41
|
|
|
@@ -41,6 +43,11 @@ KNOWLEDGE_SCHEMA_VERSION = "egregore-knowledge/v1"
|
|
|
41
43
|
PRIVATE_NOTE_SCHEMA_VERSION = "egregore-private-note/v1"
|
|
42
44
|
KNOWLEDGE_TYPES = frozenset({"decision", "finding", "pattern"})
|
|
43
45
|
NOTE_TYPES = frozenset({"thought", "session", "retrospective", "journal"})
|
|
46
|
+
# Knowledge has two linked layers: a pattern states a general motif, and an
|
|
47
|
+
# evidence record (a finding with subtype ``evidence``) keeps the specific,
|
|
48
|
+
# dated, sourced case and points at its pattern with ``instance-of``.
|
|
49
|
+
RELATIONSHIP_VOCABULARY = ("instance-of", "responds-to", "applies", "supersedes", "relates-to")
|
|
50
|
+
SITUATION_KEYS = ("domains", "paths", "activities")
|
|
44
51
|
|
|
45
52
|
|
|
46
53
|
class KnowledgeCaptureError(ValueError):
|
|
@@ -56,6 +63,165 @@ def _iso(value: datetime) -> str:
|
|
|
56
63
|
return value.astimezone(UTC).isoformat().replace("+00:00", "Z")
|
|
57
64
|
|
|
58
65
|
|
|
66
|
+
def relationship_warnings(relationships: Iterable[ArtifactRelationship]) -> tuple[str, ...]:
|
|
67
|
+
"""Unknown relations are kept as written and reported, never rejected."""
|
|
68
|
+
|
|
69
|
+
known = ", ".join(RELATIONSHIP_VOCABULARY)
|
|
70
|
+
return tuple(
|
|
71
|
+
f"relationship '{row.relation}' is not in the vocabulary ({known}); kept as written"
|
|
72
|
+
for row in relationships
|
|
73
|
+
if row.relation.strip().casefold() not in RELATIONSHIP_VOCABULARY
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def normalize_situations(value: Mapping[str, Iterable[str]] | None) -> dict[str, list[str]]:
|
|
78
|
+
"""Return ``{domains, paths, activities}`` or ``{}`` when nothing is given."""
|
|
79
|
+
|
|
80
|
+
if not value:
|
|
81
|
+
return {}
|
|
82
|
+
unknown = sorted(set(value) - set(SITUATION_KEYS))
|
|
83
|
+
if unknown:
|
|
84
|
+
raise KnowledgeCaptureError(f"unknown situation keys: {', '.join(unknown)}")
|
|
85
|
+
result = {
|
|
86
|
+
key: list(dict.fromkeys(" ".join(str(item).split()) for item in value.get(key, ()) if str(item).strip()))
|
|
87
|
+
for key in SITUATION_KEYS
|
|
88
|
+
}
|
|
89
|
+
for glob in result["paths"]:
|
|
90
|
+
if glob.startswith("/") or ".." in glob.split("/"):
|
|
91
|
+
raise KnowledgeCaptureError("situation paths are repository-relative globs")
|
|
92
|
+
return result if any(result.values()) else {}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _relations(fields: Mapping[str, Any]) -> Iterator[tuple[str, str]]:
|
|
96
|
+
value = fields.get("relationships")
|
|
97
|
+
for item in value if isinstance(value, list) else ():
|
|
98
|
+
if isinstance(item, Mapping):
|
|
99
|
+
relation = str(item.get("relation") or item.get("type") or "")
|
|
100
|
+
target = str(item.get("target_id") or item.get("target") or item.get("id") or "")
|
|
101
|
+
if relation and target:
|
|
102
|
+
yield relation.strip().casefold(), target.strip()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _relative(value: str) -> str:
|
|
106
|
+
return value.strip().replace("\\", "/").removeprefix("memory/")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Situated patterns: a deterministic match of a pattern's situations against
|
|
110
|
+
# the paths someone is changing and the words they use. No model calls.
|
|
111
|
+
SITUATED_HINT_PREFIX = "Patterns that may apply: "
|
|
112
|
+
_STOPWORDS = frozenset(
|
|
113
|
+
"about after again also and any are been before being but can could did does doing for from had has have"
|
|
114
|
+
" how into its just more most not off once only other our out over own same should some such than that the"
|
|
115
|
+
" their them then there these they this those through too under until very was were what when where which"
|
|
116
|
+
" while who why will with would you your".split()
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _stem(token: str) -> str:
|
|
121
|
+
if token.endswith("sses"):
|
|
122
|
+
return token[:-2]
|
|
123
|
+
if len(token) > 5 and token.endswith("ing"):
|
|
124
|
+
return token[:-3]
|
|
125
|
+
if len(token) > 3 and token.endswith("s") and not token.endswith("ss"):
|
|
126
|
+
return token[:-1]
|
|
127
|
+
return token
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def situation_tokens(text: str) -> frozenset[str]:
|
|
131
|
+
"""Casefolded word stems of three or more letters, without stopwords."""
|
|
132
|
+
|
|
133
|
+
words = re.findall(r"[^\W_]+", str(text).casefold(), re.UNICODE)
|
|
134
|
+
return frozenset(_stem(word) for word in words if len(word) >= 3 and word not in _STOPWORDS)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def situation_glob_matches(glob: str, path: str) -> bool:
|
|
138
|
+
"""Repository-relative glob: ``**`` crosses directories, ``*`` and ``?`` do not.
|
|
139
|
+
|
|
140
|
+
Only ``*``, ``**`` and ``?`` are wildcards; ``[`` is a literal character.
|
|
141
|
+
A glob without wildcards names a file or a directory prefix.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
glob = glob.strip().strip("`").removeprefix("./")
|
|
145
|
+
path = path.strip().replace("\\", "/").removeprefix("./")
|
|
146
|
+
if not glob or not path:
|
|
147
|
+
return False
|
|
148
|
+
if not any(char in glob for char in "*?"):
|
|
149
|
+
prefix = glob.rstrip("/")
|
|
150
|
+
return path == prefix or path.startswith(prefix + "/")
|
|
151
|
+
parts, index = [], 0
|
|
152
|
+
while index < len(glob):
|
|
153
|
+
if glob.startswith("**/", index):
|
|
154
|
+
parts.append("(?:.*/)?")
|
|
155
|
+
index += 3
|
|
156
|
+
elif glob.startswith("**", index):
|
|
157
|
+
parts.append(".*")
|
|
158
|
+
index += 2
|
|
159
|
+
else:
|
|
160
|
+
char = glob[index]
|
|
161
|
+
parts.append("[^/]*" if char == "*" else "[^/]" if char == "?" else re.escape(char))
|
|
162
|
+
index += 1
|
|
163
|
+
return re.fullmatch("".join(parts), path) is not None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _section(body: str, heading: str) -> str:
|
|
167
|
+
"""Text under the first ``## <heading>…`` up to the next level-2 heading."""
|
|
168
|
+
|
|
169
|
+
match = re.search(rf"^##\s+{re.escape(heading)}[^\n]*\n(.*?)(?=^##\s|\Z)", body, re.I | re.M | re.S)
|
|
170
|
+
return match.group(1).strip() if match else ""
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def motif_sentence(body: str, limit: int = 240) -> str:
|
|
174
|
+
"""The first sentence of the Motif section, or of the first paragraph."""
|
|
175
|
+
|
|
176
|
+
text = _section(body, "Motif")
|
|
177
|
+
if not text:
|
|
178
|
+
paragraphs = [part for part in re.split(r"\n\s*\n", body) if part.strip() and not part.lstrip().startswith("#")]
|
|
179
|
+
text = paragraphs[0] if paragraphs else ""
|
|
180
|
+
text = " ".join(text.replace("*", "").split())
|
|
181
|
+
sentence = re.split(r"(?<=[.!?])\s+", text, maxsplit=1)[0]
|
|
182
|
+
return sentence if len(sentence) <= limit else sentence[: limit - 1].rstrip() + "…"
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _body_situations(body: str) -> dict[str, list[str]]:
|
|
186
|
+
"""Read the template's ``Situations (for discovery)`` section for patterns
|
|
187
|
+
written before situations were structured frontmatter."""
|
|
188
|
+
|
|
189
|
+
lines: list[str] = []
|
|
190
|
+
for line in _section(body, "Situations").splitlines():
|
|
191
|
+
if re.match(r"^\s*[-*]\s", line) or not lines:
|
|
192
|
+
lines.append(line)
|
|
193
|
+
else:
|
|
194
|
+
lines[-1] += " " + line.strip()
|
|
195
|
+
result: dict[str, list[str]] = {}
|
|
196
|
+
for line in lines:
|
|
197
|
+
match = re.match(r"^\s*[-*]\s*(domains|paths|activities)\s*:\s*(.+)$", line, re.I)
|
|
198
|
+
if not match:
|
|
199
|
+
continue
|
|
200
|
+
key, value = match.group(1).casefold(), match.group(2)
|
|
201
|
+
items = re.findall(r"`([^`]+)`", value) if key == "paths" else re.split(r"[;,]", value)
|
|
202
|
+
result[key] = [item.strip() for item in items if item.strip() and not item.strip().startswith("-")]
|
|
203
|
+
return result
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _instances_any(fields: Mapping[str, Any], keys: set[str]) -> bool:
|
|
207
|
+
return any(
|
|
208
|
+
relation == "instance-of" and (target in keys or _relative(target) in keys)
|
|
209
|
+
for relation, target in _relations(fields)
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def situated_hint_line(title: str, canonical_path: str, limit: int = 200) -> str:
|
|
214
|
+
"""One offer line within ``limit`` characters, or "" when the path alone is too long."""
|
|
215
|
+
|
|
216
|
+
room = limit - len(SITUATED_HINT_PREFIX) - len(canonical_path) - 3
|
|
217
|
+
title = " ".join(str(title).split())
|
|
218
|
+
if room < 8:
|
|
219
|
+
return ""
|
|
220
|
+
if len(title) > room:
|
|
221
|
+
title = title[: room - 1].rstrip() + "…"
|
|
222
|
+
return f"{SITUATED_HINT_PREFIX}{title} ({canonical_path})"
|
|
223
|
+
|
|
224
|
+
|
|
59
225
|
def _authorized(runtime: EgregoreRuntime, actor: ActorContext, permission: Permission, resource: str) -> None:
|
|
60
226
|
decision = runtime.authorize(actor, permission, (resource,))
|
|
61
227
|
if not decision.allowed:
|
|
@@ -105,10 +271,17 @@ class CanonicalKnowledgeService:
|
|
|
105
271
|
supersedes: Iterable[str] = (),
|
|
106
272
|
source_provenance: Iterable[SourceProvenance] = (),
|
|
107
273
|
policy_hints: dict[str, object] | None = None,
|
|
274
|
+
situations: Mapping[str, Iterable[str]] | None = None,
|
|
108
275
|
) -> WritebackEvent:
|
|
109
276
|
kind = artifact_type.strip().casefold()
|
|
110
277
|
if kind not in KNOWLEDGE_TYPES:
|
|
111
278
|
raise KnowledgeCaptureError("knowledge type must be decision, finding, or pattern")
|
|
279
|
+
situated = normalize_situations(situations)
|
|
280
|
+
if situated and kind != "pattern":
|
|
281
|
+
raise KnowledgeCaptureError("situations describe patterns only; use --type pattern")
|
|
282
|
+
if subtype and subtype.strip().casefold() == "evidence" and kind != "finding":
|
|
283
|
+
raise KnowledgeCaptureError("evidence records are findings; use --type finding --subtype evidence")
|
|
284
|
+
relationships = tuple(relationships)
|
|
112
285
|
clean_title = " ".join(title.split()).strip()
|
|
113
286
|
if not clean_title:
|
|
114
287
|
raise KnowledgeCaptureError("knowledge title is required")
|
|
@@ -126,7 +299,7 @@ class CanonicalKnowledgeService:
|
|
|
126
299
|
raise AuthorizationDenied(
|
|
127
300
|
"; ".join(decision.reasons) or "knowledge write denied"
|
|
128
301
|
)
|
|
129
|
-
if not
|
|
302
|
+
if not allows(decision, f"memory/{relative}", action_for(decision.permission), root=self.runtime.canonical_root):
|
|
130
303
|
raise AuthorizationDenied(
|
|
131
304
|
"knowledge path is outside the actor's authorized scope"
|
|
132
305
|
)
|
|
@@ -166,7 +339,10 @@ class CanonicalKnowledgeService:
|
|
|
166
339
|
}
|
|
167
340
|
if subtype:
|
|
168
341
|
legacy["subtype"] = subtype.strip()
|
|
169
|
-
|
|
342
|
+
if situated:
|
|
343
|
+
legacy["situations"] = situated
|
|
344
|
+
warnings = relationship_warnings(relationships) + self._instance_warnings(actor, relationships)
|
|
345
|
+
receipt = self.runtime.write_document(
|
|
170
346
|
actor,
|
|
171
347
|
CanonicalDocument(
|
|
172
348
|
artifact=artifact,
|
|
@@ -175,6 +351,156 @@ class CanonicalKnowledgeService:
|
|
|
175
351
|
legacy_fields=legacy,
|
|
176
352
|
),
|
|
177
353
|
)
|
|
354
|
+
return replace(receipt, warnings=tuple(receipt.warnings) + warnings) if warnings else receipt
|
|
355
|
+
|
|
356
|
+
def _readable(self, actor: ActorContext, under: str = "") -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
357
|
+
"""Yield ``(memory/path, frontmatter, body)`` for knowledge the actor may read."""
|
|
358
|
+
|
|
359
|
+
decision = self.runtime.authorize(actor, Permission.READ)
|
|
360
|
+
if not decision.allowed:
|
|
361
|
+
raise AuthorizationDenied("; ".join(decision.reasons) or "knowledge read denied")
|
|
362
|
+
base = self.memory_root / "knowledge" / under if under else self.memory_root / "knowledge"
|
|
363
|
+
for path in sorted(base.rglob("*.md")) if base.is_dir() else ():
|
|
364
|
+
relative = path.relative_to(self.memory_root).as_posix()
|
|
365
|
+
canonical = f"memory/{relative}"
|
|
366
|
+
verdict = check(decision, canonical, "read", root=self.memory_root)
|
|
367
|
+
if not verdict.allowed:
|
|
368
|
+
continue
|
|
369
|
+
if not path.is_file():
|
|
370
|
+
continue
|
|
371
|
+
try:
|
|
372
|
+
text = verdict.resolved.read_text(encoding="utf-8")
|
|
373
|
+
fields, body = split_frontmatter(text)
|
|
374
|
+
artifact_id = canonical_artifact_id(text, canonical)
|
|
375
|
+
except (OSError, ValueError):
|
|
376
|
+
continue
|
|
377
|
+
# A grant limited to named artifacts reads only those artifacts.
|
|
378
|
+
if not self.runtime.authorize(actor, Permission.READ, (artifact_id,)).allowed:
|
|
379
|
+
continue
|
|
380
|
+
if fields:
|
|
381
|
+
fields["id"] = artifact_id
|
|
382
|
+
if not fields.get("type") and relative.startswith("knowledge/patterns/"):
|
|
383
|
+
fields["type"] = "pattern" # legacy patterns predate the typed envelope
|
|
384
|
+
yield canonical, fields, body
|
|
385
|
+
|
|
386
|
+
@staticmethod
|
|
387
|
+
def _patterns(rows: Iterable[tuple[str, dict[str, Any], str]]) -> dict[str, tuple[str, dict[str, Any]]]:
|
|
388
|
+
"""Map each pattern's stable id and relative path to its record."""
|
|
389
|
+
|
|
390
|
+
index: dict[str, tuple[str, dict[str, Any]]] = {}
|
|
391
|
+
for canonical, fields, _ in rows:
|
|
392
|
+
if str(fields.get("type") or "").casefold() == "pattern":
|
|
393
|
+
index[str(fields["id"])] = index[_relative(canonical)] = (canonical, fields)
|
|
394
|
+
return index
|
|
395
|
+
|
|
396
|
+
def _instance_warnings(
|
|
397
|
+
self, actor: ActorContext, relationships: Iterable[ArtifactRelationship]
|
|
398
|
+
) -> tuple[str, ...]:
|
|
399
|
+
targets = [row.target_id for row in relationships if row.relation.strip().casefold() == "instance-of"]
|
|
400
|
+
if not targets:
|
|
401
|
+
return ()
|
|
402
|
+
try:
|
|
403
|
+
known = self._patterns(self._readable(actor))
|
|
404
|
+
except AuthorizationDenied:
|
|
405
|
+
return ()
|
|
406
|
+
return tuple(
|
|
407
|
+
f"instance-of target '{target}' is not a readable pattern; check the pattern id"
|
|
408
|
+
for target in targets
|
|
409
|
+
if target not in known and _relative(target) not in known
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
def instances(self, actor: ActorContext, pattern: str) -> dict[str, object]:
|
|
413
|
+
"""Reverse lookup: records whose ``instance-of`` points at ``pattern``.
|
|
414
|
+
|
|
415
|
+
A typed scan of canonical frontmatter under the actor's read scope; no
|
|
416
|
+
ranking, no graph. ``pattern`` is a stable id or a canonical path.
|
|
417
|
+
"""
|
|
418
|
+
|
|
419
|
+
rows = list(self._readable(actor))
|
|
420
|
+
patterns = self._patterns(rows)
|
|
421
|
+
found = patterns.get(pattern.strip()) or patterns.get(_relative(pattern))
|
|
422
|
+
if found is None:
|
|
423
|
+
raise KnowledgeCaptureError(f"no readable pattern matches {pattern.strip()}")
|
|
424
|
+
canonical, fields = found
|
|
425
|
+
keys = {str(fields["id"]), _relative(canonical)}
|
|
426
|
+
|
|
427
|
+
def summary(path: str, values: Mapping[str, Any]) -> dict[str, object]:
|
|
428
|
+
return {
|
|
429
|
+
"id": str(values["id"]),
|
|
430
|
+
"title": str(values.get("title") or Path(path).stem),
|
|
431
|
+
"type": str(values.get("type") or ""),
|
|
432
|
+
"subtype": str(values.get("subtype") or "") or None,
|
|
433
|
+
"canonical_path": path,
|
|
434
|
+
"created_at": str(values.get("created_at") or values.get("date") or ""),
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
matches = [
|
|
438
|
+
summary(path, values)
|
|
439
|
+
for path, values, _ in rows
|
|
440
|
+
if _instances_any(values, keys)
|
|
441
|
+
]
|
|
442
|
+
matches.sort(key=lambda row: (str(row["created_at"]), str(row["canonical_path"])), reverse=True)
|
|
443
|
+
return {"pattern": summary(canonical, fields), "count": len(matches), "instances": matches}
|
|
444
|
+
|
|
445
|
+
def situated(
|
|
446
|
+
self,
|
|
447
|
+
actor: ActorContext,
|
|
448
|
+
*,
|
|
449
|
+
paths: Iterable[str] = (),
|
|
450
|
+
text: str = "",
|
|
451
|
+
limit: int = 3,
|
|
452
|
+
count_instances: bool = True,
|
|
453
|
+
) -> dict[str, object]:
|
|
454
|
+
"""Patterns whose situations are live for these paths and this text.
|
|
455
|
+
|
|
456
|
+
Path globs match the given repository paths (3 points per glob);
|
|
457
|
+
domains, activities and topics match by shared word stems (1 point
|
|
458
|
+
per stem). A pattern needs a path match, or two shared stems from at
|
|
459
|
+
least two of its phrases where one phrase matches strongly (all of its
|
|
460
|
+
stems, or at least two). One compound topic alone never fires, and
|
|
461
|
+
common verbs scattered across phrases ("add", "design") do not either.
|
|
462
|
+
Ties order by title, then path. Deterministic; no model calls.
|
|
463
|
+
"""
|
|
464
|
+
|
|
465
|
+
changed = list(dict.fromkeys(str(path).strip() for path in paths if str(path).strip()))
|
|
466
|
+
words = situation_tokens(text)
|
|
467
|
+
hits: list[dict[str, Any]] = []
|
|
468
|
+
for canonical, fields, body in self._readable(actor, "patterns"):
|
|
469
|
+
if str(fields.get("type") or "").casefold() != "pattern":
|
|
470
|
+
continue
|
|
471
|
+
given = fields.get("situations")
|
|
472
|
+
situations = given if isinstance(given, Mapping) and given else _body_situations(body)
|
|
473
|
+
|
|
474
|
+
def listed(key: str, source: Mapping[str, Any] = situations) -> list[str]:
|
|
475
|
+
value = source.get(key)
|
|
476
|
+
return [str(item) for item in value] if isinstance(value, list) else []
|
|
477
|
+
|
|
478
|
+
globs = sorted({glob for glob in listed("paths") for path in changed if situation_glob_matches(glob, path)})
|
|
479
|
+
stems = [situation_tokens(phrase) for phrase in
|
|
480
|
+
(*listed("domains"), *listed("activities"), *listed("topics", fields))]
|
|
481
|
+
phrases = [phrase & words for phrase in stems]
|
|
482
|
+
shared = sorted(set().union(*phrases))
|
|
483
|
+
strong = any(len(hit) >= 2 or (hit and hit == full) for hit, full in zip(phrases, stems))
|
|
484
|
+
if not globs and (not strong or len(shared) < 2 or sum(1 for phrase in phrases if phrase) < 2):
|
|
485
|
+
continue
|
|
486
|
+
hits.append({
|
|
487
|
+
"id": str(fields["id"]),
|
|
488
|
+
"title": str(fields.get("title") or Path(canonical).stem),
|
|
489
|
+
"canonical_path": canonical,
|
|
490
|
+
"motif": motif_sentence(body),
|
|
491
|
+
"score": 3 * len(globs) + len(shared),
|
|
492
|
+
"matched": {"paths": globs, "words": shared},
|
|
493
|
+
})
|
|
494
|
+
hits.sort(key=lambda hit: (-hit["score"], hit["title"].casefold(), hit["canonical_path"]))
|
|
495
|
+
# Packaged here, so the prompt hook's offer line and the CLI hand out the same redacted hits.
|
|
496
|
+
selected = held.kept(self.runtime.authorize(actor, Permission.READ), hits[: max(0, limit)],
|
|
497
|
+
root=self.memory_root, path="canonical_path")
|
|
498
|
+
if count_instances and selected:
|
|
499
|
+
rows = list(self._readable(actor))
|
|
500
|
+
for hit in selected:
|
|
501
|
+
keys = {hit["id"], _relative(hit["canonical_path"])}
|
|
502
|
+
hit["instances"] = sum(1 for _, values, _ in rows if _instances_any(values, keys))
|
|
503
|
+
return {"count": len(selected), "total": len(hits), "patterns": selected}
|
|
178
504
|
|
|
179
505
|
|
|
180
506
|
@dataclass(frozen=True, slots=True)
|
|
@@ -9,9 +9,11 @@ from pathlib import Path
|
|
|
9
9
|
import sys
|
|
10
10
|
from uuid import uuid4
|
|
11
11
|
|
|
12
|
+
from . import held
|
|
12
13
|
from .contracts import ArtifactRelationship
|
|
13
14
|
from .errors import AuthorizationDenied
|
|
14
15
|
from .knowledge import (
|
|
16
|
+
RELATIONSHIP_VOCABULARY,
|
|
15
17
|
CanonicalKnowledgeService,
|
|
16
18
|
KnowledgeCaptureError,
|
|
17
19
|
PersonalNoteService,
|
|
@@ -36,6 +38,10 @@ def _context(*, push_remote: bool):
|
|
|
36
38
|
return actor, knowledge, notes
|
|
37
39
|
|
|
38
40
|
|
|
41
|
+
def _emit(knowledge, actor, value, **options) -> int:
|
|
42
|
+
return held.emit_for(knowledge.runtime, actor, value, **options)
|
|
43
|
+
|
|
44
|
+
|
|
39
45
|
def _input(path: str) -> str:
|
|
40
46
|
return read_and_consume(path, _root()).decode("utf-8")
|
|
41
47
|
|
|
@@ -76,39 +82,58 @@ def _create(args: argparse.Namespace) -> int:
|
|
|
76
82
|
subtype=args.subtype,
|
|
77
83
|
relationships=_relationships(args.relationship),
|
|
78
84
|
supersedes=args.supersedes,
|
|
85
|
+
situations={
|
|
86
|
+
"domains": args.situation_domain,
|
|
87
|
+
"paths": args.situation_path,
|
|
88
|
+
"activities": args.situation_activity,
|
|
89
|
+
},
|
|
79
90
|
)
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
return _emit(knowledge, actor, _receipt(receipt)) or (0 if receipt.status.value in {"accepted", "partial"} else 1)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _instances(args: argparse.Namespace) -> int:
|
|
95
|
+
actor, knowledge, _ = _context(push_remote=False)
|
|
96
|
+
return _emit(knowledge, actor, knowledge.instances(actor, args.pattern))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _situated(args: argparse.Namespace) -> int:
|
|
100
|
+
if not args.paths and not (args.text or "").strip():
|
|
101
|
+
raise KnowledgeCaptureError("give --paths, --text, or both")
|
|
102
|
+
actor, knowledge, _ = _context(push_remote=False)
|
|
103
|
+
found = knowledge.situated(actor, paths=args.paths, text=args.text or "", limit=args.n)
|
|
104
|
+
return _emit(knowledge, actor, found)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _positive(value: str) -> int:
|
|
108
|
+
number = int(value)
|
|
109
|
+
if number < 1:
|
|
110
|
+
raise argparse.ArgumentTypeError("must be at least 1")
|
|
111
|
+
return number
|
|
82
112
|
|
|
83
113
|
|
|
84
114
|
def _note_create(args: argparse.Namespace) -> int:
|
|
85
|
-
actor,
|
|
115
|
+
actor, knowledge, notes = _context(push_remote=False)
|
|
86
116
|
note = notes.create(
|
|
87
117
|
actor,
|
|
88
118
|
title=args.title,
|
|
89
119
|
body=_input(args.input),
|
|
90
120
|
note_type=args.type,
|
|
91
121
|
)
|
|
92
|
-
|
|
93
|
-
return 0
|
|
122
|
+
return _emit(knowledge, actor, note.to_dict())
|
|
94
123
|
|
|
95
124
|
|
|
96
125
|
def _note_list(args: argparse.Namespace) -> int:
|
|
97
|
-
actor,
|
|
98
|
-
|
|
99
|
-
print(json.dumps({"notes": [row.to_dict() for row in rows]}, ensure_ascii=False))
|
|
100
|
-
return 0
|
|
126
|
+
actor, knowledge, notes = _context(push_remote=False)
|
|
127
|
+
return _emit(knowledge, actor, {"notes": [row.to_dict() for row in notes.list(actor)]})
|
|
101
128
|
|
|
102
129
|
|
|
103
130
|
def _note_open(args: argparse.Namespace) -> int:
|
|
104
|
-
actor,
|
|
105
|
-
|
|
106
|
-
print(note.body, end="")
|
|
107
|
-
return 0
|
|
131
|
+
actor, knowledge, notes = _context(push_remote=False)
|
|
132
|
+
return _emit(knowledge, actor, notes.open(actor, args.path).body, render=str, end="")
|
|
108
133
|
|
|
109
134
|
|
|
110
135
|
def _note_promote(args: argparse.Namespace) -> int:
|
|
111
|
-
actor,
|
|
136
|
+
actor, knowledge, notes = _context(push_remote=not args.no_push)
|
|
112
137
|
receipt = notes.promote(
|
|
113
138
|
actor,
|
|
114
139
|
raw_path=args.path,
|
|
@@ -117,8 +142,7 @@ def _note_promote(args: argparse.Namespace) -> int:
|
|
|
117
142
|
topics=args.topic,
|
|
118
143
|
workstream=args.workstream,
|
|
119
144
|
)
|
|
120
|
-
|
|
121
|
-
return 0 if receipt.status.value in {"accepted", "partial"} else 1
|
|
145
|
+
return _emit(knowledge, actor, _receipt(receipt)) or (0 if receipt.status.value in {"accepted", "partial"} else 1)
|
|
122
146
|
|
|
123
147
|
|
|
124
148
|
def _parser() -> argparse.ArgumentParser:
|
|
@@ -132,11 +156,27 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
132
156
|
create.add_argument("--topic", action="append", default=[])
|
|
133
157
|
create.add_argument("--workstream")
|
|
134
158
|
create.add_argument("--subtype")
|
|
135
|
-
create.add_argument(
|
|
159
|
+
create.add_argument(
|
|
160
|
+
"--relationship", action="append", default=[], metavar="RELATION:TARGET",
|
|
161
|
+
help=f"repeatable; relations: {', '.join(RELATIONSHIP_VOCABULARY)} (others warn)",
|
|
162
|
+
)
|
|
136
163
|
create.add_argument("--supersedes", action="append", default=[])
|
|
164
|
+
create.add_argument("--situation-domain", action="append", default=[], help="pattern only; repeatable")
|
|
165
|
+
create.add_argument("--situation-path", action="append", default=[], help="pattern only; repo-relative glob")
|
|
166
|
+
create.add_argument("--situation-activity", action="append", default=[], help="pattern only; repeatable")
|
|
137
167
|
create.add_argument("--no-push", action="store_true")
|
|
138
168
|
create.set_defaults(handler=_create)
|
|
139
169
|
|
|
170
|
+
instances = commands.add_parser("instances", help="records whose instance-of points at a pattern")
|
|
171
|
+
instances.add_argument("pattern", help="pattern id or canonical path")
|
|
172
|
+
instances.set_defaults(handler=_instances)
|
|
173
|
+
|
|
174
|
+
situated = commands.add_parser("situated", help="patterns whose situations match these paths or words")
|
|
175
|
+
situated.add_argument("--paths", nargs="+", action="extend", default=[], metavar="PATH")
|
|
176
|
+
situated.add_argument("--text", help="what is being worked on, in words")
|
|
177
|
+
situated.add_argument("-n", type=_positive, default=3, help="at most this many patterns (default 3)")
|
|
178
|
+
situated.set_defaults(handler=_situated)
|
|
179
|
+
|
|
140
180
|
note_create = commands.add_parser("note-create")
|
|
141
181
|
note_create.add_argument("--title", required=True)
|
|
142
182
|
note_create.add_argument("--type", choices=("thought", "session", "retrospective", "journal"), default="thought")
|