@openrig/cli 0.5.4 → 0.5.5
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/daemon/assets/guidance/openrig-start.md +7 -0
- package/daemon/assets/onboarding/01-world-and-purpose.md +52 -0
- package/daemon/assets/onboarding/02-self-and-competent-action.md +57 -0
- package/daemon/assets/plugins/openrig-core/README.md +5 -2
- package/daemon/assets/plugins/openrig-core/hooks/claude.json +3 -12
- package/daemon/assets/plugins/openrig-core/hooks/codex.json +5 -12
- package/daemon/assets/plugins/openrig-core/hooks/scripts/refocus.cjs +194 -124
- package/daemon/assets/plugins/openrig-core/skills/mission-slice-sop/SKILL.md +18 -23
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/CHANGELOG.md +92 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/REVISION-GUIDE.md +34 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/ROADMAP.md +23 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/ROLLOUT.md +234 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/SKILL.md +404 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/scripts/compose.py +653 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/scripts/scaffold.sh +34 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/scripts/trace-due.sh +32 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/scripts/trace-stamp.sh +5 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/scripts/trunk-diff.sh +18 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/templates/LEARNED.md +40 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/templates/NOTES.md +9 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/templates/PLAYBOOK.md +5 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/templates/SOP.md +24 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-operating-model/templates/SPEC.md +54 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-skills/SKILL.md +2 -0
- package/daemon/assets/plugins/openrig-core/skills/refocusing/SKILL.md +31 -0
- package/daemon/assets/plugins/openrig-core/skills/refocusing/references/refocus.md +22 -0
- package/daemon/assets/plugins/openrig-core/skills/refocusing/scripts/trace-to-root.py +221 -0
- package/daemon/assets/plugins/openrig-core/skills/retiring-and-inheriting-a-seat/SKILL.md +3 -3
- package/daemon/context-packs/onboarding-width/manifest.yaml +11 -0
- package/daemon/context-packs/{world/install/reference-material.md → onboarding-width/public-reference-material.md} +4 -26
- package/daemon/context-packs/{world/install/what-you-can-do.md → onboarding-width/public-what-you-can-do.md} +13 -9
- package/daemon/context-packs/skills/core/agent-starters/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/agent-startup-and-context-ingestion/SKILL.md +1 -1
- package/daemon/context-packs/skills/core/agent-startup-and-context-ingestion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/attention-queue/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/cross-host-rig-commands/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/human-in-the-loop/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-architect/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-cmux/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-herdr/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-upgrade/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-bundles-and-shareable-artifacts/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-lifecycle/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/session-source-fork/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/specification-system/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/topology-mutation-and-seat-management/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/watchdog/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/backlog-capture/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/context-builder/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/exec-summary/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/office-hours/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/plan-review/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/requirements-writer/SKILL.md +21 -15
- package/daemon/context-packs/skills/pm/requirements-writer/manifest.yaml +3 -3
- package/daemon/context-packs/skills/pm/ui-mockup/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/development-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/orchestration-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/oversight-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/review-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/agent-browser/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/brainstorming/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/context-engineering/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/dogfood/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/executing-plans/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/frontend-design/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/systematic-debugging/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/test-driven-development/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/using-superpowers/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/verification-before-completion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/writing-plans/manifest.yaml +1 -1
- package/daemon/context-packs/world-example/manifest.yaml +8 -0
- package/daemon/context-packs/world-example/your-world.md +37 -0
- package/daemon/dist/adapters/claude-code-adapter.d.ts +15 -0
- package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-code-adapter.js +57 -0
- package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
- package/daemon/dist/build-info.js +3 -3
- package/daemon/dist/db/all-migrations.d.ts.map +1 -1
- package/daemon/dist/db/all-migrations.js +4 -0
- package/daemon/dist/db/all-migrations.js.map +1 -1
- package/daemon/dist/db/migrations/072_thread_seat_map.d.ts +3 -0
- package/daemon/dist/db/migrations/072_thread_seat_map.d.ts.map +1 -0
- package/daemon/dist/db/migrations/072_thread_seat_map.js +22 -0
- package/daemon/dist/db/migrations/072_thread_seat_map.js.map +1 -0
- package/daemon/dist/db/migrations/073_queue_transition_wakes.d.ts +3 -0
- package/daemon/dist/db/migrations/073_queue_transition_wakes.d.ts.map +1 -0
- package/daemon/dist/db/migrations/073_queue_transition_wakes.js +21 -0
- package/daemon/dist/db/migrations/073_queue_transition_wakes.js.map +1 -0
- package/daemon/dist/domain/activity-taxonomy.d.ts +112 -0
- package/daemon/dist/domain/activity-taxonomy.d.ts.map +1 -0
- package/daemon/dist/domain/activity-taxonomy.js +99 -0
- package/daemon/dist/domain/activity-taxonomy.js.map +1 -0
- package/daemon/dist/domain/bind-plan.d.ts +19 -0
- package/daemon/dist/domain/bind-plan.d.ts.map +1 -0
- package/daemon/dist/domain/bind-plan.js +25 -0
- package/daemon/dist/domain/bind-plan.js.map +1 -0
- package/daemon/dist/domain/event-bus.d.ts +6 -0
- package/daemon/dist/domain/event-bus.d.ts.map +1 -1
- package/daemon/dist/domain/event-bus.js +15 -5
- package/daemon/dist/domain/event-bus.js.map +1 -1
- package/daemon/dist/domain/gateway/gateway-process-main.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/gateway-process-main.js +9 -0
- package/daemon/dist/domain/gateway/gateway-process-main.js.map +1 -1
- package/daemon/dist/domain/gateway/gateway-process.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/gateway-process.js +9 -0
- package/daemon/dist/domain/gateway/gateway-process.js.map +1 -1
- package/daemon/dist/domain/gateway/gateway-subsystem.d.ts +80 -0
- package/daemon/dist/domain/gateway/gateway-subsystem.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/gateway-subsystem.js +149 -0
- package/daemon/dist/domain/gateway/gateway-subsystem.js.map +1 -0
- package/daemon/dist/domain/gateway/human-registry.d.ts +109 -0
- package/daemon/dist/domain/gateway/human-registry.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/human-registry.js +250 -0
- package/daemon/dist/domain/gateway/human-registry.js.map +1 -1
- package/{dist → daemon/dist/domain/gateway}/slack/config.d.ts +8 -5
- package/daemon/dist/domain/gateway/slack/config.d.ts.map +1 -0
- package/{dist → daemon/dist/domain/gateway}/slack/config.js +8 -6
- package/daemon/dist/domain/gateway/slack/config.js.map +1 -0
- package/{dist → daemon/dist/domain/gateway}/slack/inbound-admission.d.ts +1 -1
- package/daemon/dist/domain/gateway/slack/inbound-admission.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/inbound-admission.js.map +1 -0
- package/{dist → daemon/dist/domain/gateway}/slack/inbound.d.ts +14 -3
- package/daemon/dist/domain/gateway/slack/inbound.d.ts.map +1 -0
- package/{dist → daemon/dist/domain/gateway}/slack/inbound.js +6 -5
- package/daemon/dist/domain/gateway/slack/inbound.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/message.d.ts +80 -0
- package/daemon/dist/domain/gateway/slack/message.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/message.js +164 -0
- package/daemon/dist/domain/gateway/slack/message.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/outbound-driver.d.ts +54 -0
- package/daemon/dist/domain/gateway/slack/outbound-driver.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/outbound-driver.js +96 -0
- package/daemon/dist/domain/gateway/slack/outbound-driver.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/queue-access.d.ts +53 -0
- package/daemon/dist/domain/gateway/slack/queue-access.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/queue-access.js +72 -0
- package/daemon/dist/domain/gateway/slack/queue-access.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/secrets.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/secrets.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-api.d.ts +106 -0
- package/daemon/dist/domain/gateway/slack/slack-api.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-api.js +198 -0
- package/daemon/dist/domain/gateway/slack/slack-api.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-delivery.d.ts +47 -0
- package/daemon/dist/domain/gateway/slack/slack-delivery.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-delivery.js +147 -0
- package/daemon/dist/domain/gateway/slack/slack-delivery.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-subsystem.d.ts +21 -0
- package/daemon/dist/domain/gateway/slack/slack-subsystem.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/slack-subsystem.js +198 -0
- package/daemon/dist/domain/gateway/slack/slack-subsystem.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/socket-inbound.d.ts +30 -0
- package/daemon/dist/domain/gateway/slack/socket-inbound.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/socket-inbound.js +99 -0
- package/daemon/dist/domain/gateway/slack/socket-inbound.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/state-store.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/state-store.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/thread-routing.d.ts +17 -0
- package/daemon/dist/domain/gateway/slack/thread-routing.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/thread-routing.js +35 -0
- package/daemon/dist/domain/gateway/slack/thread-routing.js.map +1 -0
- package/daemon/dist/domain/gateway/slack/thread-seat-map.d.ts +56 -0
- package/daemon/dist/domain/gateway/slack/thread-seat-map.d.ts.map +1 -0
- package/daemon/dist/domain/gateway/slack/thread-seat-map.js +103 -0
- package/daemon/dist/domain/gateway/slack/thread-seat-map.js.map +1 -0
- package/daemon/dist/domain/gateway/spawn-gateway.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/spawn-gateway.js +9 -0
- package/daemon/dist/domain/gateway/spawn-gateway.js.map +1 -1
- package/daemon/dist/domain/gateway/transport.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/transport.js +9 -0
- package/daemon/dist/domain/gateway/transport.js.map +1 -1
- package/daemon/dist/domain/node-inventory.d.ts.map +1 -1
- package/daemon/dist/domain/node-inventory.js +20 -0
- package/daemon/dist/domain/node-inventory.js.map +1 -1
- package/daemon/dist/domain/parked-query.d.ts +81 -0
- package/daemon/dist/domain/parked-query.d.ts.map +1 -0
- package/daemon/dist/domain/parked-query.js +126 -0
- package/daemon/dist/domain/parked-query.js.map +1 -0
- package/daemon/dist/domain/queue-pickup.d.ts +38 -0
- package/daemon/dist/domain/queue-pickup.d.ts.map +1 -0
- package/daemon/dist/domain/queue-pickup.js +67 -0
- package/daemon/dist/domain/queue-pickup.js.map +1 -0
- package/daemon/dist/domain/queue-repository.d.ts +38 -10
- package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
- package/daemon/dist/domain/queue-repository.js +267 -35
- package/daemon/dist/domain/queue-repository.js.map +1 -1
- package/daemon/dist/domain/queue-stuck-sweep.d.ts +77 -0
- package/daemon/dist/domain/queue-stuck-sweep.d.ts.map +1 -0
- package/daemon/dist/domain/queue-stuck-sweep.js +348 -0
- package/daemon/dist/domain/queue-stuck-sweep.js.map +1 -0
- package/daemon/dist/domain/queue-wake-ladder.d.ts +96 -0
- package/daemon/dist/domain/queue-wake-ladder.d.ts.map +1 -0
- package/daemon/dist/domain/queue-wake-ladder.js +533 -0
- package/daemon/dist/domain/queue-wake-ladder.js.map +1 -0
- package/daemon/dist/domain/queue-wake-repository.d.ts +37 -0
- package/daemon/dist/domain/queue-wake-repository.d.ts.map +1 -0
- package/daemon/dist/domain/queue-wake-repository.js +80 -0
- package/daemon/dist/domain/queue-wake-repository.js.map +1 -0
- package/daemon/dist/domain/rebuild-priming-chain.d.ts +28 -0
- package/daemon/dist/domain/rebuild-priming-chain.d.ts.map +1 -0
- package/daemon/dist/domain/rebuild-priming-chain.js +71 -0
- package/daemon/dist/domain/rebuild-priming-chain.js.map +1 -0
- package/daemon/dist/domain/review/compose.d.ts +3 -1
- package/daemon/dist/domain/review/compose.d.ts.map +1 -1
- package/daemon/dist/domain/review/compose.js +14 -8
- package/daemon/dist/domain/review/compose.js.map +1 -1
- package/daemon/dist/domain/review/gather.d.ts.map +1 -1
- package/daemon/dist/domain/review/gather.js +3 -1
- package/daemon/dist/domain/review/gather.js.map +1 -1
- package/daemon/dist/domain/rigspec-instantiator.d.ts +3 -0
- package/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
- package/daemon/dist/domain/rigspec-instantiator.js +18 -0
- package/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
- package/daemon/dist/domain/scope/plan-lock-artifacts.d.ts +6 -5
- package/daemon/dist/domain/scope/plan-lock-artifacts.d.ts.map +1 -1
- package/daemon/dist/domain/scope/plan-lock-artifacts.js +23 -20
- package/daemon/dist/domain/scope/plan-lock-artifacts.js.map +1 -1
- package/daemon/dist/domain/scope/scaffold-placeholder.d.ts +4 -5
- package/daemon/dist/domain/scope/scaffold-placeholder.d.ts.map +1 -1
- package/daemon/dist/domain/scope/scaffold-placeholder.js +6 -7
- package/daemon/dist/domain/scope/scaffold-placeholder.js.map +1 -1
- package/daemon/dist/domain/scope/scope-approve.d.ts +1 -1
- package/daemon/dist/domain/scope/scope-approve.d.ts.map +1 -1
- package/daemon/dist/domain/scope/scope-approve.js +5 -4
- package/daemon/dist/domain/scope/scope-approve.js.map +1 -1
- package/daemon/dist/domain/scope/scope-audit.d.ts +42 -3
- package/daemon/dist/domain/scope/scope-audit.d.ts.map +1 -1
- package/daemon/dist/domain/scope/scope-audit.js +78 -93
- package/daemon/dist/domain/scope/scope-audit.js.map +1 -1
- package/daemon/dist/domain/scope/scope-view-projection.d.ts.map +1 -1
- package/daemon/dist/domain/scope/scope-view-projection.js +7 -2
- package/daemon/dist/domain/scope/scope-view-projection.js.map +1 -1
- package/daemon/dist/domain/seat-activity-service.d.ts +91 -0
- package/daemon/dist/domain/seat-activity-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-activity-service.js +416 -1
- package/daemon/dist/domain/seat-activity-service.js.map +1 -1
- package/daemon/dist/domain/seat-handover-planner.d.ts +14 -0
- package/daemon/dist/domain/seat-handover-planner.d.ts.map +1 -1
- package/daemon/dist/domain/seat-handover-planner.js +14 -1
- package/daemon/dist/domain/seat-handover-planner.js.map +1 -1
- package/daemon/dist/domain/seat-handover-service.d.ts +54 -1
- package/daemon/dist/domain/seat-handover-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-handover-service.js +162 -19
- package/daemon/dist/domain/seat-handover-service.js.map +1 -1
- package/daemon/dist/domain/session-transport.js +1 -2
- package/daemon/dist/domain/session-transport.js.map +1 -1
- package/daemon/dist/domain/successor-session-launcher.d.ts +6 -1
- package/daemon/dist/domain/successor-session-launcher.d.ts.map +1 -1
- package/daemon/dist/domain/successor-session-launcher.js +3 -3
- package/daemon/dist/domain/successor-session-launcher.js.map +1 -1
- package/daemon/dist/domain/types.d.ts +33 -0
- package/daemon/dist/domain/types.d.ts.map +1 -1
- package/daemon/dist/domain/types.js.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.js +48 -0
- package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
- package/daemon/dist/domain/view-projector.d.ts +1 -1
- package/daemon/dist/domain/view-projector.d.ts.map +1 -1
- package/daemon/dist/domain/view-projector.js +41 -2
- package/daemon/dist/domain/view-projector.js.map +1 -1
- package/daemon/dist/domain/watchdog-policy-engine.d.ts +7 -0
- package/daemon/dist/domain/watchdog-policy-engine.d.ts.map +1 -1
- package/daemon/dist/domain/watchdog-policy-engine.js +3 -0
- package/daemon/dist/domain/watchdog-policy-engine.js.map +1 -1
- package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts +4 -3
- package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
- package/daemon/dist/domain/workspace/default-workspace-scaffold.js +56 -196
- package/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
- package/daemon/dist/domain/workspace/getting-started-narrative.js +1 -1
- package/daemon/dist/domain/workspace/getting-started-narrative.js.map +1 -1
- package/daemon/dist/domain/workspace/workspace-doctor.d.ts +8 -11
- package/daemon/dist/domain/workspace/workspace-doctor.d.ts.map +1 -1
- package/daemon/dist/domain/workspace/workspace-doctor.js +23 -25
- package/daemon/dist/domain/workspace/workspace-doctor.js.map +1 -1
- package/daemon/dist/gateway-slack-surface.d.ts +4 -0
- package/daemon/dist/gateway-slack-surface.d.ts.map +1 -0
- package/daemon/dist/gateway-slack-surface.js +8 -0
- package/daemon/dist/gateway-slack-surface.js.map +1 -0
- package/daemon/dist/index.d.ts +29 -0
- package/daemon/dist/index.d.ts.map +1 -1
- package/daemon/dist/index.js +99 -4
- package/daemon/dist/index.js.map +1 -1
- package/daemon/dist/lib/pane-envelope.d.ts +1 -1
- package/daemon/dist/lib/pane-envelope.d.ts.map +1 -1
- package/daemon/dist/lib/pane-envelope.js +8 -14
- package/daemon/dist/lib/pane-envelope.js.map +1 -1
- package/daemon/dist/routes/activity.d.ts +13 -0
- package/daemon/dist/routes/activity.d.ts.map +1 -1
- package/daemon/dist/routes/activity.js +186 -0
- package/daemon/dist/routes/activity.js.map +1 -1
- package/daemon/dist/routes/config.js +2 -2
- package/daemon/dist/routes/config.js.map +1 -1
- package/daemon/dist/routes/gateway.d.ts +3 -0
- package/daemon/dist/routes/gateway.d.ts.map +1 -0
- package/daemon/dist/routes/gateway.js +46 -0
- package/daemon/dist/routes/gateway.js.map +1 -0
- package/daemon/dist/routes/health-summary.d.ts.map +1 -1
- package/daemon/dist/routes/health-summary.js +8 -0
- package/daemon/dist/routes/health-summary.js.map +1 -1
- package/daemon/dist/routes/queue.d.ts.map +1 -1
- package/daemon/dist/routes/queue.js +3 -1
- package/daemon/dist/routes/queue.js.map +1 -1
- package/daemon/dist/routes/scope-audit.d.ts.map +1 -1
- package/daemon/dist/routes/scope-audit.js +72 -13
- package/daemon/dist/routes/scope-audit.js.map +1 -1
- package/daemon/dist/routes/seat.d.ts.map +1 -1
- package/daemon/dist/routes/seat.js +15 -0
- package/daemon/dist/routes/seat.js.map +1 -1
- package/daemon/dist/server.d.ts +17 -0
- package/daemon/dist/server.d.ts.map +1 -1
- package/daemon/dist/server.js +25 -4
- package/daemon/dist/server.js.map +1 -1
- package/daemon/dist/startup.d.ts +4 -0
- package/daemon/dist/startup.d.ts.map +1 -1
- package/daemon/dist/startup.js +33 -0
- package/daemon/dist/startup.js.map +1 -1
- package/daemon/docs/reference/agent-state-taxonomy.md +106 -0
- package/daemon/docs/reference/project-workspace.md +22 -14
- package/daemon/docs/reference/refocus-channel.md +27 -14
- package/daemon/docs/reference/sdlc-conventions.md +24 -13
- package/daemon/specs/agents/shared/skills/core/agent-startup-and-context-ingestion/SKILL.md +1 -1
- package/daemon/specs/agents/shared/skills/pm/requirements-writer/SKILL.md +21 -15
- package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/guidance/role.md +1 -1
- package/dist/build-info.js +3 -3
- package/dist/commands/config-init-workspace.d.ts.map +1 -1
- package/dist/commands/config-init-workspace.js +32 -57
- package/dist/commands/config-init-workspace.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +5 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +14 -4
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/gateway.d.ts +19 -1
- package/dist/commands/gateway.d.ts.map +1 -1
- package/dist/commands/gateway.js +157 -33
- package/dist/commands/gateway.js.map +1 -1
- package/dist/commands/parked.d.ts +3 -0
- package/dist/commands/parked.d.ts.map +1 -0
- package/dist/commands/parked.js +83 -0
- package/dist/commands/parked.js.map +1 -0
- package/dist/commands/proof.d.ts +2 -1
- package/dist/commands/proof.d.ts.map +1 -1
- package/dist/commands/proof.js +8 -8
- package/dist/commands/proof.js.map +1 -1
- package/dist/commands/ps.d.ts +10 -0
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +14 -3
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/queue.d.ts.map +1 -1
- package/dist/commands/queue.js +31 -3
- package/dist/commands/queue.js.map +1 -1
- package/dist/commands/scope.d.ts.map +1 -1
- package/dist/commands/scope.js +255 -136
- package/dist/commands/scope.js.map +1 -1
- package/dist/commands/seat.d.ts.map +1 -1
- package/dist/commands/seat.js +40 -10
- package/dist/commands/seat.js.map +1 -1
- package/dist/commands/send.d.ts +1 -1
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/send.js +13 -14
- package/dist/commands/send.js.map +1 -1
- package/dist/commands/slack.d.ts +14 -28
- package/dist/commands/slack.d.ts.map +1 -1
- package/dist/commands/slack.js +73 -187
- package/dist/commands/slack.js.map +1 -1
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +12 -5
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +11 -4
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/view.d.ts +4 -2
- package/dist/commands/view.d.ts.map +1 -1
- package/dist/commands/view.js +1 -1
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/watchdog.d.ts.map +1 -1
- package/dist/commands/watchdog.js +2 -1
- package/dist/commands/watchdog.js.map +1 -1
- package/dist/commands/workspace.js +1 -1
- package/dist/config-store.d.ts +15 -1
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +60 -0
- package/dist/config-store.js.map +1 -1
- package/dist/cross-host-target.d.ts.map +1 -1
- package/dist/cross-host-target.js +5 -4
- package/dist/cross-host-target.js.map +1 -1
- package/dist/daemon-lifecycle.d.ts +45 -3
- package/dist/daemon-lifecycle.d.ts.map +1 -1
- package/dist/daemon-lifecycle.js +126 -0
- package/dist/daemon-lifecycle.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/scope/capability-delta.d.ts +9 -0
- package/dist/lib/scope/capability-delta.d.ts.map +1 -0
- package/dist/lib/scope/capability-delta.js +73 -0
- package/dist/lib/scope/capability-delta.js.map +1 -0
- package/dist/lib/scope/scaffold-placeholder.d.ts +4 -5
- package/dist/lib/scope/scaffold-placeholder.d.ts.map +1 -1
- package/dist/lib/scope/scaffold-placeholder.js +6 -7
- package/dist/lib/scope/scaffold-placeholder.js.map +1 -1
- package/dist/lib/scope/scope-audit.d.ts +42 -3
- package/dist/lib/scope/scope-audit.d.ts.map +1 -1
- package/dist/lib/scope/scope-audit.js +78 -93
- package/dist/lib/scope/scope-audit.js.map +1 -1
- package/dist/lib/scope/scope-fs.d.ts +18 -14
- package/dist/lib/scope/scope-fs.d.ts.map +1 -1
- package/dist/lib/scope/scope-fs.js +60 -29
- package/dist/lib/scope/scope-fs.js.map +1 -1
- package/dist/lib/scope/templates.d.ts +17 -17
- package/dist/lib/scope/templates.d.ts.map +1 -1
- package/dist/lib/scope/templates.js +35 -39
- package/dist/lib/scope/templates.js.map +1 -1
- package/dist/lib/scope-templates/backlog-deprecation.md +3 -1
- package/dist/lib/scope-templates/backlog-tech-debt.md +3 -1
- package/dist/lib/scope-templates/bug-fix.md +3 -1
- package/dist/lib/scope-templates/capability-delta.md +60 -0
- package/dist/lib/scope-templates/mission-placeholder.md +9 -40
- package/dist/lib/scope-templates/mission-progress.md +5 -6
- package/dist/lib/scope-templates/mission-release.md +9 -40
- package/dist/lib/scope-templates/notes.md +14 -0
- package/dist/lib/scope-templates/placeholder.md +3 -1
- package/dist/lib/scope-templates/proof.md +1 -1
- package/dist/lib/scope-templates/release-feature.md +3 -1
- package/dist/lib/scope-templates/research.md +3 -1
- package/dist/lib/scope-templates/slice-progress.md +4 -5
- package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.d.ts +15 -0
- package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.js +57 -0
- package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/build-info.js +3 -3
- package/node_modules/@openrig/daemon/dist/db/all-migrations.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/db/all-migrations.js +4 -0
- package/node_modules/@openrig/daemon/dist/db/all-migrations.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/db/migrations/072_thread_seat_map.d.ts +3 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/072_thread_seat_map.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/072_thread_seat_map.js +22 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/072_thread_seat_map.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/073_queue_transition_wakes.d.ts +3 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/073_queue_transition_wakes.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/073_queue_transition_wakes.js +21 -0
- package/node_modules/@openrig/daemon/dist/db/migrations/073_queue_transition_wakes.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/activity-taxonomy.d.ts +112 -0
- package/node_modules/@openrig/daemon/dist/domain/activity-taxonomy.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/activity-taxonomy.js +99 -0
- package/node_modules/@openrig/daemon/dist/domain/activity-taxonomy.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/bind-plan.d.ts +19 -0
- package/node_modules/@openrig/daemon/dist/domain/bind-plan.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/bind-plan.js +25 -0
- package/node_modules/@openrig/daemon/dist/domain/bind-plan.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/event-bus.d.ts +6 -0
- package/node_modules/@openrig/daemon/dist/domain/event-bus.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/event-bus.js +15 -5
- package/node_modules/@openrig/daemon/dist/domain/event-bus.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process-main.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process-main.js +9 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process-main.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process.js +9 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-process.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-subsystem.d.ts +80 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-subsystem.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-subsystem.js +149 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/gateway-subsystem.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/human-registry.d.ts +109 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/human-registry.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/human-registry.js +250 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/human-registry.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/config.d.ts +44 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/config.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/config.js +62 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/config.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound-admission.d.ts +8 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound-admission.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound-admission.js +20 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound-admission.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound.d.ts +113 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound.js +146 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/inbound.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/message.d.ts +80 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/message.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/message.js +164 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/message.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/outbound-driver.d.ts +54 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/outbound-driver.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/outbound-driver.js +96 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/outbound-driver.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/queue-access.d.ts +53 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/queue-access.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/queue-access.js +72 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/queue-access.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/secrets.d.ts +21 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/secrets.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/secrets.js +73 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/secrets.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-api.d.ts +106 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-api.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-api.js +198 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-api.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-delivery.d.ts +47 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-delivery.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-delivery.js +147 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-delivery.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-subsystem.d.ts +21 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-subsystem.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-subsystem.js +198 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/slack-subsystem.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/socket-inbound.d.ts +30 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/socket-inbound.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/socket-inbound.js +99 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/socket-inbound.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/state-store.d.ts +62 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/state-store.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/state-store.js +132 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/state-store.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-routing.d.ts +17 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-routing.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-routing.js +35 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-routing.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-seat-map.d.ts +56 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-seat-map.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-seat-map.js +103 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/slack/thread-seat-map.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/spawn-gateway.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/spawn-gateway.js +9 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/spawn-gateway.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/transport.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/gateway/transport.js +9 -0
- package/node_modules/@openrig/daemon/dist/domain/gateway/transport.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/node-inventory.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/node-inventory.js +20 -0
- package/node_modules/@openrig/daemon/dist/domain/node-inventory.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/parked-query.d.ts +81 -0
- package/node_modules/@openrig/daemon/dist/domain/parked-query.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/parked-query.js +126 -0
- package/node_modules/@openrig/daemon/dist/domain/parked-query.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-pickup.d.ts +38 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-pickup.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-pickup.js +67 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-pickup.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-repository.d.ts +38 -10
- package/node_modules/@openrig/daemon/dist/domain/queue-repository.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/queue-repository.js +267 -35
- package/node_modules/@openrig/daemon/dist/domain/queue-repository.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/queue-stuck-sweep.d.ts +77 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-stuck-sweep.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-stuck-sweep.js +348 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-stuck-sweep.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-ladder.d.ts +96 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-ladder.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-ladder.js +533 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-ladder.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-repository.d.ts +37 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-repository.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-repository.js +80 -0
- package/node_modules/@openrig/daemon/dist/domain/queue-wake-repository.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/rebuild-priming-chain.d.ts +28 -0
- package/node_modules/@openrig/daemon/dist/domain/rebuild-priming-chain.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/rebuild-priming-chain.js +71 -0
- package/node_modules/@openrig/daemon/dist/domain/rebuild-priming-chain.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/domain/review/compose.d.ts +3 -1
- package/node_modules/@openrig/daemon/dist/domain/review/compose.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/review/compose.js +14 -8
- package/node_modules/@openrig/daemon/dist/domain/review/compose.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/review/gather.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/review/gather.js +3 -1
- package/node_modules/@openrig/daemon/dist/domain/review/gather.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.d.ts +3 -0
- package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.js +18 -0
- package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/plan-lock-artifacts.d.ts +6 -5
- package/node_modules/@openrig/daemon/dist/domain/scope/plan-lock-artifacts.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/plan-lock-artifacts.js +23 -20
- package/node_modules/@openrig/daemon/dist/domain/scope/plan-lock-artifacts.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scaffold-placeholder.d.ts +4 -5
- package/node_modules/@openrig/daemon/dist/domain/scope/scaffold-placeholder.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scaffold-placeholder.js +6 -7
- package/node_modules/@openrig/daemon/dist/domain/scope/scaffold-placeholder.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-approve.d.ts +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-approve.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-approve.js +5 -4
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-approve.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-audit.d.ts +42 -3
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-audit.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-audit.js +78 -93
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-audit.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-view-projection.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-view-projection.js +7 -2
- package/node_modules/@openrig/daemon/dist/domain/scope/scope-view-projection.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-activity-service.d.ts +91 -0
- package/node_modules/@openrig/daemon/dist/domain/seat-activity-service.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-activity-service.js +416 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-activity-service.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-planner.d.ts +14 -0
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-planner.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-planner.js +14 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-planner.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-service.d.ts +54 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-service.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-service.js +162 -19
- package/node_modules/@openrig/daemon/dist/domain/seat-handover-service.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/session-transport.js +1 -2
- package/node_modules/@openrig/daemon/dist/domain/session-transport.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/successor-session-launcher.d.ts +6 -1
- package/node_modules/@openrig/daemon/dist/domain/successor-session-launcher.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/successor-session-launcher.js +3 -3
- package/node_modules/@openrig/daemon/dist/domain/successor-session-launcher.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/types.d.ts +33 -0
- package/node_modules/@openrig/daemon/dist/domain/types.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/types.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.d.ts +1 -1
- package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.js +48 -0
- package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/view-projector.d.ts +1 -1
- package/node_modules/@openrig/daemon/dist/domain/view-projector.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/view-projector.js +41 -2
- package/node_modules/@openrig/daemon/dist/domain/view-projector.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.d.ts +7 -0
- package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.js +3 -0
- package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts +4 -3
- package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.js +56 -196
- package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/getting-started-narrative.js +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/getting-started-narrative.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/workspace-doctor.d.ts +8 -11
- package/node_modules/@openrig/daemon/dist/domain/workspace/workspace-doctor.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/domain/workspace/workspace-doctor.js +23 -25
- package/node_modules/@openrig/daemon/dist/domain/workspace/workspace-doctor.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/gateway-slack-surface.d.ts +4 -0
- package/node_modules/@openrig/daemon/dist/gateway-slack-surface.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/gateway-slack-surface.js +8 -0
- package/node_modules/@openrig/daemon/dist/gateway-slack-surface.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/index.d.ts +29 -0
- package/node_modules/@openrig/daemon/dist/index.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/index.js +99 -4
- package/node_modules/@openrig/daemon/dist/index.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/lib/pane-envelope.d.ts +1 -1
- package/node_modules/@openrig/daemon/dist/lib/pane-envelope.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/lib/pane-envelope.js +8 -14
- package/node_modules/@openrig/daemon/dist/lib/pane-envelope.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/activity.d.ts +13 -0
- package/node_modules/@openrig/daemon/dist/routes/activity.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/activity.js +186 -0
- package/node_modules/@openrig/daemon/dist/routes/activity.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/config.js +2 -2
- package/node_modules/@openrig/daemon/dist/routes/config.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/gateway.d.ts +3 -0
- package/node_modules/@openrig/daemon/dist/routes/gateway.d.ts.map +1 -0
- package/node_modules/@openrig/daemon/dist/routes/gateway.js +46 -0
- package/node_modules/@openrig/daemon/dist/routes/gateway.js.map +1 -0
- package/node_modules/@openrig/daemon/dist/routes/health-summary.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/health-summary.js +8 -0
- package/node_modules/@openrig/daemon/dist/routes/health-summary.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/queue.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/queue.js +3 -1
- package/node_modules/@openrig/daemon/dist/routes/queue.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/scope-audit.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/scope-audit.js +72 -13
- package/node_modules/@openrig/daemon/dist/routes/scope-audit.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/seat.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/routes/seat.js +15 -0
- package/node_modules/@openrig/daemon/dist/routes/seat.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/server.d.ts +17 -0
- package/node_modules/@openrig/daemon/dist/server.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/server.js +25 -4
- package/node_modules/@openrig/daemon/dist/server.js.map +1 -1
- package/node_modules/@openrig/daemon/dist/startup.d.ts +4 -0
- package/node_modules/@openrig/daemon/dist/startup.d.ts.map +1 -1
- package/node_modules/@openrig/daemon/dist/startup.js +33 -0
- package/node_modules/@openrig/daemon/dist/startup.js.map +1 -1
- package/node_modules/@openrig/daemon/package.json +5 -1
- package/package.json +1 -1
- package/tui/dist/daemon-client.d.ts +5 -0
- package/tui/dist/daemon-client.d.ts.map +1 -1
- package/tui/dist/daemon-client.js +17 -0
- package/tui/dist/daemon-client.js.map +1 -1
- package/tui/dist/hydrate.d.ts.map +1 -1
- package/tui/dist/hydrate.js +12 -4
- package/tui/dist/hydrate.js.map +1 -1
- package/tui/dist/live-events.d.ts +21 -0
- package/tui/dist/live-events.d.ts.map +1 -0
- package/tui/dist/live-events.js +88 -0
- package/tui/dist/live-events.js.map +1 -0
- package/tui/dist/live.js +1 -1
- package/tui/dist/main.js +27 -8
- package/tui/dist/main.js.map +1 -1
- package/tui/dist/refresh.d.ts +10 -1
- package/tui/dist/refresh.d.ts.map +1 -1
- package/tui/dist/refresh.js +22 -2
- package/tui/dist/refresh.js.map +1 -1
- package/daemon/context-packs/world/install/01-world-from-primitives.md +0 -97
- package/daemon/context-packs/world/install/02-permission-self-sleep.md +0 -141
- package/daemon/context-packs/world/install/03-what-this-is-for.md +0 -86
- package/daemon/context-packs/world/install/04-ontology.md +0 -790
- package/daemon/context-packs/world/install/05-harness-power-use.md +0 -355
- package/daemon/context-packs/world/install/06-a-competent-turn.md +0 -225
- package/daemon/context-packs/world/install/manifest.yaml +0 -125
- package/dist/lib/scope-templates/mission-brief.md +0 -20
- package/dist/lib/scope-templates/mission-notes.md +0 -102
- package/dist/slack/config.d.ts.map +0 -1
- package/dist/slack/config.js.map +0 -1
- package/dist/slack/connector-server.d.ts +0 -31
- package/dist/slack/connector-server.d.ts.map +0 -1
- package/dist/slack/connector-server.js +0 -108
- package/dist/slack/connector-server.js.map +0 -1
- package/dist/slack/inbound-admission.d.ts.map +0 -1
- package/dist/slack/inbound-admission.js.map +0 -1
- package/dist/slack/inbound.d.ts.map +0 -1
- package/dist/slack/inbound.js.map +0 -1
- package/dist/slack/message.d.ts +0 -39
- package/dist/slack/message.d.ts.map +0 -1
- package/dist/slack/message.js +0 -88
- package/dist/slack/message.js.map +0 -1
- package/dist/slack/outbound.d.ts +0 -39
- package/dist/slack/outbound.d.ts.map +0 -1
- package/dist/slack/outbound.js +0 -63
- package/dist/slack/outbound.js.map +0 -1
- package/dist/slack/queue-bridge.d.ts +0 -61
- package/dist/slack/queue-bridge.d.ts.map +0 -1
- package/dist/slack/queue-bridge.js +0 -114
- package/dist/slack/queue-bridge.js.map +0 -1
- package/dist/slack/secrets.d.ts.map +0 -1
- package/dist/slack/secrets.js.map +0 -1
- package/dist/slack/slack-api.d.ts +0 -49
- package/dist/slack/slack-api.d.ts.map +0 -1
- package/dist/slack/slack-api.js +0 -110
- package/dist/slack/slack-api.js.map +0 -1
- package/dist/slack/slack-delivery.d.ts +0 -14
- package/dist/slack/slack-delivery.d.ts.map +0 -1
- package/dist/slack/slack-delivery.js +0 -28
- package/dist/slack/slack-delivery.js.map +0 -1
- package/dist/slack/state-store.d.ts.map +0 -1
- package/dist/slack/state-store.js.map +0 -1
- /package/{dist → daemon/dist/domain/gateway}/slack/inbound-admission.js +0 -0
- /package/{dist → daemon/dist/domain/gateway}/slack/secrets.d.ts +0 -0
- /package/{dist → daemon/dist/domain/gateway}/slack/secrets.js +0 -0
- /package/{dist → daemon/dist/domain/gateway}/slack/state-store.d.ts +0 -0
- /package/{dist → daemon/dist/domain/gateway}/slack/state-store.js +0 -0
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""compose.py — leaf-to-root chain composition and subtree renders.
|
|
3
|
+
|
|
4
|
+
SUPERSEDED FOR REFOCUS: the public core reorientation trace lives at
|
|
5
|
+
../../refocusing/scripts/trace-to-root.py. This general composer remains the
|
|
6
|
+
compatibility surface for down/progress and historical up invocations.
|
|
7
|
+
|
|
8
|
+
up <start-dir> --name FILE [--name FILE ...] [--root DIR]
|
|
9
|
+
Walk from start-dir up to root (default: filesystem stops at a dir
|
|
10
|
+
containing .compose-root, or at --root). Emit the chain ROOT-FIRST
|
|
11
|
+
(defaults, then overrides) with provenance headers, and a MISSING-LINK
|
|
12
|
+
report for altitudes without the file — the scream is output, not error.
|
|
13
|
+
|
|
14
|
+
down <root-dir> --name FILE [--name FILE ...] [--exclude GLOB ...]
|
|
15
|
+
Gather every instance of the named files under root-dir.
|
|
16
|
+
|
|
17
|
+
progress <root-dir> --name FILE [--name FILE ...] [--exclude GLOB ...]
|
|
18
|
+
THE DERIVED PROGRESS VIEW (the PROGRESS.md prototype done right):
|
|
19
|
+
count markdown checkboxes in the named files (the mark level), roll
|
|
20
|
+
counts UP the tree, and print a walk-map-shaped tree with done/total
|
|
21
|
+
per level. Never stored in any file — the render is the only home.
|
|
22
|
+
Gather every instance of the named files under root-dir (the subtree
|
|
23
|
+
render; run at the topology root = THE TRUNK RENDER). Sorted by path.
|
|
24
|
+
|
|
25
|
+
Composed output is GENERATED, NEVER EDITED (fragments are the source of truth).
|
|
26
|
+
Seals/locks bind to a render's bytes, not to fragments. Stdlib only.
|
|
27
|
+
"""
|
|
28
|
+
import argparse, os, sys, fnmatch, datetime, re, shutil, subprocess
|
|
29
|
+
|
|
30
|
+
# A SHELF holds instances of an altitude; it is not a position and carries no chain file.
|
|
31
|
+
# Both trees have them: missions/ slices/ (work) and rigs/ pods/ seats/ (topology). Without
|
|
32
|
+
# this list the trace reports every shelf as a gap and the audit tells you to scaffold one —
|
|
33
|
+
# which is litter that inflates the map to a clean-looking 5/5 while adding nothing. Extend
|
|
34
|
+
# with --shelf for a tree that names them differently.
|
|
35
|
+
SHELF_NAMES = {"missions", "slices", "seats", "pods", "rigs"}
|
|
36
|
+
|
|
37
|
+
_TPL_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "templates")
|
|
38
|
+
def _template_bytes(name):
|
|
39
|
+
try:
|
|
40
|
+
return open(os.path.join(_TPL_DIR, name), "rb").read()
|
|
41
|
+
except OSError:
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
def read_state(path):
|
|
45
|
+
"""Detection is DETERMINISTIC-FIRST, declared-second — never memory-reliant:
|
|
46
|
+
1. byte-identical to the shipped template -> 'unseeded' (nobody had to remember anything)
|
|
47
|
+
2. `status: UNSEEDED` marker on content that DIFFERS from the template -> 'conflicted':
|
|
48
|
+
render the content AND scream — real work is never hidden behind a stale field,
|
|
49
|
+
and the disagreement is its own reported state (third-state law).
|
|
50
|
+
3. otherwise -> 'seeded'. Every residual failure mode shows too much plus a scream,
|
|
51
|
+
never hides work and never silently trusts a field."""
|
|
52
|
+
raw = open(path, "rb").read()
|
|
53
|
+
tpl = _template_bytes(os.path.basename(path))
|
|
54
|
+
body = raw.decode("utf-8", errors="replace")
|
|
55
|
+
head = "\n".join(body.splitlines()[:15])
|
|
56
|
+
marked = re.search(r"^status:\s*UNSEEDED", head, re.M)
|
|
57
|
+
if tpl is not None and raw == tpl:
|
|
58
|
+
m = re.search(r"^owners?:\s*(.+)$", head, re.M)
|
|
59
|
+
return "unseeded", (m.group(1).strip() if m else "owner unknown — untouched scaffold")
|
|
60
|
+
if marked:
|
|
61
|
+
return "conflicted", body
|
|
62
|
+
return "seeded", body
|
|
63
|
+
|
|
64
|
+
def hdr(title):
|
|
65
|
+
return f"\n\n<!-- ═══ {title} ═══ -->\n\n## ⟦{title}⟧\n"
|
|
66
|
+
|
|
67
|
+
def frontmatter(payload):
|
|
68
|
+
"""Parse the frontmatter block ONCE. Returns (dict, note); note is set when there is
|
|
69
|
+
nothing to read, so a caller can report the gap rather than silently skip it."""
|
|
70
|
+
if not payload:
|
|
71
|
+
return None, "no content"
|
|
72
|
+
m = re.match(r"^---\n(.*?)\n---\n", payload, re.S)
|
|
73
|
+
if not m:
|
|
74
|
+
return None, "no frontmatter"
|
|
75
|
+
try:
|
|
76
|
+
import yaml
|
|
77
|
+
return (yaml.safe_load(m.group(1)) or {}), None
|
|
78
|
+
except Exception as e:
|
|
79
|
+
return None, f"frontmatter did not parse ({e.__class__.__name__})"
|
|
80
|
+
|
|
81
|
+
def field_of(payload, field):
|
|
82
|
+
"""Extract ONE frontmatter field. Returns (value, note).
|
|
83
|
+
A chain walked by FIELD composes intent without dragging bodies: three sentences
|
|
84
|
+
unfurl, not three documents. A level whose file exists but lacks the field is a
|
|
85
|
+
real gap and is reported as such — never silently skipped."""
|
|
86
|
+
fm, note = frontmatter(payload)
|
|
87
|
+
if fm is None:
|
|
88
|
+
return None, note
|
|
89
|
+
if field not in fm:
|
|
90
|
+
return None, f"no `{field}:` field"
|
|
91
|
+
v = fm[field]
|
|
92
|
+
return (" ".join(str(v).split()) if v is not None else None), None
|
|
93
|
+
|
|
94
|
+
def _cut_at_boundary(s, n):
|
|
95
|
+
"""Cut to AT MOST n chars, NEVER inside a token.
|
|
96
|
+
|
|
97
|
+
Measured 2026-08-14: a cold subject read `see PROOF.m…` and `see P…` in the walk's own
|
|
98
|
+
output. A path cut mid-token still READS as a path — the reader cannot tell `PROOF.m` from
|
|
99
|
+
a file that is actually called that, so a truncation artifact is silently promoted to a
|
|
100
|
+
fact about the tree. Filenames, paths and identifiers are exactly the tokens a reader is
|
|
101
|
+
most likely to act on, which makes them the worst place to lose characters.
|
|
102
|
+
|
|
103
|
+
So the cut lands on whitespace or it does not land: paragraph, then line, then word. A
|
|
104
|
+
single unbroken token longer than the budget is DROPPED WHOLE rather than shortened —
|
|
105
|
+
half an identifier is worse than no identifier."""
|
|
106
|
+
if len(s) <= n:
|
|
107
|
+
return s
|
|
108
|
+
head = s[:n]
|
|
109
|
+
if s[n:n + 1].isspace(): # n already sits on a boundary
|
|
110
|
+
return head.rstrip()
|
|
111
|
+
for sep, floor in (("\n\n", n // 2), ("\n", n // 2), (" ", 0)):
|
|
112
|
+
i = head.rfind(sep)
|
|
113
|
+
if i > floor:
|
|
114
|
+
return head[:i].rstrip()
|
|
115
|
+
return "" # one unbroken token — drop it, never cut into it
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _short(s, n=52):
|
|
119
|
+
s = " ".join(str(s).split())
|
|
120
|
+
if len(s) <= n:
|
|
121
|
+
return s
|
|
122
|
+
return _cut_at_boundary(s, n - 1).rstrip(" ,;:.-—") + "…"
|
|
123
|
+
|
|
124
|
+
_ARTIFACT_KEYS = ("outputs", "output", "artifacts", "artifact")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def dep_artifacts(dep_dir, names, dep_fm):
|
|
128
|
+
"""WHAT THE DEPENDENCY HANDS YOU — the file, not the fact that it is done.
|
|
129
|
+
|
|
130
|
+
Frontmatter first if the node declares it (`outputs:`/`output:`/`artifacts:`/`artifact:`),
|
|
131
|
+
because a declaration outranks a guess. Otherwise the directory itself: everything beside
|
|
132
|
+
the node file, which for a built slice IS its output (MAP.md, PROOF.md, the script). No
|
|
133
|
+
prose parsing — a `## Output` section is written for humans and reading it would make the
|
|
134
|
+
trace confidently wrong exactly where it is trying to stop being that."""
|
|
135
|
+
for k in _ARTIFACT_KEYS:
|
|
136
|
+
v = (dep_fm or {}).get(k)
|
|
137
|
+
if v:
|
|
138
|
+
return [" ".join(str(x).split()) for x in (v if isinstance(v, list) else [v])], "declared"
|
|
139
|
+
try:
|
|
140
|
+
entries = sorted(os.listdir(dep_dir))
|
|
141
|
+
except OSError:
|
|
142
|
+
return [], "unreadable"
|
|
143
|
+
out = [e + ("/" if os.path.isdir(os.path.join(dep_dir, e)) else "")
|
|
144
|
+
for e in entries if not e.startswith(".") and e not in set(names)]
|
|
145
|
+
return out, "on disk"
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def blocking_state(payload, lvl, names):
|
|
149
|
+
"""THE LEAF'S NEXT-ACTION FACTS, composed BESIDE its intent. Returns a line or None.
|
|
150
|
+
|
|
151
|
+
Measured 2026-08-14: a cold seat walked `--field intent`, reconstructed the mission's
|
|
152
|
+
thesis from ~90 words, and finished green and ready to start work its own slice says is
|
|
153
|
+
blocked — because the walk opened the file holding `status: not-started`, extracted
|
|
154
|
+
exactly one key, and threw the rest away. It answers *what is this for* completely and
|
|
155
|
+
*what should I do now* not at all, and ships as though the first answered the second.
|
|
156
|
+
|
|
157
|
+
So the blocking facts ride along: `status`, and `depends:` — a sibling slice id (or a
|
|
158
|
+
list of them) RESOLVED ON DISK so the dependency's current state is reported rather than
|
|
159
|
+
remembered. Leaf only — the ancestors say what the work is for, and only the leaf says
|
|
160
|
+
whether to start it.
|
|
161
|
+
|
|
162
|
+
Measured 2026-08-14: a cold subject working slice 13 needed slice 11's OUTPUT. The walk
|
|
163
|
+
gave it 11's STATE and nothing else; the subject called the missing location "the single
|
|
164
|
+
largest unknown in my Phase 1 answer and it was the load-bearing input", and resolved it
|
|
165
|
+
with `ls` a phase later. A status answers *may I start*; it does not answer *where is the
|
|
166
|
+
thing I start from*. So each dependency now renders its ABSOLUTE PATH and its output
|
|
167
|
+
ARTIFACTS beside its state — and an id that resolves to nothing renders UNRESOLVED, said
|
|
168
|
+
out loud, because an unresolvable dependency dropped in silence is the same false
|
|
169
|
+
confidence in a smaller box."""
|
|
170
|
+
fm, _ = frontmatter(payload)
|
|
171
|
+
if not fm:
|
|
172
|
+
return None
|
|
173
|
+
parts = []
|
|
174
|
+
if fm.get("status") is not None:
|
|
175
|
+
parts.append(f"status: {_short(fm['status'], 88)}")
|
|
176
|
+
deps = fm.get("depends")
|
|
177
|
+
if deps:
|
|
178
|
+
shelf = os.path.dirname(lvl)
|
|
179
|
+
lines = ["depends:"]
|
|
180
|
+
for dep in (deps if isinstance(deps, list) else [deps]):
|
|
181
|
+
dep = " ".join(str(dep).split())
|
|
182
|
+
dep_dir = os.path.join(shelf, dep)
|
|
183
|
+
if not os.path.isdir(dep_dir):
|
|
184
|
+
lines.append(f" {dep} — ⚠ UNRESOLVED: no directory `{dep}` under {shelf}"
|
|
185
|
+
f" (nothing to point you at — check the id)")
|
|
186
|
+
continue
|
|
187
|
+
state, dfm = None, None
|
|
188
|
+
for n in names:
|
|
189
|
+
cand = os.path.join(dep_dir, n)
|
|
190
|
+
if os.path.isfile(cand):
|
|
191
|
+
st, body = read_state(cand)
|
|
192
|
+
dfm = frontmatter(body)[0] if st != "unseeded" else None
|
|
193
|
+
state = _short((dfm or {}).get("status") or st)
|
|
194
|
+
break
|
|
195
|
+
lines.append(f" {dep} ({state})" if state else
|
|
196
|
+
f" {dep} (⚠ no {'/'.join(names)} — state unknown)")
|
|
197
|
+
lines.append(f" path: {os.path.abspath(dep_dir)}")
|
|
198
|
+
arts, how = dep_artifacts(dep_dir, names, dfm)
|
|
199
|
+
if arts:
|
|
200
|
+
shown = arts[:8]
|
|
201
|
+
more = f" (+{len(arts) - 8} more)" if len(arts) > 8 else ""
|
|
202
|
+
lines.append(f" artifacts ({how}): " + " · ".join(shown) + more)
|
|
203
|
+
else:
|
|
204
|
+
lines.append(f" artifacts: ⚠ none found — the dependency has produced no"
|
|
205
|
+
f" output file yet")
|
|
206
|
+
parts.append("\n".join(lines)) # lines 2+ carry their own indent; the caller indents line 1
|
|
207
|
+
return "\n ".join(parts) or None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def operates_on(payload):
|
|
211
|
+
"""The roots this WORK touches — which are NOT the root the trace ascended.
|
|
212
|
+
|
|
213
|
+
Measured 2026-08-14, 4 cold subjects out of 4: the walk orients to PURPOSE excellently
|
|
214
|
+
and misleads on LOCATION every time. Naming the walked root did not help, because the
|
|
215
|
+
failure is not "which tree am I looking at" — it is "which tree does this work act on."
|
|
216
|
+
A slice about the skill library renders inside a map rooted at the workspace, and the
|
|
217
|
+
reader plans into the tree it was shown. One subject planned to CREATE a second corpus,
|
|
218
|
+
duplicating the very thing whose duplication was that slice's subject.
|
|
219
|
+
|
|
220
|
+
The walk cannot infer this: a work node is not bound to a root. So the node DECLARES it
|
|
221
|
+
and the leaf renders it verbatim. Mechanical, like `depends:`, and absent when unstated
|
|
222
|
+
rather than guessed."""
|
|
223
|
+
fm, _ = frontmatter(payload)
|
|
224
|
+
if not fm:
|
|
225
|
+
return None
|
|
226
|
+
roots = fm.get("operates_on")
|
|
227
|
+
if not roots:
|
|
228
|
+
return None
|
|
229
|
+
return [" ".join(str(r).split()) for r in (roots if isinstance(roots, list) else [roots])]
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# WHAT SURVIVES TRUNCATION. Both lists are read off the 15 real SPEC.md files of
|
|
233
|
+
# context-engineering-v2 — every pattern below matches a heading that actually exists there;
|
|
234
|
+
# no category is invented for symmetry. CONTRACT is the completion-and-scope family (`Done
|
|
235
|
+
# when`, `What done looks like`, `Scope fences`, `Output`, `Inputs`, `Depends on`, `What must
|
|
236
|
+
# be built`, `How we will know it works`, `PAYLOAD`). DISCUSSION is the rationale-and-history
|
|
237
|
+
# family (`Why …`, `The problem …`, `The evidence …`, `The finding …`, `RESULT …`, `Also
|
|
238
|
+
# found`, `Triage`, `What is already done`, `New evidence`, `Where this spec was wrong`) —
|
|
239
|
+
# valuable, and the first thing a reader can go get from the file itself.
|
|
240
|
+
# Anything unmatched sits in the MIDDLE on purpose: an unfamiliar heading is neither
|
|
241
|
+
# privileged nor sacrificed, so a new section shape degrades gracefully instead of silently
|
|
242
|
+
# becoming the first casualty.
|
|
243
|
+
_PRI_CONTRACT = re.compile(
|
|
244
|
+
r"(done when|what done looks like|scope fence|outputs?\b|inputs?\b|depends on|"
|
|
245
|
+
r"what must be built|how we will know|acceptance|payload|deliverable)", re.I)
|
|
246
|
+
_PRI_DISCUSSION = re.compile(
|
|
247
|
+
r"^(why\b|the problem|the evidence|the finding|result\b|also\b|related\b|triage\b|"
|
|
248
|
+
r"background\b|history\b|what is already done|new evidence|measured\b|answered\b|"
|
|
249
|
+
r"where this spec was wrong|notes for|the counter-argument|the asset|the mechanism|"
|
|
250
|
+
r"this mission is the acceptance criteria)", re.I)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _priority(heading):
|
|
254
|
+
"""0 = preamble (never dropped) · 1 = contract · 2 = unclassified · 3 = discussion."""
|
|
255
|
+
if heading is None:
|
|
256
|
+
return 0
|
|
257
|
+
if _PRI_CONTRACT.search(heading):
|
|
258
|
+
return 1
|
|
259
|
+
if _PRI_DISCUSSION.match(heading):
|
|
260
|
+
return 3
|
|
261
|
+
return 2
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _sections(body):
|
|
265
|
+
"""Split a node body at LEVEL-2 headings into [(heading|None, chunk), ...].
|
|
266
|
+
|
|
267
|
+
Chunk 0 is the preamble — the `# Title` and its lede — and carries heading None. `###`
|
|
268
|
+
stays inside its parent section: in these specs it is a sub-step of the section above it,
|
|
269
|
+
and splitting there would let half a section survive its own heading."""
|
|
270
|
+
starts = [m.start() for m in re.finditer(r"^## +.*$", body, re.M)]
|
|
271
|
+
if not starts:
|
|
272
|
+
return [(None, body)]
|
|
273
|
+
out = [(None, body[:starts[0]])]
|
|
274
|
+
for i, s in enumerate(starts):
|
|
275
|
+
chunk = body[s:starts[i + 1] if i + 1 < len(starts) else len(body)]
|
|
276
|
+
out.append((chunk.splitlines()[0].lstrip("# ").strip(), chunk))
|
|
277
|
+
return out
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def leaf_body(payload, cap):
|
|
281
|
+
"""Ancestors compose by FIELD; the leaf composes by BODY.
|
|
282
|
+
|
|
283
|
+
Measured 2026-08-14 (slice 01 A/B): a cold agent given three intent sentences
|
|
284
|
+
reconstructed the mission's thesis correctly, then assumed the work tree it had been
|
|
285
|
+
shown was the tree its slice was about. The slice was about the TOPOLOGY tree. It built
|
|
286
|
+
a coherent four-step plan aimed at the wrong one — and the three altitudes it planned
|
|
287
|
+
over need three different verbs, which it had no way to know.
|
|
288
|
+
|
|
289
|
+
That is misdirection, not a gap. Ancestors compress beautifully because they are stable
|
|
290
|
+
and abstract. **The leaf is where the nouns live, and a field-only walk throws them
|
|
291
|
+
away** — every word that would have disambiguated it sat in the body that was not shown.
|
|
292
|
+
|
|
293
|
+
Truncation is BY PRIORITY, never by position. Measured 2026-08-14: positional cutting on
|
|
294
|
+
slice 13 dropped `Output`, `Done when` and `Scope fences` — the three sections that say
|
|
295
|
+
what to produce, when it is finished and what it may not touch — and kept four screens of
|
|
296
|
+
rationale, because the rationale happened to be written first. The subject rated its own
|
|
297
|
+
grasp of purpose 85% and its next action 70% and named that omission as the reason. A
|
|
298
|
+
render that keeps the argument and drops the contract has the priorities backwards."""
|
|
299
|
+
if not payload:
|
|
300
|
+
return None
|
|
301
|
+
m = re.match(r"^---\n.*?\n---\n", payload, re.S)
|
|
302
|
+
body = (payload[m.end():] if m else payload).strip()
|
|
303
|
+
if not body:
|
|
304
|
+
return None
|
|
305
|
+
if len(body) <= cap:
|
|
306
|
+
return body
|
|
307
|
+
secs = _sections(body)
|
|
308
|
+
if len(secs) == 1: # headingless prose — nothing to prioritise
|
|
309
|
+
kept = _cut_at_boundary(body, cap)
|
|
310
|
+
return (kept + "\n\n[… " + str(len(body) - len(kept)) + " more chars, no further "
|
|
311
|
+
"headings — prose tail]" + "\n(read the node file for these)")
|
|
312
|
+
# Drop LOWEST priority first and, within a tier, the LARGEST section first. Size beats
|
|
313
|
+
# position here and it was measured: slice 13's contract sections total more than any
|
|
314
|
+
# sane cap, and dropping the tier tail-first killed `Done when` (12 lines) and `Scope
|
|
315
|
+
# fences` (9) to save `Output` and `Inputs` (~2k chars each) — the two long prose
|
|
316
|
+
# sections eating the two short decisive ones. Largest-first keeps the most sections
|
|
317
|
+
# standing, and in these specs the short section is the one carrying the ruling. The
|
|
318
|
+
# preamble (title + lede, index 0) is never a candidate: it is what names the thing.
|
|
319
|
+
keep, size = set(range(len(secs))), len(body)
|
|
320
|
+
for i in sorted(range(1, len(secs)), key=lambda i: (-_priority(secs[i][0]), -len(secs[i][1]))):
|
|
321
|
+
if size <= cap:
|
|
322
|
+
break
|
|
323
|
+
keep.discard(i)
|
|
324
|
+
size -= len(secs[i][1])
|
|
325
|
+
kept = "".join(secs[i][1] for i in sorted(keep)).rstrip()
|
|
326
|
+
if len(kept) > cap: # preamble alone overflows; cut it safely, never mid-token
|
|
327
|
+
kept = _cut_at_boundary(kept, cap)
|
|
328
|
+
dropped = [secs[i][0] for i in range(1, len(secs)) if i not in keep]
|
|
329
|
+
# NAME what was cut. A byte count reads as trivia; two subjects in a row lost the
|
|
330
|
+
# acceptance criteria to it and neither could tell, because a truncated head can end on
|
|
331
|
+
# a clean rhetorical close and look like a finished document. Listing the dropped
|
|
332
|
+
# headings turns invisible truncation into a decision the reader can actually make —
|
|
333
|
+
# one subject lowered its own confidence honestly on the strength of this line alone.
|
|
334
|
+
tail = ("\n\nOMITTED FROM THIS RENDER — " + str(len(body) - len(kept)) + " chars, sections: "
|
|
335
|
+
+ " · ".join(dropped) if dropped else
|
|
336
|
+
"\n\n[… " + str(len(body) - len(kept)) + " more chars, no further headings — prose tail]")
|
|
337
|
+
return kept + tail + "\n(read the node file for these)"
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def resolve_roots():
|
|
341
|
+
"""WHERE THE TWO TREES LIVE — resolved, never hardcoded, never guessed.
|
|
342
|
+
|
|
343
|
+
A skill ships inside a plugin and its scripts must run unmodified on a stranger's machine.
|
|
344
|
+
The WORK tree has been addressable for a while (`workspace.root`). The TOPOLOGY tree was not:
|
|
345
|
+
every consumer hardcoded `~/.openrig/shared-docs`, so half the walk was portable and half was
|
|
346
|
+
not. Precedence matches every other typed key: env > config > derived > fail-with-the-key.
|
|
347
|
+
|
|
348
|
+
The derived step is honest rather than clever: this script physically lives inside the
|
|
349
|
+
shared-docs tree, so it can find its own `rigs/` sibling by walking up from __file__. That
|
|
350
|
+
works for the library copy and its symlinked projections (resolved with realpath) and NOT for
|
|
351
|
+
a real plugin copy — which is correct. A plugin copy on
|
|
352
|
+
someone else's machine has no business inferring a path; it must be told, and it fails saying
|
|
353
|
+
exactly which key to set rather than picking a directory and being confidently wrong."""
|
|
354
|
+
out = {}
|
|
355
|
+
out["work_root"] = os.environ.get("OPENRIG_WORKSPACE_ROOT") or rig_config("workspace.root")
|
|
356
|
+
|
|
357
|
+
t = os.environ.get("OPENRIG_TOPOLOGY_ROOT") or rig_config("workspace.topology_root")
|
|
358
|
+
if not t:
|
|
359
|
+
# realpath, NOT abspath: the runtime tiers project this script as a SYMLINK
|
|
360
|
+
# (~/.claude/skills/... -> the library copy). abspath keeps the symlink's own path, so
|
|
361
|
+
# the ascent runs up a tree with no `rigs/` sibling and topology_root comes back
|
|
362
|
+
# UNRESOLVED — for every agent reaching the tool the documented way. Measured 2026-08-14:
|
|
363
|
+
# exit 3 via the projection, exit 0 via the realpath, same file.
|
|
364
|
+
here = os.path.realpath(__file__)
|
|
365
|
+
for _ in range(6): # scripts/ skill/ skills/ skill-canon/ -> shared-docs/
|
|
366
|
+
here = os.path.dirname(here)
|
|
367
|
+
cand = os.path.join(here, "rigs")
|
|
368
|
+
if os.path.isdir(cand):
|
|
369
|
+
t = cand
|
|
370
|
+
break
|
|
371
|
+
out["topology_root"] = t
|
|
372
|
+
return out
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def rig_config(key):
|
|
376
|
+
if not shutil.which("rig"):
|
|
377
|
+
return None
|
|
378
|
+
try:
|
|
379
|
+
p = subprocess.run(["rig", "config", "get", key], capture_output=True, text=True, timeout=10)
|
|
380
|
+
v = (p.stdout or "").strip()
|
|
381
|
+
return v if p.returncode == 0 and v else None
|
|
382
|
+
except Exception:
|
|
383
|
+
return None
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def compose_up(start, names, root, field=None, prefer=False, shelves=None, leaf_cap=2400):
|
|
387
|
+
shelves = SHELF_NAMES | set(shelves or ())
|
|
388
|
+
start = os.path.abspath(start); root = os.path.abspath(root) if root else None
|
|
389
|
+
levels = []
|
|
390
|
+
d = start
|
|
391
|
+
while True:
|
|
392
|
+
levels.append(d)
|
|
393
|
+
if root and os.path.samefile(d, root): break
|
|
394
|
+
if not root and os.path.exists(os.path.join(d, ".compose-root")): break
|
|
395
|
+
parent = os.path.dirname(d)
|
|
396
|
+
if parent == d: break
|
|
397
|
+
d = parent
|
|
398
|
+
levels.reverse() # root first: defaults, then overrides
|
|
399
|
+
out = [f"<!-- GENERATED by compose.py up · {datetime.datetime.now().isoformat(timespec='minutes')} -->",
|
|
400
|
+
f"<!-- start: {start} · altitudes: {sum(1 for d in levels if os.path.basename(d) not in shelves)} ({len(levels)} path segments) · chains: {', '.join(names)}" + (f" · FIELD: {field}" if field else "") + " -->",
|
|
401
|
+
"<!-- Composed view — never edit; edit the fragments. -->"]
|
|
402
|
+
GLYPH = {"seeded": "✓ seeded", "unseeded": "⟂ UNSEEDED", "conflicted": "⚠ stale marker",
|
|
403
|
+
"absent": "✗ absent", "shelf": "· shelf"}
|
|
404
|
+
missing, unseeded = [], []
|
|
405
|
+
# --prefer turns the --name list into ONE chain resolved per level by precedence
|
|
406
|
+
# (first match wins) instead of N independent chains. A tree mid-rename is the normal
|
|
407
|
+
# case, not an exception: SPEC.md is the current node filename and README.md the legacy
|
|
408
|
+
# one, and a trace that cannot span both reports a chain as broken when it is merely mixed.
|
|
409
|
+
# Test the START NODE against the TREES, not the root against the workspace. Being
|
|
410
|
+
# somewhere under workspace.root is not the property that matters: the measured hazard
|
|
411
|
+
# is a fixture tree at workspace/artifacts/<qitem>/fixture-workspace/missions/, which is
|
|
412
|
+
# inside workspace.root and is not a work tree. Only slices_root and topology_root name
|
|
413
|
+
# actual trees, so those are the discriminator.
|
|
414
|
+
_cfg = [c for c in (rig_config("workspace.slices_root"),
|
|
415
|
+
resolve_roots().get("topology_root")) if c]
|
|
416
|
+
_here = os.path.abspath(start)
|
|
417
|
+
_root_warning = None
|
|
418
|
+
if _cfg and not any(_here == os.path.abspath(c) or _here.startswith(os.path.abspath(c) + os.sep)
|
|
419
|
+
for c in _cfg):
|
|
420
|
+
_root_warning = (" ⚠ THIS IS NOT A CONFIGURED TREE. Trees on this instance: "
|
|
421
|
+
+ " · ".join(_cfg) + "\n A walk renders just as cleanly from a stray or"
|
|
422
|
+
" fixture tree — verify before acting on it.")
|
|
423
|
+
groups = [list(names)] if prefer else [[n] for n in names]
|
|
424
|
+
for group in groups:
|
|
425
|
+
name = group[0]
|
|
426
|
+
out.append(f"\n\n# CHAIN: {' → '.join(group)} (root → leaf)"
|
|
427
|
+
+ (" · precedence: first match wins per level" if len(group) > 1 else ""))
|
|
428
|
+
# pass 1 — collect the state of every level (this IS the trace; the map derives from it)
|
|
429
|
+
chain, hits = [], {}
|
|
430
|
+
for lvl in levels:
|
|
431
|
+
p = None
|
|
432
|
+
for n in group:
|
|
433
|
+
cand = os.path.join(lvl, n)
|
|
434
|
+
if os.path.isfile(cand):
|
|
435
|
+
p, hits[lvl] = cand, n
|
|
436
|
+
break
|
|
437
|
+
where = os.path.relpath(lvl, levels[0]) or '.'
|
|
438
|
+
# A SHELF is a path segment, not an altitude. The chain has three rungs — project,
|
|
439
|
+
# mission, slice — and rendering `missions/` and `slices/` as rungs implies five.
|
|
440
|
+
# Any file living at a shelf is ordinary folder documentation, NOT a chain link:
|
|
441
|
+
# ignore it rather than flagging it. `README.md` does double duty as a legacy node
|
|
442
|
+
# name and as a plain readme, and only the level it sits at can tell them apart.
|
|
443
|
+
is_shelf = os.path.basename(lvl) in shelves
|
|
444
|
+
if is_shelf:
|
|
445
|
+
state, payload, p = "shelf", None, None
|
|
446
|
+
hits.pop(lvl, None)
|
|
447
|
+
elif p:
|
|
448
|
+
state, payload = read_state(p)
|
|
449
|
+
else:
|
|
450
|
+
state, payload = "absent", None
|
|
451
|
+
# Resolve the field HERE so the map can tell the truth. A map keyed on file
|
|
452
|
+
# presence says ✓ for a level that composes nothing — the exact reading that
|
|
453
|
+
# lets a trace certify the drift it exists to catch.
|
|
454
|
+
fval, fnote = (field_of(payload, field) if (field and state == "seeded") else (None, None))
|
|
455
|
+
chain.append((lvl, where, state, payload, fval, fnote))
|
|
456
|
+
# TRACE — derived orientation tree (never stored in files; the render is the only home)
|
|
457
|
+
# The map shows ALTITUDES as rungs; shelves fold into the next rung's path so the tree
|
|
458
|
+
# depth equals the number of levels that actually carry intent.
|
|
459
|
+
rungs, pending = [], []
|
|
460
|
+
for idx, row in enumerate(chain):
|
|
461
|
+
if row[2] == "shelf" and idx != len(chain) - 1:
|
|
462
|
+
pending.append(os.path.basename(row[0]) or row[0])
|
|
463
|
+
continue
|
|
464
|
+
label = "/".join(pending + [os.path.basename(row[0]) or row[0]])
|
|
465
|
+
rungs.append((label, row)); pending = []
|
|
466
|
+
leads = [("" if i == 0 else " " * (i - 1) + "└─ ") + rungs[i][0] + "/" for i in range(len(rungs))]
|
|
467
|
+
width = max(len(l) for l in leads) + 2
|
|
468
|
+
# NAME THE REFERENT. Three cold subjects in a row assumed the tree they were
|
|
469
|
+
# SHOWN was the tree their slice was ABOUT, and planned into the wrong one. The map
|
|
470
|
+
# cannot know "work" vs "topology" semantically, but it knows what it walked — and
|
|
471
|
+
# root + chain filename is enough to tell them apart (workspace/SPEC.md vs rigs/LEARNED.md).
|
|
472
|
+
out.append(f"\nTRACE · root {levels[0]} · chain {' → '.join(group)}")
|
|
473
|
+
# VALIDATE THE ROOT. Measured 2026-08-14: this box has four directories named
|
|
474
|
+
# `missions`, one of them a TEST FIXTURE under artifacts/. Handed the fixture as
|
|
475
|
+
# --root, the trace renders an equally clean, equally confident chain — because
|
|
476
|
+
# `✓ seeded` means "a file was found here", never "you are in the right tree".
|
|
477
|
+
# Confidence that is independent of correctness is the failure this whole mission
|
|
478
|
+
# is against, so the trace now says when it cannot vouch for where it is standing.
|
|
479
|
+
if _root_warning:
|
|
480
|
+
out.append(_root_warning)
|
|
481
|
+
for i, (_label, (lvl, where, state, payload, fval, fnote)) in enumerate(rungs):
|
|
482
|
+
note = f" (owner: {payload})" if state == "unseeded" and payload else ""
|
|
483
|
+
here = " ← you are here" if i == len(rungs) - 1 else ""
|
|
484
|
+
glyph = f"⟂ no {field}" if (field and state == "seeded" and not fval) else GLYPH[state]
|
|
485
|
+
# In precedence mode, name WHICH file answered at each level — a mixed tree is
|
|
486
|
+
# readable state, not noise, and hiding it is how a rename looks like corruption.
|
|
487
|
+
via = f" [{hits[lvl]}]" if len(group) > 1 and lvl in hits and state != "shelf" else ""
|
|
488
|
+
out.append(f" {leads[i]:<{width}}{glyph}{via}{note}{here}")
|
|
489
|
+
# pass 2 — contents, states collapsed per the three-state rules
|
|
490
|
+
found = 0
|
|
491
|
+
for lvl, where, state, payload, fval, fnote in chain:
|
|
492
|
+
if state == "shelf":
|
|
493
|
+
continue # a path segment, not a position — contributes nothing, flags nothing
|
|
494
|
+
elif state == "unseeded":
|
|
495
|
+
out.append(f"\n⟂ {name} @ {where} — UNSEEDED (scaffold only, not rendered; seed it: {payload})")
|
|
496
|
+
unseeded.append(f"{name} @ {where} (owner: {payload})")
|
|
497
|
+
elif state == "conflicted":
|
|
498
|
+
found += 1
|
|
499
|
+
out.append(hdr(f"{name} @ {where} — ⚠ carries status: UNSEEDED but content differs from template"))
|
|
500
|
+
out.append(payload.rstrip())
|
|
501
|
+
unseeded.append(f"{name} @ {where} — MARKER/CONTENT DISAGREE: rendered anyway; owner should clear the stale status line")
|
|
502
|
+
elif state == "seeded":
|
|
503
|
+
found += 1
|
|
504
|
+
if field:
|
|
505
|
+
if fval:
|
|
506
|
+
out.append(f"\n{where}: {fval}")
|
|
507
|
+
else:
|
|
508
|
+
out.append(f"\n{where}: ⚠ {fnote}")
|
|
509
|
+
unseeded.append(f"{name} @ {where} — {fnote}")
|
|
510
|
+
# The leaf is the only level whose answer is an ACTION. Compose its
|
|
511
|
+
# blocking state here or the walk certifies the next step it never read.
|
|
512
|
+
if lvl == chain[-1][0]:
|
|
513
|
+
blocked = blocking_state(payload, lvl, group)
|
|
514
|
+
if blocked:
|
|
515
|
+
out.append(f" {blocked}")
|
|
516
|
+
roots = operates_on(payload)
|
|
517
|
+
if roots:
|
|
518
|
+
out.append(" operates on: " + " · ".join(roots))
|
|
519
|
+
# ...and the only altitude that SPECIFIES. See leaf_body().
|
|
520
|
+
lb = leaf_body(payload, leaf_cap) if leaf_cap else None
|
|
521
|
+
if lb:
|
|
522
|
+
out.append(f"\n─── {where} · node body ───")
|
|
523
|
+
out.append(lb)
|
|
524
|
+
else:
|
|
525
|
+
out.append(hdr(f"{name} @ {where}"))
|
|
526
|
+
out.append(payload.rstrip())
|
|
527
|
+
else:
|
|
528
|
+
missing.append(f"{name} @ {where}")
|
|
529
|
+
if not found:
|
|
530
|
+
out.append(f"\n⚠ NO seeded instances of {name} on this walk.")
|
|
531
|
+
if unseeded or missing:
|
|
532
|
+
out.append("\n\n# ⚠ CHAIN AUDIT (the walk screams once, here — never by breaking, never by template litter)")
|
|
533
|
+
if unseeded:
|
|
534
|
+
out.append("UNSEEDED (file exists, template only — the owner writes the first true version):")
|
|
535
|
+
out += [f"- {m}" for m in unseeded]
|
|
536
|
+
if missing:
|
|
537
|
+
out.append("ABSENT (no file at a POSITION — scaffold it, or report to the level owner if absence looks wrong):")
|
|
538
|
+
out += [f"- {m}" for m in missing]
|
|
539
|
+
return "\n".join(out)
|
|
540
|
+
|
|
541
|
+
def compose_down(root, names, excludes):
|
|
542
|
+
root = os.path.abspath(root)
|
|
543
|
+
hits = []
|
|
544
|
+
for dirpath, dirs, files in os.walk(root):
|
|
545
|
+
dirs[:] = [x for x in dirs if not x.startswith(".") and x != "node_modules"
|
|
546
|
+
and not any(fnmatch.fnmatch(os.path.join(dirpath, x), g) for g in excludes)]
|
|
547
|
+
for name in names:
|
|
548
|
+
if name in files:
|
|
549
|
+
hits.append(os.path.join(dirpath, name))
|
|
550
|
+
hits.sort()
|
|
551
|
+
out = [f"<!-- GENERATED by compose.py down · {datetime.datetime.now().isoformat(timespec='minutes')} -->",
|
|
552
|
+
f"<!-- root: {root} · files: {len(hits)} · chains: {', '.join(names)} -->",
|
|
553
|
+
"<!-- Subtree render (trunk render at a tree root). Never edit. -->"]
|
|
554
|
+
unseeded = []
|
|
555
|
+
for p in hits:
|
|
556
|
+
state, payload = read_state(p)
|
|
557
|
+
rel = os.path.relpath(p, root)
|
|
558
|
+
if state == "unseeded":
|
|
559
|
+
unseeded.append(f"{rel} (owner: {payload})")
|
|
560
|
+
elif state == "conflicted":
|
|
561
|
+
out.append(hdr(f"{rel} — ⚠ stale UNSEEDED marker on real content"))
|
|
562
|
+
out.append(payload.rstrip())
|
|
563
|
+
unseeded.append(f"{rel} — MARKER/CONTENT DISAGREE: rendered anyway; clear the stale status line")
|
|
564
|
+
else:
|
|
565
|
+
out.append(hdr(rel))
|
|
566
|
+
out.append(payload.rstrip())
|
|
567
|
+
if unseeded:
|
|
568
|
+
out.append("\n\n# ⚠ UNSEEDED under this root (scaffold only — collapsed, not rendered)")
|
|
569
|
+
out += [f"- {u}" for u in unseeded]
|
|
570
|
+
if not hits:
|
|
571
|
+
out.append("\n⚠ no chain files under this root — unfurl first?")
|
|
572
|
+
return "\n".join(out)
|
|
573
|
+
|
|
574
|
+
def compose_progress(root, names, excludes):
|
|
575
|
+
import collections
|
|
576
|
+
root = os.path.abspath(root)
|
|
577
|
+
direct = collections.defaultdict(lambda: [0, 0]) # dir -> [done, total] from its own files
|
|
578
|
+
for dirpath, dirs, files in os.walk(root):
|
|
579
|
+
dirs[:] = [x for x in dirs if not x.startswith(".") and x != "node_modules"
|
|
580
|
+
and not any(fnmatch.fnmatch(os.path.join(dirpath, x), g) for g in excludes)]
|
|
581
|
+
for name in names:
|
|
582
|
+
if name in files:
|
|
583
|
+
txt = open(os.path.join(dirpath, name), encoding="utf-8", errors="replace").read()
|
|
584
|
+
done = len(re.findall(r"^\s*[-*] \[[xX]\]", txt, re.M))
|
|
585
|
+
open_ = len(re.findall(r"^\s*[-*] \[ \]", txt, re.M))
|
|
586
|
+
if done + open_:
|
|
587
|
+
direct[dirpath][0] += done
|
|
588
|
+
direct[dirpath][1] += done + open_
|
|
589
|
+
agg = collections.defaultdict(lambda: [0, 0]) # dir -> rolled-up [done, total]
|
|
590
|
+
for d, (dn, tt) in direct.items():
|
|
591
|
+
cur = d
|
|
592
|
+
while True:
|
|
593
|
+
agg[cur][0] += dn; agg[cur][1] += tt
|
|
594
|
+
if os.path.samefile(cur, root): break
|
|
595
|
+
cur = os.path.dirname(cur)
|
|
596
|
+
out = [f"<!-- GENERATED by compose.py progress · {datetime.datetime.now().isoformat(timespec='minutes')} -->",
|
|
597
|
+
"<!-- Derived from the mark level at render time. Never store this in a file. -->",
|
|
598
|
+
f"\nPROGRESS MAP ({', '.join(names)} — checkbox = the one mark level; everything above derives):"]
|
|
599
|
+
if not agg:
|
|
600
|
+
out.append(" (no checkboxes found in the named files under this root — nothing is marked here)")
|
|
601
|
+
return "\n".join(out)
|
|
602
|
+
keys = sorted(agg, key=lambda d: os.path.relpath(d, root))
|
|
603
|
+
leads = []
|
|
604
|
+
for d in keys:
|
|
605
|
+
rel = os.path.relpath(d, root)
|
|
606
|
+
depth = 0 if rel == "." else rel.count(os.sep) + 1
|
|
607
|
+
label = os.path.basename(root) if rel == "." else os.path.basename(d)
|
|
608
|
+
leads.append(("" if depth == 0 else " " * (depth - 1) + "└─ ") + label)
|
|
609
|
+
width = max(len(l) for l in leads) + 2
|
|
610
|
+
for i, d in enumerate(keys):
|
|
611
|
+
dn, tt = agg[d]
|
|
612
|
+
pct = 100 * dn // tt if tt else 0
|
|
613
|
+
glyph = "✓" if dn == tt else ("◐" if dn else "○")
|
|
614
|
+
own = " ·" if d in direct else " " # · = has marks of its own (vs pure roll-up)
|
|
615
|
+
out.append(f" {leads[i]:<{width}}{glyph} {dn}/{tt} ({pct}%){own}")
|
|
616
|
+
return "\n".join(out)
|
|
617
|
+
|
|
618
|
+
if __name__ == "__main__":
|
|
619
|
+
ap = argparse.ArgumentParser()
|
|
620
|
+
ap.add_argument("mode", choices=["up", "down", "progress", "roots"])
|
|
621
|
+
ap.add_argument("path", nargs="?")
|
|
622
|
+
ap.add_argument("--name", action="append")
|
|
623
|
+
ap.add_argument("--root", default=None)
|
|
624
|
+
ap.add_argument("--prefer", action="store_true",
|
|
625
|
+
help="treat --name as a PRECEDENCE list (first match wins per level) rather "
|
|
626
|
+
"than separate chains — for a tree mid-rename: --name SPEC.md --name README.md --prefer")
|
|
627
|
+
ap.add_argument("--exclude", action="append", default=[])
|
|
628
|
+
ap.add_argument("--field", default=None, help="compose ONE frontmatter field up the chain (e.g. --field intent) instead of whole bodies")
|
|
629
|
+
ap.add_argument("--leaf-cap", type=int, default=2400, metavar="N",
|
|
630
|
+
help="with --field: also render the LEAF's body, capped at N chars (0 = off). "
|
|
631
|
+
"Ancestors compress; the leaf is where the nouns are.")
|
|
632
|
+
ap.add_argument("--shelf", action="append", default=[],
|
|
633
|
+
help=f"extra directory name that HOLDS instances rather than being a position, so "
|
|
634
|
+
f"its absence of a chain file is correct (defaults: {', '.join(sorted(SHELF_NAMES))})")
|
|
635
|
+
a = ap.parse_args()
|
|
636
|
+
if a.mode == "roots":
|
|
637
|
+
r = resolve_roots()
|
|
638
|
+
for k in ("work_root", "topology_root"):
|
|
639
|
+
v = r.get(k)
|
|
640
|
+
if v:
|
|
641
|
+
print(f"{k}={v}")
|
|
642
|
+
else:
|
|
643
|
+
key = "workspace.root" if k == "work_root" else "workspace.topology_root"
|
|
644
|
+
print(f"# {k} UNRESOLVED — set it: rig config set {key} <path>", file=sys.stderr)
|
|
645
|
+
sys.exit(0 if all(r.values()) else 3)
|
|
646
|
+
if not a.name:
|
|
647
|
+
ap.error("--name is required for up/down/progress")
|
|
648
|
+
if a.mode == "up":
|
|
649
|
+
print(compose_up(a.path, a.name, a.root, a.field, prefer=a.prefer, shelves=a.shelf, leaf_cap=a.leaf_cap))
|
|
650
|
+
elif a.mode == "down":
|
|
651
|
+
print(compose_down(a.path, a.name, a.exclude))
|
|
652
|
+
else:
|
|
653
|
+
print(compose_progress(a.path, a.name, a.exclude))
|