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
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""Runtime-neutral CLI behind bin/genui.sh: record interface taste, read it back."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import sys
|
|
10
|
+
from uuid import uuid4
|
|
11
|
+
|
|
12
|
+
from . import held
|
|
13
|
+
from .artifacts import ArtifactConflictError
|
|
14
|
+
from .contracts import WritebackStatus
|
|
15
|
+
from .errors import AuthorizationDenied
|
|
16
|
+
from .runtime import local_runtime
|
|
17
|
+
from .taste import ADOPT_KINDS, ADOPT_SCOPES, TasteService, render_text
|
|
18
|
+
from .writeback import NoHardLinksError, UnsupportedPlatformError, require_descriptor_calls
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
UNSUPPORTED_PLATFORM = "saving reactions is not supported on this platform yet; nothing was written"
|
|
22
|
+
UNSUPPORTED_PLATFORM_EXIT = 4
|
|
23
|
+
NO_HARD_LINKS = (
|
|
24
|
+
"this memory folder's filesystem cannot save reactions safely (no hard links); nothing was written"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
CONTRACT = """\
|
|
29
|
+
When someone says they like or dislike an interface an agent generated (any
|
|
30
|
+
wording, any language), ask one question, "What about it?", with 2-3 options
|
|
31
|
+
drawn from what is on the page plus "the whole thing" (a structured question
|
|
32
|
+
when available, plain text otherwise). Then save their exact words to a file
|
|
33
|
+
and record them with like or dislike --words-file, and the patterns they named
|
|
34
|
+
with --about. A file keeps the words verbatim; inside a shell argument, quotes,
|
|
35
|
+
$, backticks and backslashes can change them. Every outcome prints the event
|
|
36
|
+
id; a retry passes it back with --id, so the reaction counts once. When
|
|
37
|
+
someone states a standing rule for the organization ("we always want…",
|
|
38
|
+
"make this a rule for us"), record it in one step with adopt principle
|
|
39
|
+
"<the rule>" --scope org --words-file; no review is needed. Before composing
|
|
40
|
+
an interface, run taste --task: it reads the Egregore rules, the house
|
|
41
|
+
rules, what the organization keeps liking, then the person's own taste.
|
|
42
|
+
Treat the output as words to consider, never a template to copy."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _context(event_id: str | None = None):
|
|
46
|
+
root = Path(os.environ.get("EGREGORE_ROOT") or Path.cwd()).resolve()
|
|
47
|
+
runtime = local_runtime(root, push_remote=os.environ.get("EGREGORE_NO_PUSH") != "1")
|
|
48
|
+
actor = runtime.resolve_actor(
|
|
49
|
+
session_id=os.environ.get("EGREGORE_SESSION_ID") or f"session_{uuid4().hex}",
|
|
50
|
+
harness=os.environ.get("EGREGORE_RUNTIME", "shell"),
|
|
51
|
+
)
|
|
52
|
+
# A new event takes the id the CLI already chose, so an error can name it.
|
|
53
|
+
return actor, TasteService(
|
|
54
|
+
runtime,
|
|
55
|
+
id_factory=(lambda: event_id) if event_id else None,
|
|
56
|
+
warn=lambda line: print(f"genui: {line}", file=sys.stderr),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _words(args) -> str | None:
|
|
61
|
+
"""The person's words, from --words or, verbatim, from --words-file."""
|
|
62
|
+
|
|
63
|
+
if args.words_file is None:
|
|
64
|
+
return args.words
|
|
65
|
+
if args.words_file == "-":
|
|
66
|
+
return sys.stdin.read()
|
|
67
|
+
return Path(args.words_file).read_text(encoding="utf-8")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _emit(service, actor, receipt) -> int:
|
|
71
|
+
"""Print the receipt, and one line on stderr unless it was fully shared.
|
|
72
|
+
|
|
73
|
+
Exit 0 means the event is committed on this machine; anything less is an
|
|
74
|
+
error, since the person's words are not durably recorded.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
held.emit_for(service.runtime, actor, receipt.to_dict())
|
|
78
|
+
event_id = receipt.event["id"]
|
|
79
|
+
warnings = list(receipt.writeback.warnings)
|
|
80
|
+
if not receipt.recorded:
|
|
81
|
+
reason = "; ".join(warnings) or "the write was refused"
|
|
82
|
+
print(f"genui: not recorded: {reason} (event {event_id}; retry with --id {event_id})", file=sys.stderr)
|
|
83
|
+
return 1
|
|
84
|
+
if receipt.writeback.status is WritebackStatus.PARTIAL:
|
|
85
|
+
unshared = [warning for warning in warnings if "push" in warning or "remote" in warning]
|
|
86
|
+
if unshared:
|
|
87
|
+
line = f"saved on this machine, not yet shared: {'; '.join(unshared)}"
|
|
88
|
+
else:
|
|
89
|
+
line = f"saved on this machine, with a warning: {'; '.join(warnings) or 'partial writeback'}"
|
|
90
|
+
print(f"genui: {line} (event {event_id})", file=sys.stderr)
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _record(args, record) -> int:
|
|
95
|
+
"""Run one recording command so that every outcome names the event id."""
|
|
96
|
+
|
|
97
|
+
event_id = (args.id or "").strip() or str(uuid4())
|
|
98
|
+
try:
|
|
99
|
+
require_descriptor_calls() # before anything is opened or written
|
|
100
|
+
actor, service = _context(None if args.id else event_id)
|
|
101
|
+
receipt = record(actor, service, args.id)
|
|
102
|
+
except UnsupportedPlatformError:
|
|
103
|
+
# No retry can help on this platform.
|
|
104
|
+
print(f"genui: {UNSUPPORTED_PLATFORM}", file=sys.stderr)
|
|
105
|
+
return UNSUPPORTED_PLATFORM_EXIT
|
|
106
|
+
except NoHardLinksError:
|
|
107
|
+
# Nor on this filesystem: the staged copy is gone, nothing is written.
|
|
108
|
+
print(f"genui: not recorded: {NO_HARD_LINKS} (event {event_id})", file=sys.stderr)
|
|
109
|
+
return 1
|
|
110
|
+
except ArtifactConflictError as exc:
|
|
111
|
+
# A retry cannot fix a different reaction under a used id.
|
|
112
|
+
print(f"genui: not recorded: {exc} (event {event_id})", file=sys.stderr)
|
|
113
|
+
return 1
|
|
114
|
+
except (AuthorizationDenied, OSError, RuntimeError, ValueError) as exc:
|
|
115
|
+
print(f"genui: not recorded: {exc} (event {event_id}; retry with --id {event_id})", file=sys.stderr)
|
|
116
|
+
return 1
|
|
117
|
+
return _emit(service, actor, receipt)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _react(args) -> int:
|
|
121
|
+
return _record(args, lambda actor, service, event_id: service.react(
|
|
122
|
+
actor,
|
|
123
|
+
"liked" if args.command == "like" else "disliked",
|
|
124
|
+
args.target,
|
|
125
|
+
words=_words(args),
|
|
126
|
+
about=args.about,
|
|
127
|
+
region=args.region,
|
|
128
|
+
task=args.task,
|
|
129
|
+
audience=args.audience,
|
|
130
|
+
form=args.form,
|
|
131
|
+
event_id=event_id,
|
|
132
|
+
))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _chose(args) -> int:
|
|
136
|
+
return _record(args, lambda actor, service, event_id: service.choose(
|
|
137
|
+
actor,
|
|
138
|
+
args.winner,
|
|
139
|
+
args.over,
|
|
140
|
+
words=_words(args),
|
|
141
|
+
about=args.about,
|
|
142
|
+
task=args.task,
|
|
143
|
+
audience=args.audience,
|
|
144
|
+
form=args.form,
|
|
145
|
+
event_id=event_id,
|
|
146
|
+
))
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _adopt(args) -> int:
|
|
150
|
+
return _record(args, lambda actor, service, event_id: service.adopt(
|
|
151
|
+
actor, args.kind, args.value, scope=args.scope, words=_words(args), event_id=event_id,
|
|
152
|
+
))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _retract(args) -> int:
|
|
156
|
+
return _record(args, lambda actor, service, event_id: service.retract(
|
|
157
|
+
actor, args.event_id, words=_words(args), event_id=event_id,
|
|
158
|
+
))
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _taste(args) -> int:
|
|
162
|
+
actor, service = _context()
|
|
163
|
+
summary = service.summary(actor, person=args.person, task=args.task, form=args.form)
|
|
164
|
+
return held.emit_for(service.runtime, actor, summary, **({} if args.json else {"render": render_text, "end": ""}))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _parser() -> argparse.ArgumentParser:
|
|
168
|
+
parser = argparse.ArgumentParser(
|
|
169
|
+
prog="bin/genui.sh",
|
|
170
|
+
description="Record what people like in generated interfaces and read it back as words.",
|
|
171
|
+
epilog=CONTRACT,
|
|
172
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
173
|
+
)
|
|
174
|
+
commands = parser.add_subparsers(dest="command", required=True)
|
|
175
|
+
|
|
176
|
+
def words(command, *, required: bool) -> None:
|
|
177
|
+
given = command.add_mutually_exclusive_group(required=required)
|
|
178
|
+
given.add_argument("--words", help="what the person said, verbatim, as one shell argument")
|
|
179
|
+
given.add_argument(
|
|
180
|
+
"--words-file", metavar="PATH",
|
|
181
|
+
help="a file holding what the person said, kept verbatim; '-' reads standard input",
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def context(command, *, region: bool = True) -> None:
|
|
185
|
+
command.add_argument("--about", action="append", default=[], metavar="PATTERN",
|
|
186
|
+
help="a pattern the person named; repeat for each")
|
|
187
|
+
if region:
|
|
188
|
+
command.add_argument("--region", help="the part of the page, as free text or a selector")
|
|
189
|
+
command.add_argument("--task", help="what the interface was for")
|
|
190
|
+
command.add_argument("--audience", help="who it was for")
|
|
191
|
+
command.add_argument("--form", help="the kind of interface, e.g. cards, scroll, mock, view")
|
|
192
|
+
command.add_argument("--id", help="event UUID; reuse it when retrying the same event")
|
|
193
|
+
|
|
194
|
+
for name, verb in (("like", "liked"), ("dislike", "disliked")):
|
|
195
|
+
react = commands.add_parser(name, help=f"record that someone {verb} a generated interface")
|
|
196
|
+
react.add_argument("target", help="registry id, hosted URL, local path or claude.ai artifact link")
|
|
197
|
+
words(react, required=True)
|
|
198
|
+
context(react)
|
|
199
|
+
react.set_defaults(handler=_react)
|
|
200
|
+
|
|
201
|
+
chose = commands.add_parser("chose", help="record that someone chose one interface over another")
|
|
202
|
+
chose.add_argument("winner", help="the interface they chose")
|
|
203
|
+
chose.add_argument("--over", required=True, help="the interface they passed over")
|
|
204
|
+
words(chose, required=False)
|
|
205
|
+
context(chose, region=False)
|
|
206
|
+
chose.set_defaults(handler=_chose)
|
|
207
|
+
|
|
208
|
+
adopt = commands.add_parser(
|
|
209
|
+
"adopt",
|
|
210
|
+
help="make a palette or pattern a default, or a principle a standing rule (--scope org: a house rule)",
|
|
211
|
+
)
|
|
212
|
+
adopt.add_argument("kind", choices=ADOPT_KINDS)
|
|
213
|
+
adopt.add_argument("value", help="the palette, pattern or principle, in a few words")
|
|
214
|
+
adopt.add_argument("--scope", choices=ADOPT_SCOPES, default="person")
|
|
215
|
+
words(adopt, required=False)
|
|
216
|
+
adopt.add_argument("--id", help="event UUID; reuse it when retrying the same event")
|
|
217
|
+
adopt.set_defaults(handler=_adopt)
|
|
218
|
+
|
|
219
|
+
retract = commands.add_parser("retract", help="withdraw one of your own taste events")
|
|
220
|
+
retract.add_argument("event_id")
|
|
221
|
+
words(retract, required=False)
|
|
222
|
+
retract.add_argument("--id", help="event UUID; reuse it when retrying the same event")
|
|
223
|
+
retract.set_defaults(handler=_retract)
|
|
224
|
+
|
|
225
|
+
taste = commands.add_parser("taste", help="read back what someone liked, in their words")
|
|
226
|
+
taste.add_argument("--person", help="a name or actor id; defaults to you")
|
|
227
|
+
taste.add_argument("--task", help="the work about to be composed; closest reactions come first")
|
|
228
|
+
taste.add_argument("--form", help="the kind of interface about to be composed")
|
|
229
|
+
taste.add_argument("--json", action="store_true")
|
|
230
|
+
taste.set_defaults(handler=_taste)
|
|
231
|
+
return parser
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def main(argv: list[str] | None = None) -> int:
|
|
235
|
+
"""Run one command; bin/genui.sh reaches it through bin/lib/genui-entry.py."""
|
|
236
|
+
|
|
237
|
+
args = _parser().parse_args(argv)
|
|
238
|
+
try:
|
|
239
|
+
return args.handler(args)
|
|
240
|
+
except (AuthorizationDenied, OSError, RuntimeError, ValueError) as exc:
|
|
241
|
+
print(f"genui: {exc}", file=sys.stderr)
|
|
242
|
+
return 1
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Egregore rules: good design for any reader, whatever the brand.
|
|
2
|
+
|
|
3
|
+
These ship with the Runtime to every organization and are read first, before
|
|
4
|
+
the organization's house rules, what the organization keeps liking, and one
|
|
5
|
+
person's own taste; later layers win where they conflict. The must-pass
|
|
6
|
+
checks (contrast, accessibility, colours from tokens, sandboxed hosting, no
|
|
7
|
+
internal notes in the outside copy) live in code and always hold.
|
|
8
|
+
|
|
9
|
+
Each rule says when to skip it and why it exists, so an agent can set it
|
|
10
|
+
aside with a reason instead of following it blindly.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
EGREGORE_RULES: tuple[dict[str, str], ...] = (
|
|
16
|
+
{
|
|
17
|
+
"rule": "Design every page from its content; never ship a stock template.",
|
|
18
|
+
"skip": "A form the reader already knows and expects, such as a receipt.",
|
|
19
|
+
"why": "Examples inspire; a skeleton reused as-is makes every page read the same.",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"rule": "The first view is a complete frame: nothing cut by the fold, nothing overflowing sideways, no controls over content.",
|
|
23
|
+
"skip": "Never.",
|
|
24
|
+
"why": "The first screen decides whether the reader continues.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"rule": "Give one strong visual room, and keep nothing off-chart: extend the axes, or cut the items and say so.",
|
|
28
|
+
"skip": "Pages with no visual argument to make.",
|
|
29
|
+
"why": "A cramped or clipped figure hides the point it exists to show.",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"rule": "Leave clear space between groups, and check overlaps mechanically, not by eye.",
|
|
33
|
+
"skip": "Never.",
|
|
34
|
+
"why": "Crowding reads as noise, and the eye misses overlaps a check catches.",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"rule": "Choose sections per piece, never because a template lists them.",
|
|
38
|
+
"skip": "A form whose sections the reader relies on, such as a changelog.",
|
|
39
|
+
"why": "Standing sections pad a page with headings that say nothing.",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"rule": "Use plain, established words and the organization's own vocabulary; coin no terms in reader-facing text.",
|
|
43
|
+
"skip": "A term the organization already uses.",
|
|
44
|
+
"why": "A coined word is one more thing the reader must learn before understanding.",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"rule": "Introduce every term before using it, and write for someone who was not there.",
|
|
48
|
+
"skip": "Pages written for the people who were in the room.",
|
|
49
|
+
"why": "Pages travel further than the conversation that produced them.",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"rule": "Reveal depth step by step, but let the page answer its question with no interaction.",
|
|
53
|
+
"skip": "Tools and forms whose purpose is the interaction.",
|
|
54
|
+
"why": "A reader who never clicks should still leave with the answer.",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"rule": "Keep one design system as the chassis and one visual device per element.",
|
|
58
|
+
"skip": "Never.",
|
|
59
|
+
"why": "Mixed systems and stacked devices compete for attention.",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"rule": "Keep geometry honest: one meaning per axis, status readable without colour, every item accounted for.",
|
|
63
|
+
"skip": "Never.",
|
|
64
|
+
"why": "A figure that misleads is worse than no figure.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"rule": "Move things only to explain them, and respect reduced motion.",
|
|
68
|
+
"skip": "Never.",
|
|
69
|
+
"why": "Decorative motion distracts and can make readers unwell.",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"rule": "Keep minimum craft: no cropped glyphs, labels that fit, focus always visible and styled, never removed.",
|
|
73
|
+
"skip": "Never.",
|
|
74
|
+
"why": "Small defects cost trust out of proportion to their size.",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"rule": "Serve two audiences from one source: mark internal notes and strip them from the outside copy.",
|
|
78
|
+
"skip": "Pages that never leave the organization.",
|
|
79
|
+
"why": "One source keeps both copies true; marked notes cannot leak by accident.",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"rule": "A page may carry its own palette when the content calls for it, if it passes the must-pass checks.",
|
|
83
|
+
"skip": "An organization with a house palette rule.",
|
|
84
|
+
"why": "Colour carries meaning; the checks keep it readable.",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"rule": "Draw no coloured side stripes: mark reading emphasis with a marker, a margin label or type, and status with a quiet panel whose label carries a shape.",
|
|
88
|
+
"skip": "A rail that connects timeline items.",
|
|
89
|
+
"why": "A stripe says only 'look here' and fails without colour; a shaped label reads in any theme.",
|
|
90
|
+
},
|
|
91
|
+
)
|
|
@@ -24,6 +24,7 @@ from urllib import request as urllib_request
|
|
|
24
24
|
from uuid import uuid4
|
|
25
25
|
|
|
26
26
|
from .contracts import TelemetryEvent
|
|
27
|
+
from .sandbox import state_directory
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
TELEMETRY_SCHEMA_VERSION = "egregore.telemetry/v1"
|
|
@@ -138,6 +139,7 @@ class TelemetryStatus:
|
|
|
138
139
|
storage_path: Path
|
|
139
140
|
local_only: bool = True
|
|
140
141
|
retention: Mapping[str, Any] | None = None
|
|
142
|
+
warnings: tuple[str, ...] = ()
|
|
141
143
|
|
|
142
144
|
|
|
143
145
|
@dataclass(frozen=True, slots=True)
|
|
@@ -236,6 +238,8 @@ def validate_event(event: TelemetryEvent) -> None:
|
|
|
236
238
|
|
|
237
239
|
for artifact_id in event.artifact_ids:
|
|
238
240
|
_safe_identifier(artifact_id, field="artifact_ids[]", max_length=256)
|
|
241
|
+
if artifact_id.startswith(("memory/", "/", ".", "~")) or artifact_id.endswith((".md", ".html")):
|
|
242
|
+
raise TelemetryPrivacyError("artifact_ids[] must be opaque identifiers, never paths")
|
|
239
243
|
|
|
240
244
|
if event.event_type in {"operation.start", "operation.result"}:
|
|
241
245
|
required = {"operation", "layer", "invocation_id", "harness"}
|
|
@@ -368,7 +372,10 @@ class LocalTelemetrySink:
|
|
|
368
372
|
``~/.egregore/telemetry/``: on-device, outside canonical repositories, and
|
|
369
373
|
unable to mix multiple Egregore instances. ``EGREGORE_TELEMETRY_DIR`` or
|
|
370
374
|
an explicit ``storage_dir`` may relocate one sink for tests or managed
|
|
371
|
-
local deployments.
|
|
375
|
+
local deployments. When that per-user directory refuses writes (a
|
|
376
|
+
sandboxed session), the buffer moves to the workspace's own
|
|
377
|
+
``.egregore/telemetry/``, and ``status()`` names the cause first, and
|
|
378
|
+
names both failures when that copy is refused too.
|
|
372
379
|
"""
|
|
373
380
|
|
|
374
381
|
def __init__(
|
|
@@ -382,6 +389,9 @@ class LocalTelemetrySink:
|
|
|
382
389
|
instance_root: Path | None = None,
|
|
383
390
|
) -> None:
|
|
384
391
|
env_dir = os.environ.get("EGREGORE_TELEMETRY_DIR")
|
|
392
|
+
# Set when the per-user directory refuses writes: with the workspace
|
|
393
|
+
# copy in use, or naming why that copy was refused too.
|
|
394
|
+
self.state_warning: str | None = None
|
|
385
395
|
if storage_dir is not None:
|
|
386
396
|
self.storage_dir = storage_dir
|
|
387
397
|
elif env_dir:
|
|
@@ -390,6 +400,16 @@ class LocalTelemetrySink:
|
|
|
390
400
|
root = instance_root or (state_file.parent if state_file else Path.cwd())
|
|
391
401
|
namespace = hashlib.sha256(str(root.resolve()).encode()).hexdigest()[:20]
|
|
392
402
|
self.storage_dir = Path.home() / ".egregore" / "telemetry" / namespace
|
|
403
|
+
if state_file is not None:
|
|
404
|
+
# The state file names the workspace, the one place a
|
|
405
|
+
# sandboxed session can still write.
|
|
406
|
+
workspace = state_file.parent
|
|
407
|
+
self.storage_dir, self.state_warning = state_directory(
|
|
408
|
+
self.storage_dir,
|
|
409
|
+
workspace / ".egregore" / "telemetry",
|
|
410
|
+
workspace=workspace,
|
|
411
|
+
home=Path.home(),
|
|
412
|
+
)
|
|
393
413
|
self.buffer_path = self.storage_dir / "telemetry.jsonl"
|
|
394
414
|
self.lock_path = self.storage_dir / "telemetry.lock"
|
|
395
415
|
self.share_consent_path = self.storage_dir / "telemetry-share-consent.json"
|
|
@@ -550,6 +570,7 @@ class LocalTelemetrySink:
|
|
|
550
570
|
byte_count=byte_count,
|
|
551
571
|
storage_path=self.buffer_path,
|
|
552
572
|
retention=self._retention() if self.retention_path.exists() else None,
|
|
573
|
+
warnings=(self.state_warning,) if self.state_warning else (),
|
|
553
574
|
)
|
|
554
575
|
|
|
555
576
|
def set_enabled(self, enabled: bool) -> None:
|
|
@@ -722,11 +743,13 @@ class HttpSharedTelemetrySink:
|
|
|
722
743
|
"Content-Type": "application/x-ndjson",
|
|
723
744
|
"User-Agent": "egregore-runtime-telemetry/1",
|
|
724
745
|
}
|
|
725
|
-
if self.bearer_token:
|
|
726
|
-
headers["Authorization"] = f"Bearer {self.bearer_token}"
|
|
727
746
|
outbound = urllib_request.Request(
|
|
728
747
|
self.endpoint, data=payload, headers=headers, method="POST"
|
|
729
748
|
)
|
|
749
|
+
if self.bearer_token:
|
|
750
|
+
# urllib copies only Request.headers to a redirect; the bearer
|
|
751
|
+
# token stays with this request and never reaches another host.
|
|
752
|
+
outbound.add_unredirected_header("Authorization", f"Bearer {self.bearer_token}")
|
|
730
753
|
with urllib_request.urlopen(outbound, timeout=self.timeout_seconds) as response:
|
|
731
754
|
body = response.read(4096).decode("utf-8", errors="replace")
|
|
732
755
|
return body or str(response.status)
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
-
import json
|
|
7
6
|
import os
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from uuid import uuid4
|
|
10
9
|
|
|
10
|
+
from . import held
|
|
11
11
|
from .contracts import Permission
|
|
12
|
-
from .policy import
|
|
12
|
+
from .policy import action_for, check
|
|
13
13
|
from .runtime import local_runtime
|
|
14
14
|
from .todos import CanonicalTodoService
|
|
15
15
|
|
|
@@ -40,22 +40,25 @@ def _require(
|
|
|
40
40
|
decision = runtime.authorize(actor, permission, (resource,))
|
|
41
41
|
if not decision.allowed:
|
|
42
42
|
raise PermissionError("; ".join(decision.reasons) or f"todo {permission.value} denied")
|
|
43
|
-
if
|
|
43
|
+
if not canonical_path:
|
|
44
|
+
return decision, None
|
|
45
|
+
verdict = check(decision, canonical_path, action_for(decision.permission), root=runtime.canonical_root)
|
|
46
|
+
if not verdict.allowed:
|
|
44
47
|
raise PermissionError("todo path is outside the actor's authorized scope")
|
|
45
|
-
return decision
|
|
48
|
+
return decision, verdict.resolved # readers open the path the predicate resolved
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
def _list(args):
|
|
49
52
|
runtime, actor, service, default_person = _context()
|
|
50
53
|
person = args.person or default_person
|
|
51
|
-
_require(
|
|
54
|
+
decision, source = _require(
|
|
52
55
|
runtime,
|
|
53
56
|
actor,
|
|
54
57
|
Permission.READ,
|
|
55
58
|
f"todos:{person}",
|
|
56
59
|
canonical_path=service.canonical_path(person),
|
|
57
60
|
)
|
|
58
|
-
snapshot = service.read(person)
|
|
61
|
+
snapshot = service.read(person, source=source)
|
|
59
62
|
rows = list(snapshot.todos)
|
|
60
63
|
if not args.all:
|
|
61
64
|
rows = [row for row in rows if row.get("status") in {"open", "blocked", "deferred"}]
|
|
@@ -63,8 +66,8 @@ def _list(args):
|
|
|
63
66
|
key=lambda row: (int(row.get("priority") or 0), str(row.get("created") or "")),
|
|
64
67
|
reverse=True,
|
|
65
68
|
)
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
return held.emit(decision, {"person": snapshot.person, "todos": rows}, root=runtime.canonical_root,
|
|
70
|
+
paths=(service.canonical_path(person),))
|
|
68
71
|
|
|
69
72
|
|
|
70
73
|
def _add(args):
|
|
@@ -84,8 +87,8 @@ def _add(args):
|
|
|
84
87
|
priority=args.priority,
|
|
85
88
|
quest=args.quest,
|
|
86
89
|
)
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
return held.emit_for(runtime, actor, {"todo": row, "writeback": receipt.to_dict()}) or (
|
|
91
|
+
0 if receipt.status.value in {"accepted", "partial"} else 1)
|
|
89
92
|
|
|
90
93
|
|
|
91
94
|
def _transition(args):
|
|
@@ -104,8 +107,8 @@ def _transition(args):
|
|
|
104
107
|
todo_id=args.id,
|
|
105
108
|
status=args.command,
|
|
106
109
|
)
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
return held.emit_for(runtime, actor, {"todo": row, "writeback": receipt.to_dict()}) or (
|
|
111
|
+
0 if receipt.status.value in {"accepted", "partial"} else 1)
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
def _parser():
|
|
@@ -159,8 +159,9 @@ class CanonicalTodoService:
|
|
|
159
159
|
def canonical_path(person: str) -> str:
|
|
160
160
|
return f"memory/todos/{_slug(person)}.md"
|
|
161
161
|
|
|
162
|
-
def read(self, person: str) -> TodoSnapshot:
|
|
163
|
-
|
|
162
|
+
def read(self, person: str, *, source: Path | None = None) -> TodoSnapshot:
|
|
163
|
+
"""Read a person's todos; a read surface passes the ``source`` the predicate resolved."""
|
|
164
|
+
path = source or self._path(person)
|
|
164
165
|
if not path.exists():
|
|
165
166
|
return TodoSnapshot(_slug(person), False, ())
|
|
166
167
|
return parse_todo_markdown(path.read_text(encoding="utf-8"), person=person)
|