@zerwiz/ymir 0.1.4 → 0.1.7
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/.agents/README.md +291 -0
- package/.agents/agents/bragi-marketer.md +111 -0
- package/.agents/agents/brokk.md +352 -0
- package/.agents/agents/forseti-reviewer.md +93 -0
- package/.agents/agents/frigg-consent.md +77 -0
- package/.agents/agents/groa-update.md +77 -0
- package/.agents/agents/hnoss-designer.md +69 -0
- package/.agents/agents/huginn-researcher.md +99 -0
- package/.agents/agents/jord-projects.md +78 -0
- package/.agents/agents/kvasir-scout.md +91 -0
- package/.agents/agents/mimir-planner.md +92 -0
- package/.agents/agents/muninn-stow.md +77 -0
- package/.agents/agents/saga-bearings.md +78 -0
- package/.agents/agents/sindri-developer.md +114 -0
- package/.agents/agents/snotra-documenter.md +105 -0
- package/.agents/agents/syn-recovery.md +78 -0
- package/.agents/agents/tyr-check.md +78 -0
- package/.agents/agents/urdh-hold.md +77 -0
- package/.agents/agents/volundr-smith.md +80 -0
- package/.agents/agents/vor-diagnostics.md +77 -0
- package/.agents/assets/agents/naming.md +50 -0
- package/.agents/assets/agents/registry.md +93 -0
- package/.agents/assets/agents/runtime.md +36 -0
- package/.agents/assets/agents/toon-tasks-cli.md +42 -0
- package/.agents/assets/templates/company_entity.template.md +37 -0
- package/.agents/backend/README.md +74 -0
- package/.agents/backend/backends/cmux.sh +649 -0
- package/.agents/backend/backends/herdr-eventwait.py +157 -0
- package/.agents/backend/backends/herdr-workspace-move.py +114 -0
- package/.agents/backend/backends/herdr.sh +3386 -0
- package/.agents/backend/backends/orca.sh +290 -0
- package/.agents/backend/backends/tmux.sh +357 -0
- package/.agents/backend/backends/zellij.sh +700 -0
- package/.agents/backend/fm-afk-launch.sh +654 -0
- package/.agents/backend/fm-afk-return.sh +241 -0
- package/.agents/backend/fm-afk-start.sh +172 -0
- package/.agents/backend/fm-arm-command-policy.mjs +960 -0
- package/.agents/backend/fm-arm-pretool-check.sh +200 -0
- package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
- package/.agents/backend/fm-backend.sh +981 -0
- package/.agents/backend/fm-backlog-handoff.sh +909 -0
- package/.agents/backend/fm-backlog-receive.sh +187 -0
- package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
- package/.agents/backend/fm-bearings-board.sh +204 -0
- package/.agents/backend/fm-bearings-snapshot.sh +546 -0
- package/.agents/backend/fm-bootstrap.sh +1568 -0
- package/.agents/backend/fm-branch-outcome.sh +203 -0
- package/.agents/backend/fm-branch-prompt.sh +101 -0
- package/.agents/backend/fm-brief.sh +452 -0
- package/.agents/backend/fm-busy-event.sh +234 -0
- package/.agents/backend/fm-busy-lib.sh +986 -0
- package/.agents/backend/fm-captain-hold.sh +1001 -0
- package/.agents/backend/fm-cd-command-policy.mjs +153 -0
- package/.agents/backend/fm-cd-pretool-check.sh +190 -0
- package/.agents/backend/fm-check-lib.sh +74 -0
- package/.agents/backend/fm-check-register.sh +42 -0
- package/.agents/backend/fm-check-unregister.sh +52 -0
- package/.agents/backend/fm-classify-lib.sh +1770 -0
- package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
- package/.agents/backend/fm-composer-lib.sh +1416 -0
- package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
- package/.agents/backend/fm-config-push.sh +254 -0
- package/.agents/backend/fm-control-lib.sh +251 -0
- package/.agents/backend/fm-control.sh +878 -0
- package/.agents/backend/fm-crew-state.sh +625 -0
- package/.agents/backend/fm-cursor-lib.sh +243 -0
- package/.agents/backend/fm-decision-hold.sh +232 -0
- package/.agents/backend/fm-doc-audience-check.sh +269 -0
- package/.agents/backend/fm-dod-lib.sh +67 -0
- package/.agents/backend/fm-ensure-agents-md.sh +253 -0
- package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
- package/.agents/backend/fm-extension.mjs +2577 -0
- package/.agents/backend/fm-extension.sh +16 -0
- package/.agents/backend/fm-ff-lib.sh +420 -0
- package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
- package/.agents/backend/fm-fleet-sync.sh +458 -0
- package/.agents/backend/fm-fleet-view.sh +96 -0
- package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
- package/.agents/backend/fm-guard.sh +242 -0
- package/.agents/backend/fm-harness.sh +195 -0
- package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
- package/.agents/backend/fm-herdr-lab.sh +346 -0
- package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
- package/.agents/backend/fm-home-seed.sh +984 -0
- package/.agents/backend/fm-home-summary-refresh.sh +255 -0
- package/.agents/backend/fm-hook-host-lib.sh +36 -0
- package/.agents/backend/fm-inactive-reconcile.sh +531 -0
- package/.agents/backend/fm-inbox.sh +399 -0
- package/.agents/backend/fm-install-actionlint.sh +84 -0
- package/.agents/backend/fm-install-herdr.sh +96 -0
- package/.agents/backend/fm-install-shellcheck.sh +84 -0
- package/.agents/backend/fm-install-treehouse.sh +95 -0
- package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
- package/.agents/backend/fm-lease-lib.sh +218 -0
- package/.agents/backend/fm-lease.sh +189 -0
- package/.agents/backend/fm-line-cap-lib.sh +51 -0
- package/.agents/backend/fm-lint-workflows.sh +137 -0
- package/.agents/backend/fm-lint.sh +591 -0
- package/.agents/backend/fm-lock-lib.sh +104 -0
- package/.agents/backend/fm-lock.sh +107 -0
- package/.agents/backend/fm-marker-lib.sh +12 -0
- package/.agents/backend/fm-merge-local.sh +74 -0
- package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
- package/.agents/backend/fm-nm-run-lib.sh +124 -0
- package/.agents/backend/fm-on.sh +125 -0
- package/.agents/backend/fm-operational-input.sh +253 -0
- package/.agents/backend/fm-peek.sh +46 -0
- package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
- package/.agents/backend/fm-pr-check.sh +135 -0
- package/.agents/backend/fm-pr-lib.sh +1016 -0
- package/.agents/backend/fm-pr-merge.sh +707 -0
- package/.agents/backend/fm-pr-poll.sh +110 -0
- package/.agents/backend/fm-primary-scope-lib.sh +33 -0
- package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
- package/.agents/backend/fm-procevent-lavish.sh +628 -0
- package/.agents/backend/fm-procevent-lib.sh +892 -0
- package/.agents/backend/fm-procevent-quota.sh +290 -0
- package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
- package/.agents/backend/fm-procevent-when.sh +504 -0
- package/.agents/backend/fm-procevent.sh +1466 -0
- package/.agents/backend/fm-project-mode.sh +92 -0
- package/.agents/backend/fm-project-origin-lib.sh +180 -0
- package/.agents/backend/fm-promote.sh +282 -0
- package/.agents/backend/fm-public-followup-emit.sh +260 -0
- package/.agents/backend/fm-public-followup-lib.sh +398 -0
- package/.agents/backend/fm-public-followup.sh +1330 -0
- package/.agents/backend/fm-push-transition-lib.sh +168 -0
- package/.agents/backend/fm-quota-axi-lib.sh +93 -0
- package/.agents/backend/fm-quota-choose.sh +384 -0
- package/.agents/backend/fm-remote-delta-read.sh +189 -0
- package/.agents/backend/fm-remote-doctor.sh +800 -0
- package/.agents/backend/fm-remote-entrypoint.sh +193 -0
- package/.agents/backend/fm-remote-file.sh +234 -0
- package/.agents/backend/fm-remote-home-provision.sh +259 -0
- package/.agents/backend/fm-remote-home-seed.sh +259 -0
- package/.agents/backend/fm-remote-inherit-push.sh +90 -0
- package/.agents/backend/fm-remote-inherit.sh +179 -0
- package/.agents/backend/fm-remote-job-lib.sh +1241 -0
- package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
- package/.agents/backend/fm-remote-job-worker.sh +1124 -0
- package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
- package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
- package/.agents/backend/fm-review-diff.sh +158 -0
- package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
- package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
- package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
- package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
- package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
- package/.agents/backend/fm-secondmate-report.sh +88 -0
- package/.agents/backend/fm-send.sh +1059 -0
- package/.agents/backend/fm-session-lock-lib.sh +176 -0
- package/.agents/backend/fm-session-start.sh +970 -0
- package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
- package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
- package/.agents/backend/fm-sessionstart-run.sh +145 -0
- package/.agents/backend/fm-spawn.sh +3153 -0
- package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
- package/.agents/backend/fm-startup-memory-budget.sh +94 -0
- package/.agents/backend/fm-startup-network.sh +642 -0
- package/.agents/backend/fm-stow-cascade.sh +251 -0
- package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
- package/.agents/backend/fm-supervise-daemon.sh +1732 -0
- package/.agents/backend/fm-supervision-instructions.sh +215 -0
- package/.agents/backend/fm-supervision-lib.sh +90 -0
- package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
- package/.agents/backend/fm-tangle-lib.sh +53 -0
- package/.agents/backend/fm-task-inbox-lib.sh +402 -0
- package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
- package/.agents/backend/fm-teardown.sh +2922 -0
- package/.agents/backend/fm-test-isolation-proof.sh +588 -0
- package/.agents/backend/fm-test-run.sh +2191 -0
- package/.agents/backend/fm-timeout-lib.sh +141 -0
- package/.agents/backend/fm-timing-lib.sh +179 -0
- package/.agents/backend/fm-tmux-lib.sh +291 -0
- package/.agents/backend/fm-tool-update-check.sh +898 -0
- package/.agents/backend/fm-trace-context-lib.sh +227 -0
- package/.agents/backend/fm-transition-lib.sh +103 -0
- package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
- package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
- package/.agents/backend/fm-turnend-guard.sh +432 -0
- package/.agents/backend/fm-update.sh +110 -0
- package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
- package/.agents/backend/fm-voice-client.py +1373 -0
- package/.agents/backend/fm-voice-relay.py +1256 -0
- package/.agents/backend/fm-wake-drain.sh +592 -0
- package/.agents/backend/fm-wake-grant.sh +127 -0
- package/.agents/backend/fm-wake-lib.sh +1849 -0
- package/.agents/backend/fm-watch-arm.sh +602 -0
- package/.agents/backend/fm-watch-checkpoint.sh +109 -0
- package/.agents/backend/fm-watch.sh +1962 -0
- package/.agents/backend/fm-x-dismiss.sh +116 -0
- package/.agents/backend/fm-x-followup.sh +286 -0
- package/.agents/backend/fm-x-lib.sh +1000 -0
- package/.agents/backend/fm-x-link.sh +234 -0
- package/.agents/backend/fm-x-poll.sh +185 -0
- package/.agents/backend/fm-x-reply.sh +385 -0
- package/.agents/backend/fm_voice_frame.py +166 -0
- package/.agents/backend/fm_voice_records.py +574 -0
- package/.agents/backend/model-bridge.py +360 -0
- package/.agents/backend/opencode-go-bridge.py +30 -0
- package/.agents/bus/README.md +12 -0
- package/.agents/bus/messages.json +1 -0
- package/.agents/config/agents.machine.example.yaml +16 -0
- package/.agents/config/agents.yaml.example +72 -0
- package/.agents/config/crew-dispatch.json +22 -0
- package/.agents/config/cron.yaml +11 -0
- package/.agents/config/eindri-dispatch.json +67 -0
- package/.agents/config/eindri-harness +1 -0
- package/.agents/config/startup-memory-budget +1 -0
- package/.agents/filebrowser/.filebrowser.json +6 -0
- package/.agents/filebrowser/README.md +11 -0
- package/.agents/gateway/README.md +12 -0
- package/.agents/github/README.md +15 -0
- package/.agents/github/webhooks/.gitkeep +0 -0
- package/.agents/github/workflows/.gitkeep +0 -0
- package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
- package/.agents/harness/opencode/plugins/package.json +4 -0
- package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
- package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
- package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
- package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
- package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
- package/.agents/memory/README.md +46 -0
- package/.agents/memory/runes_audit.md +5 -0
- package/.agents/migrations/0001-hodd-layout.sh +38 -0
- package/.agents/migrations/0002-a2a-mcp.sh +27 -0
- package/.agents/migrations/0003-private-data-separation.sh +121 -0
- package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
- package/.agents/migrations/0005-roots-out-of-tree.sh +158 -0
- package/.agents/sandbox/Dockerfile.utgard +19 -0
- package/.agents/sandbox/README.md +14 -0
- package/.agents/sandbox/utgard.config.json +14 -0
- package/.agents/skills/README.md +59 -0
- package/.agents/skills/bragi-marketing/README.md +3 -0
- package/.agents/skills/bragi-marketing/SKILL.md +82 -0
- package/.agents/skills/eindri-homes/README.md +3 -0
- package/.agents/skills/eindri-homes/SKILL.md +291 -0
- package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
- package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
- package/.agents/skills/frigg-consent/README.md +3 -0
- package/.agents/skills/frigg-consent/SKILL.md +56 -0
- package/.agents/skills/galdr-ymirsystem/README.md +3 -0
- package/.agents/skills/galdr-ymirsystem/SKILL.md +159 -0
- package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
- package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
- package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
- package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +736 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +539 -0
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +763 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
- package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +415 -0
- package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +133 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +101 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
- package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
- package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
- package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
- package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +180 -0
- package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
- package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
- package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +503 -0
- package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
- package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
- package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
- package/.agents/skills/gjallarhorn-relay/README.md +3 -0
- package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
- package/.agents/skills/groa-update/SKILL.md +90 -0
- package/.agents/skills/hamr-adapters/README.md +3 -0
- package/.agents/skills/hamr-adapters/SKILL.md +123 -0
- package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
- package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
- package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
- package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
- package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
- package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
- package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
- package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
- package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
- package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
- package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
- package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
- package/.agents/skills/herdr-panes/README.md +3 -0
- package/.agents/skills/herdr-panes/SKILL.md +92 -0
- package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
- package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
- package/.agents/skills/hnoss-design/DESIGN.md +19 -0
- package/.agents/skills/hnoss-design/README.md +3 -0
- package/.agents/skills/hnoss-design/SKILL.md +83 -0
- package/.agents/skills/hvild-afk/README.md +3 -0
- package/.agents/skills/hvild-afk/SKILL.md +241 -0
- package/.agents/skills/jord-projects/README.md +3 -0
- package/.agents/skills/jord-projects/SKILL.md +92 -0
- package/.agents/skills/lifecycle/SKILL.md +56 -0
- package/.agents/skills/lifecycle/smoke_test.sh +57 -0
- package/.agents/skills/lifecycle/start.sh +21 -0
- package/.agents/skills/lifecycle/status.sh +35 -0
- package/.agents/skills/lifecycle/stop.sh +16 -0
- package/.agents/skills/muninn-stow/README.md +3 -0
- package/.agents/skills/muninn-stow/SKILL.md +309 -0
- package/.agents/skills/no-mistakes/SKILL.md +379 -0
- package/.agents/skills/nornir-schedule/README.md +3 -0
- package/.agents/skills/nornir-schedule/SKILL.md +25 -0
- package/.agents/skills/nornir-schedule/assets/events.md +137 -0
- package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
- package/.agents/skills/nsr-compliance/README.md +3 -0
- package/.agents/skills/nsr-compliance/SKILL.md +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
- package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
- package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
- package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
- package/.agents/skills/pr-ops/README.md +3 -0
- package/.agents/skills/pr-ops/SKILL.md +109 -0
- package/.agents/skills/ratatoskr-a2a/README.md +3 -0
- package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
- package/.agents/skills/rules-check-drift/SKILL.md +81 -0
- package/.agents/skills/saga-bearings/README.md +3 -0
- package/.agents/skills/saga-bearings/SKILL.md +26 -0
- package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
- package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
- package/.agents/skills/saga-bearings/assets/recap.md +56 -0
- package/.agents/skills/syn-recovery/README.md +3 -0
- package/.agents/skills/syn-recovery/SKILL.md +54 -0
- package/.agents/skills/tyr-check/README.md +3 -0
- package/.agents/skills/tyr-check/SKILL.md +218 -0
- package/.agents/skills/urdh-hold/README.md +3 -0
- package/.agents/skills/urdh-hold/SKILL.md +25 -0
- package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
- package/.agents/skills/urdh-hold/assets/hold.md +54 -0
- package/.agents/skills/vor-diagnostics/README.md +3 -0
- package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
- package/.agents/skills/ymir-host/README.md +3 -0
- package/.agents/skills/ymir-host/SKILL.md +35 -0
- package/.agents/skills/ymir-host/assets/desktop.md +36 -0
- package/.agents/skills/ymir-host/assets/install.md +69 -0
- package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
- package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
- package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
- package/.agents/skills/ymir-host/assets/update.md +64 -0
- package/.agents/tests/assets/board-render-harness.mjs +117 -0
- package/.agents/tests/cmux-test-safety.sh +51 -0
- package/.agents/tests/fixtures.sh +291 -0
- package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
- package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
- package/.agents/tests/fm-afk-launch.test.sh +961 -0
- package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
- package/.agents/tests/fm-afk-return.test.sh +283 -0
- package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
- package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
- package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
- package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
- package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
- package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
- package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
- package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
- package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
- package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
- package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
- package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
- package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
- package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
- package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
- package/.agents/tests/fm-backend-orca.test.sh +1357 -0
- package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
- package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
- package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
- package/.agents/tests/fm-backend.test.sh +1142 -0
- package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
- package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
- package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
- package/.agents/tests/fm-bearings-board.test.sh +414 -0
- package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
- package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
- package/.agents/tests/fm-bootstrap.test.sh +1178 -0
- package/.agents/tests/fm-branch-supervision.test.sh +552 -0
- package/.agents/tests/fm-brief.test.sh +785 -0
- package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
- package/.agents/tests/fm-busy-state.test.sh +465 -0
- package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
- package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
- package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
- package/.agents/tests/fm-check-unregister.test.sh +198 -0
- package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
- package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
- package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
- package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
- package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
- package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
- package/.agents/tests/fm-composer-ghost.test.sh +716 -0
- package/.agents/tests/fm-composer-lib.test.sh +666 -0
- package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
- package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
- package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
- package/.agents/tests/fm-control.test.sh +910 -0
- package/.agents/tests/fm-crew-state.test.sh +1610 -0
- package/.agents/tests/fm-cursor-harness.test.sh +404 -0
- package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
- package/.agents/tests/fm-cursor-primary.test.sh +708 -0
- package/.agents/tests/fm-daemon.test.sh +2740 -0
- package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
- package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
- package/.agents/tests/fm-extension-binding.test.sh +2187 -0
- package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
- package/.agents/tests/fm-fleet-sync.test.sh +721 -0
- package/.agents/tests/fm-gate-refuse.test.sh +356 -0
- package/.agents/tests/fm-gitignore-config.test.sh +89 -0
- package/.agents/tests/fm-gotmp.test.sh +230 -0
- package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
- package/.agents/tests/fm-grok-harness.test.sh +117 -0
- package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
- package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
- package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
- package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
- package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
- package/.agents/tests/fm-herdr-lab.test.sh +243 -0
- package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
- package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
- package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
- package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
- package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
- package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
- package/.agents/tests/fm-kimi-harness.test.sh +687 -0
- package/.agents/tests/fm-lint-workflows.test.sh +532 -0
- package/.agents/tests/fm-lint.test.sh +1023 -0
- package/.agents/tests/fm-muse-harness.test.sh +932 -0
- package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
- package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
- package/.agents/tests/fm-on.test.sh +507 -0
- package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
- package/.agents/tests/fm-operational-input.test.sh +160 -0
- package/.agents/tests/fm-peek-remote.test.sh +110 -0
- package/.agents/tests/fm-pending-reply.test.sh +1288 -0
- package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
- package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
- package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
- package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
- package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
- package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
- package/.agents/tests/fm-pr-merge.test.sh +2135 -0
- package/.agents/tests/fm-procevent-quota.test.sh +225 -0
- package/.agents/tests/fm-procevent-when.test.sh +406 -0
- package/.agents/tests/fm-procevent.test.sh +1745 -0
- package/.agents/tests/fm-project-origin.test.sh +110 -0
- package/.agents/tests/fm-public-followup.test.sh +2272 -0
- package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
- package/.agents/tests/fm-quota-choose.test.sh +626 -0
- package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
- package/.agents/tests/fm-remote-doctor.test.sh +625 -0
- package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
- package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
- package/.agents/tests/fm-remote-job.test.sh +768 -0
- package/.agents/tests/fm-remote-reply.test.sh +520 -0
- package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
- package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
- package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
- package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
- package/.agents/tests/fm-review-diff.test.sh +176 -0
- package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
- package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
- package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
- package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
- package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
- package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
- package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
- package/.agents/tests/fm-send-inbox.test.sh +352 -0
- package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
- package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
- package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
- package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
- package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
- package/.agents/tests/fm-send-settle.test.sh +147 -0
- package/.agents/tests/fm-send-strict.test.sh +241 -0
- package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
- package/.agents/tests/fm-session-start.test.sh +2515 -0
- package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
- package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
- package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
- package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
- package/.agents/tests/fm-spawn-batch.test.sh +148 -0
- package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
- package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
- package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
- package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
- package/.agents/tests/fm-startup-network.test.sh +712 -0
- package/.agents/tests/fm-stow-cascade.test.sh +370 -0
- package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
- package/.agents/tests/fm-supervision-events.test.sh +156 -0
- package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
- package/.agents/tests/fm-tangle-guard.test.sh +277 -0
- package/.agents/tests/fm-task-delivery.test.sh +420 -0
- package/.agents/tests/fm-task-inbox.test.sh +513 -0
- package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
- package/.agents/tests/fm-teardown.test.sh +2665 -0
- package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
- package/.agents/tests/fm-test-fixtures.test.sh +132 -0
- package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
- package/.agents/tests/fm-test-run.test.sh +1196 -0
- package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
- package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
- package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
- package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
- package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
- package/.agents/tests/fm-transition-lib.test.sh +54 -0
- package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
- package/.agents/tests/fm-update.test.sh +304 -0
- package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
- package/.agents/tests/fm-voice-relay.test.sh +4741 -0
- package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
- package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
- package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
- package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
- package/.agents/tests/fm-wake-queue.test.sh +1224 -0
- package/.agents/tests/fm-watch-arm.test.sh +821 -0
- package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
- package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
- package/.agents/tests/fm-watch-triage.test.sh +3889 -0
- package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
- package/.agents/tests/fm-x-mode.test.sh +3042 -0
- package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
- package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
- package/.agents/tests/herdr-test-safety.sh +42 -0
- package/.agents/tests/lib.sh +315 -0
- package/.agents/tests/remote-herdr-fixture.sh +125 -0
- package/.agents/tests/secondmate-helpers.sh +193 -0
- package/.agents/tests/smoke.test.sh +93 -0
- package/.agents/tests/wake-helpers.sh +338 -0
- package/.agents/tests/zellij-test-safety.sh +60 -0
- package/.agents/tools/README.md +10 -0
- package/.agents/tools/bin/tasks-cli +267 -0
- package/.agents/tools/tasks-cli.ts +216 -0
- package/AGENTS.md +498 -0
- package/CHANGELOG.md +1913 -0
- package/LICENSE +1 -1
- package/NOTICE +63 -0
- package/README.md +114 -60
- package/RULES/01-domains.md +51 -0
- package/RULES/02-agents.md +78 -0
- package/RULES/03-houses.md +61 -0
- package/RULES/04-hoard.md +97 -0
- package/RULES/05-platforms.md +67 -0
- package/RULES/06-append-only.md +108 -0
- package/RULES/07-config.md +101 -0
- package/RULES/08-delivery-gate.md +75 -0
- package/RULES/09-electron.md +58 -0
- package/RULES/README.md +22 -0
- package/bin/README.md +107 -0
- package/bin/a2a-mcp.sh +133 -0
- package/bin/a2a-serve.py +103 -0
- package/bin/a2a-serve.sh +8 -0
- package/bin/a2a-talk.sh +50 -0
- package/bin/a2abridge-ensure.sh +108 -0
- package/bin/agent-run.sh +43 -0
- package/bin/agents-config.sh +256 -0
- package/bin/apodex-smoke-test.sh +105 -0
- package/bin/bifrost-bridge.sh +131 -0
- package/bin/bifrost-ingress.sh +77 -0
- package/bin/bootstrap-macos.sh +112 -0
- package/bin/bootstrap-windows.ps1 +112 -0
- package/bin/branch-guard.sh +64 -0
- package/bin/brokk +73 -0
- package/bin/brokk-classify-lib.sh +1770 -0
- package/bin/brokk-lease-lib.sh +222 -0
- package/bin/brokk-lease.sh +193 -0
- package/bin/brokk-lint.sh +65 -0
- package/bin/brokk-send.sh +51 -0
- package/bin/brokk-update.sh +9 -0
- package/bin/brokk-wake-grant.sh +127 -0
- package/bin/brokk-wake-lib.sh +1849 -0
- package/bin/changelog-assemble.sh +154 -0
- package/bin/changelog-guard.sh +197 -0
- package/bin/crash-sense.sh +173 -0
- package/bin/design-check.sh +80 -0
- package/bin/design-icon.sh +153 -0
- package/bin/desktop-place.sh +224 -0
- package/bin/docs-guard.sh +39 -0
- package/bin/editor-place.sh +225 -0
- package/bin/eindri-acclaim.sh +47 -0
- package/bin/eindri-control.sh +28 -0
- package/bin/eindri-role.sh +83 -0
- package/bin/eindri-seat.sh +83 -0
- package/bin/eindri-seen.sh +54 -0
- package/bin/eindri-send.sh +15 -0
- package/bin/eindri-start.sh +98 -0
- package/bin/eindri-watch.sh +57 -0
- package/bin/einherjar-spawn.sh +576 -0
- package/bin/eir-doctor.sh +158 -0
- package/bin/erindi-brief.sh +271 -0
- package/bin/feature-inventory.sh +73 -0
- package/bin/fleet-apply.sh +81 -0
- package/bin/github-deploy.sh +94 -0
- package/bin/gjallarhorn-expose.sh +136 -0
- package/bin/gjallarhorn-notify.sh +71 -0
- package/bin/gjallarhorn-purge.sh +67 -0
- package/bin/gjallarhorn-tunnel.sh +85 -0
- package/bin/gleipnir-lock-lib.sh +284 -0
- package/bin/groa-update.sh +130 -0
- package/bin/hall-snapshot.sh +111 -0
- package/bin/hamr-harness.sh +246 -0
- package/bin/heimdall-ssh-keys.sh +374 -0
- package/bin/herdr-agents.py +44 -0
- package/bin/herdr-ensure.sh +104 -0
- package/bin/herdr-run.sh +452 -0
- package/bin/hermes-ensure.sh +88 -0
- package/bin/hlidskjalf-agents.sh +172 -0
- package/bin/hlidskjalf-usage.sh +196 -0
- package/bin/hoard-guard.sh +135 -0
- package/bin/hoard-lib.sh +105 -0
- package/bin/hodd.sh +102 -0
- package/bin/host-sense.sh +199 -0
- package/bin/huginn-research-worker.sh +121 -0
- package/bin/local-model-lock.sh +70 -0
- package/bin/mimir-bridge.py +259 -0
- package/bin/mimir-bridge.sh +100 -0
- package/bin/mimir-ingest.sh +131 -0
- package/bin/mimir-reflect.sh +27 -0
- package/bin/mimir.sh +113 -0
- package/bin/mjollnir-webhook.sh +72 -0
- package/bin/mjollnir.sh +104 -0
- package/bin/model-hardware.sh +96 -0
- package/bin/model-resolve.sh +160 -0
- package/bin/models-detect.sh +178 -0
- package/bin/nornir-cron-start.sh +162 -0
- package/bin/nornir-job-daily-briefing.sh +191 -0
- package/bin/nornir-job-git-sync.sh +152 -0
- package/bin/nornir-job-hall-snapshot.sh +28 -0
- package/bin/nornir-job-memory-housekeeping.sh +114 -0
- package/bin/nornir-job-nsr-compliance.sh +54 -0
- package/bin/nornir-job-observer.sh +166 -0
- package/bin/nornir-job-skillopt-sleep.sh +76 -0
- package/bin/npm-publish.sh +136 -0
- package/bin/omarchy-hook-install.sh +60 -0
- package/bin/omarchy-install.sh +161 -0
- package/bin/omarchy-plugins.sh +187 -0
- package/bin/omarchy-sense.sh +162 -0
- package/bin/perm-guard.sh +30 -0
- package/bin/pi-agent.sh +68 -0
- package/bin/pi-ensure.sh +77 -0
- package/bin/pi-local.sh +37 -0
- package/bin/pi-model-agnostic.sh +71 -0
- package/bin/pi-seat.sh +63 -0
- package/bin/prereq-ensure.sh +166 -0
- package/bin/private-guard.sh +58 -0
- package/bin/project-git.sh +69 -0
- package/bin/public-guard.sh +71 -0
- package/bin/ratatoskr.sh +49 -0
- package/bin/realm-lib.sh +32 -0
- package/bin/repo-scrub.sh +62 -0
- package/bin/rodd-operational-input.sh +250 -0
- package/bin/runes-append.sh +198 -0
- package/bin/saga-session-start.sh +172 -0
- package/bin/saga-sessionstart-run.sh +79 -0
- package/bin/saga-wake-drain.sh +41 -0
- package/bin/secret-guard.sh +63 -0
- package/bin/sessrumnir-ensure.sh +100 -0
- package/bin/sessrumnir-sync.sh +237 -0
- package/bin/sessrumnir.sh +104 -0
- package/bin/skillopt-setup.sh +76 -0
- package/bin/skuld-branch-outcome.sh +203 -0
- package/bin/skuld-branch-prompt.sh +101 -0
- package/bin/smidja-bootstrap.sh +94 -0
- package/bin/smidja-observe.sh +86 -0
- package/bin/syn-arm-pretool-check.sh +57 -0
- package/bin/syn-asset-pretool-check.sh +89 -0
- package/bin/syn-cd-pretool-check.sh +28 -0
- package/bin/syn-guard-pretool-check.sh +83 -0
- package/bin/syn-spawn-pretool-check.sh +58 -0
- package/bin/syn-turnend-guard.sh +36 -0
- package/bin/syn-watch-arm.sh +99 -0
- package/bin/tailscale-sync.sh +203 -0
- package/bin/telegram-bot.sh +82 -0
- package/bin/toolchain.sh +74 -0
- package/bin/ui-truth-check.sh +75 -0
- package/bin/utgard.sh +111 -0
- package/bin/valhalla.sh +115 -0
- package/bin/valknut-load.sh +298 -0
- package/bin/vor-crew-state.sh +124 -0
- package/bin/wedge-notify.sh +60 -0
- package/bin/workspace-provision.sh +80 -0
- package/bin/workspace-rag.sh +163 -0
- package/bin/wyrd-db.sh +47 -0
- package/bin/yggdrasil.sh +152 -0
- package/bin/ymir-edit.sh +145 -0
- package/bin/ymir-install.sh +806 -0
- package/bin/ymir-invite.sh +93 -0
- package/bin/ymir-isolation.sh +88 -0
- package/bin/ymir-migrate.sh +61 -0
- package/bin/ymir-plan.sh +356 -0
- package/bin/ymir-platform.sh +348 -0
- package/bin/ymir-say.sh +110 -0
- package/bin/ymir-setup-auth.sh +119 -0
- package/bin/ymir-validate.sh +193 -0
- package/bin/ymir.js +74 -16
- package/docs/Architecture.md +339 -0
- package/docs/design.md +351 -0
- package/docs/installations/README.md +63 -0
- package/docs/installations/ymir-home.md +93 -0
- package/docs/integration.md +105 -0
- package/docs/lore.md +1060 -0
- package/docs/research/agent-harnesses.md +290 -0
- package/docs/runbooks/README.md +19 -0
- package/docs/runbooks/a2a.md +91 -0
- package/docs/runbooks/agent-permissions.md +99 -0
- package/docs/runbooks/agents.md +57 -0
- package/docs/runbooks/models.md +69 -0
- package/docs/runbooks/realm-onboarding.md +60 -0
- package/docs/runbooks/secrets-and-hoard.md +60 -0
- package/docs/runbooks/updates-and-migrations.md +110 -0
- package/docs/runbooks/worktrees-isolation.md +72 -0
- package/docs/session-start.md +105 -0
- package/docs/skillopt-integration.md +321 -0
- package/docs/sync-system.md +66 -0
- package/docs/workspaces.md +104 -0
- package/docs/ymir-rut.md +260 -0
- package/package.json +54 -14
- package/packaging/build.sh +74 -0
- package/packaging/macos/Ymir Installer.command +43 -0
- package/packaging/windows/ymir-setup.nsi +74 -0
- package/scripts/README.md +22 -0
- package/scripts/electron.sh +269 -0
- package/scripts/lower.sh +34 -0
- package/scripts/raise.sh +42 -0
- package/scripts/start.sh +217 -0
- package/scripts/stop.sh +113 -0
- package/install.sh +0 -35
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
# Harness Integration — the Ymir harness adapter matrix and adapter contract
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Define how each agent harness (OpenCode, Pi, Claude Code, Cursor, Codex, Grok) seats **Brokk** before the first turn, arms **Sýn** supervision, guards the turn end, and enforces the PreToolUse seatbelts — and give a step-by-step recipe to add a new harness.
|
|
4
|
+
|
|
5
|
+
This is the reference an agent reads to add a harness adapter or rebuild one from scratch. It is paired with one deep-dive file per harness:
|
|
6
|
+
|
|
7
|
+
| Deep dive | Harness |
|
|
8
|
+
|---|---|
|
|
9
|
+
| [`opencode.md`](opencode.md) | OpenCode (Öppencode) |
|
|
10
|
+
| [`pi.md`](pi.md) | Pi (`@earendil-works/pi-coding-agent`) |
|
|
11
|
+
| [`claude-code.md`](claude-code.md) | Claude Code |
|
|
12
|
+
| [`cursor.md`](cursor.md) | Cursor |
|
|
13
|
+
| [`codex.md`](codex.md) | Codex |
|
|
14
|
+
| *(none — not implemented)* | Grok |
|
|
15
|
+
|
|
16
|
+
Runtime inventory that every adapter calls: [`../runtime-components.md`](../runtime-components.md).
|
|
17
|
+
The governing plan is [`docs/plans/29-brokk-distro-runtime.md`](../../../../../docs/plans/29-brokk-distro-runtime.md) (referred to below as **plan 29**), whose §12 carries the Norse naming law.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. What a harness adapter is
|
|
22
|
+
|
|
23
|
+
> **MCP scope (well · mesh · Teams · Anchor).** `bin/a2a-mcp.sh install` wires the
|
|
24
|
+
> `engram` (memory well) and `a2abridge` (A2A mesh) MCP servers into OpenCode's
|
|
25
|
+
> repo `opencode.json` **and** Pi. The **Teams** plane (`wayofteams`) and
|
|
26
|
+
> **Anchor** memory are **remote** MCP servers named by URL: set
|
|
27
|
+
> `WAYOFTEAMS_MCP_URL` / `ANCHOR_MCP_URL` in the private platform env, then run
|
|
28
|
+
> `bin/a2a-mcp.sh install`. OpenCode speaks `type: remote` natively; Pi has no
|
|
29
|
+
> remote transport, so it reaches them through the `mcp-remote` stdio bridge. The
|
|
30
|
+
> URLs never enter the tracked tree. By default the Pi side writes the **global**
|
|
31
|
+
> `~/.pi/agent/mcp.json`; `bin/a2a-mcp.sh install --project` writes the repo's
|
|
32
|
+
> `.pi/mcp.json` instead, leaving a Pi used elsewhere untouched (launch with
|
|
33
|
+
> `pi --mcp-config .pi/mcp.json`). Prefer `--project` when integrating Ymir into
|
|
34
|
+
> an existing workflow. `bin/a2a-mcp.sh show` reports what is **actually** wired —
|
|
35
|
+
> every key present, not a fixed list.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
The Ymir runtime is a **distro**: a directory of instructions, skills, tooling and conventions that turns a general-purpose agent into a specialized one. Launching a supported harness inside `BROKK_HOME` is supposed to instantiate **Brokk** and address the operator as the **Allfather** *before the model's first turn*.
|
|
39
|
+
|
|
40
|
+
A harness will not do that on its own. Each harness exposes a different set of lifecycle hooks, and each adapter is a thin, harness-specific shim that binds those hooks to **harness-agnostic runtime scripts** in `bin/`. The shim never re-implements runtime logic: it only decides *when* to call a script and *how* to deliver the result.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
harness lifecycle event ──► adapter shim ──► bin/<owner script> ──► state/ data/
|
|
44
|
+
(session open / idle / (.opencode, (Sága, Sýn, Rödd,
|
|
45
|
+
turn end / tool call) .pi, hooks.json) Gleipnir, ...)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Every adapter must satisfy the **four-part adapter contract** (§3). A harness with no adapter is *unverified* and must never be used for a dispatched Eindri (`bin/einherjar-spawn.sh` fails closed).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. Run-tier vs nudge-tier
|
|
53
|
+
|
|
54
|
+
The tier answers **how the session-start digest reaches model context**.
|
|
55
|
+
|
|
56
|
+
| Tier | Meaning | Contract |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| **run-tier** | The harness's session-open adapter can **execute** a command and inject its stdout into model context (or as the session's first context) before the model acts. | Adapter calls `bin/saga-sessionstart-run.sh`; the digest text is delivered natively. Nothing is left to the model's discretion. |
|
|
59
|
+
| **nudge-tier** | The harness can only post a message into the session and **ask** the model to take the helm. The model can defer. | Adapter calls `bin/saga-sessionstart-run.sh` (which emits the digest *or* a one-line "run `bin/saga-session-start.sh` now" instruction) and delivers it as a prompt/follow-up. |
|
|
60
|
+
|
|
61
|
+
Important nuance: **tier is per-event, not per-harness.** All current harnesses are run-tier for the session-open digest *except* the disabled/Grok path. But `bin/saga-sessionstart-run.sh` deliberately emits a **nudge** for context-preserving opens (`resume`, `reload`, `fork`) even on a run-tier harness, because re-running the whole digest is redundant when prior context is restored:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# bin/saga-sessionstart-run.sh:70-72
|
|
65
|
+
resume|reload|fork)
|
|
66
|
+
printf 'Run `%s` exactly once now, before executing any other instructions.\n' "bash $SCRIPT_DIR/saga-session-start.sh"
|
|
67
|
+
;;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
So the digest is *run* on `startup`/`new`, *re-emitted* on `clear`/`compact` after a completed startup, and *nudged* on `resume`/`reload`/`fork`.
|
|
71
|
+
|
|
72
|
+
### Tier + mechanism per harness
|
|
73
|
+
|
|
74
|
+
| Harness | Tier | Session-open mechanism | Source value(s) seen |
|
|
75
|
+
|---|---|---|---|
|
|
76
|
+
| OpenCode | run (nudge delivery) | plugin `session.created` runs `saga-sessionstart-run.sh`, injects stdout through `client.session.promptAsync` | (wrapper chooses from no payload) |
|
|
77
|
+
| Pi | run | extension `before_agent_start` returns a `syn-sessionstart-nudge` message built from the wrapper | `startup`, `clear`, `resume`, `fork`, `compact` |
|
|
78
|
+
| Claude Code | run | `SessionStart` hook stdout is injected; wrapper reads `source` from the hook JSON on stdin | `startup`, `resume`, `clear`, `compact` |
|
|
79
|
+
| Cursor | run | `sessionStart` hook returns JSON `{"additional_context": "..."}` | `--source startup` (explicit) |
|
|
80
|
+
| Codex | run | `SessionStart` hook pipes the JSON payload into `saga-sessionstart-run.sh` | parsed from payload |
|
|
81
|
+
| Grok | nudge (upstream only) | upstream uses `.grok/hooks/*sessionstart-nudge.json` | — (not implemented in Ymir) |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 3. The adapter contract (four required parts + one optional)
|
|
86
|
+
|
|
87
|
+
Every production adapter implements the same four responsibilities. The harness-specific *how* lives in the deep-dive files; the *what* is fixed here.
|
|
88
|
+
|
|
89
|
+
### Part 1 — Session-open injection
|
|
90
|
+
|
|
91
|
+
Bind the harness's "session is opening" event to `bin/saga-sessionstart-run.sh`.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# The one command every session-open adapter invokes.
|
|
95
|
+
"$BROKK_ROOT/bin/saga-sessionstart-run.sh" [--source <src>] [--pi-prerequisite]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- `--source` ∈ `startup|new|clear|compact|resume|reload|fork`; absent → parse a Claude/Codex-shaped JSON hook payload on stdin, default `startup`.
|
|
99
|
+
- `--pi-prerequisite` is Pi-only: an intentional stand-down exits **3** so Pi provider preflight can tell it apart from an eligible attempt that produced nothing.
|
|
100
|
+
- **Every ordinary transport path exits 0.** A failed session start must reach the agent as digest text it can act on, never as a refusal to open the session. (Claude `SessionStart` exit 2 blocks initialization.)
|
|
101
|
+
- The script records `state/.session-start-complete` so `clear`/`compact` can re-emit instead of re-running.
|
|
102
|
+
|
|
103
|
+
### Part 2 — Watch arm (Sýn supervision)
|
|
104
|
+
|
|
105
|
+
Bind a "session is idle / turn ended" event to arm **one** `bin/syn-watch-arm.sh` cycle, and let the adapter own **continuity** (re-arming) so no model tokens are spent on ordinary re-arms.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
bin/syn-watch-arm.sh --restart
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The arm script polls `state/` every `BROKK_WATCH_POLL_SECONDS` (default 5), writes `state/.watch.heartbeat`, and exits with an actionable line when the wake queue or a `*.signal`/`*.check`/`.watcher-stop` appears:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
signal: wake queue
|
|
115
|
+
signal: <name>
|
|
116
|
+
check: <name>
|
|
117
|
+
stale: watcher stopped by operator
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
It refuses to arm with exit 0 and a `watcher: read-only - the session helm is held by
|
|
121
|
+
another live session` message **only** when a genuinely live other session holds the helm.
|
|
122
|
+
A **vacant** helm — no owner, a dead/zombie/recycled owner, or a truncated/empty
|
|
123
|
+
lock — is entered in place: the arm script runs `gleipnir_lock_acquire` (which
|
|
124
|
+
refuses only a verifiably live owner), and the Pi extension classifies an empty
|
|
125
|
+
lock as `missing` so `gna_watch_arm`'s reclaim takes it directly. A vacant helm
|
|
126
|
+
is never punted to a manual session start; only a real live contender is refused.
|
|
127
|
+
|
|
128
|
+
- **Pi** owns continuity in `gna-pi-watch.ts` (Gná); the model gets a **tool** `gna_watch_arm` and a command `/gna-watch-arm` for the first cycle or a repair, never for ordinary re-arms. Gná's liveness is **zombie-aware**: `kill(pid, 0)` alone passes a zombie and a recycled pid, so the watcher reads `/proc/<pid>/stat` — the state character (Z/X = dead) and the starttime recorded at lock acquire (field 22; a mismatch means the kernel handed the pid to an unrelated process) — answers every ordinary wake: a **vacant** helm is taken (arm script via `gleipnir_lock_acquire`; Gná classifies an empty lock as `missing` so the reclaim takes it in place), while only a verifiably live other owner is refused as read-only. It drops its own lock on real process exit (`releaseLockIfOwned`). Gná's wake delivery is **echo-guarded**: an identical watcher message is sent at most once per drained state — when both durable queues (`state/.wake-queue` and the FM runner's `.agents/state/.wake-queue`) are empty, a repeat is the same news the primary already drained and is not re-delivered, so a long stale window cannot flood the follow-up queue.
|
|
129
|
+
- **OpenCode** owns continuity in `syn-watch-arm.js` (Sýn); the coordinator is published under `globalThis.__brokkOpenCodeWatchArm` so the turn-end guard can consult it first.
|
|
130
|
+
- **Claude Code** uses the `Stop` hook with `"asyncRewake": true` and a long timeout to keep the arm running out of band.
|
|
131
|
+
- **Codex / Cursor** run `syn-turnend-guard.sh` at Stop; they do **not** own a long-lived arm (no auto re-arm).
|
|
132
|
+
|
|
133
|
+
### Part 3 — Turn-end guard
|
|
134
|
+
|
|
135
|
+
Bind the harness's "turn is about to end" event to `bin/syn-turnend-guard.sh`. If the guard prints the recovery instruction and exits **2**, the adapter must re-prompt instead of letting the turn end blind.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
bin/syn-turnend-guard.sh [--claude]
|
|
139
|
+
# reads Claude/Codex-shaped {"stop_hook_active":false} on stdin (ignored)
|
|
140
|
+
# exit 0 = supervision healthy OR never armed (inert)
|
|
141
|
+
# exit 2 = supervision was armed and the watcher is missing/stale; stderr carries recovery
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The guard is **inert until the first successful arm** writes `state/.supervision-armed`:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# bin/syn-turnend-guard.sh:20
|
|
148
|
+
[ -f "$STATE/.supervision-armed" ] || exit 0
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
It goes stale when `now - state/.watch.heartbeat > BROKK_WATCH_HEARTBEAT_STALE_SECONDS` (default 60).
|
|
152
|
+
|
|
153
|
+
### Part 4 — PreToolUse seatbelts
|
|
154
|
+
|
|
155
|
+
Bind the harness's pre-tool event for shell commands to the two owner scripts. Exit **2** (or throw) blocks the tool call.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
bin/syn-arm-pretool-check.sh --command "<bash command>" # denies backgrounding the watcher arm
|
|
159
|
+
bin/syn-cd-pretool-check.sh --command "<bash command>" # denies a persistent escaping `cd`
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Both are **v0 inert-by-default** contracts: `syn-arm-pretool-check.sh` blocks only a command that backgrounds `syn-watch-arm.sh`; `syn-cd-pretool-check.sh` blocks only `cd .../../`. Owner scripts hold the policy; adapters only relay.
|
|
163
|
+
|
|
164
|
+
**A third seatbelt guards the assets** — `bin/syn-asset-pretool-check.sh` denies an
|
|
165
|
+
`edit`/`write` of a governed path until its owning asset has been read in the
|
|
166
|
+
session (reads are recorded in `state/asset-reads`).
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
bin/syn-asset-pretool-check.sh --path "<file>" # exit 2 when the asset is not loaded
|
|
170
|
+
bin/syn-asset-pretool-check.sh --note "<asset path>" # record an asset as read
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Who governs what:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
governed[6]{path,load_first}:
|
|
177
|
+
"bin/ymir-install.sh",".agents/skills/galdr-ymirsystem/assets/installation.md"
|
|
178
|
+
"apps/hlidskjalf/**",".agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md"
|
|
179
|
+
"bin/mimir*",".agents/skills/galdr-ymirsystem/assets/memory-well.md"
|
|
180
|
+
"bin/nornir-* | config/cron.yaml",".agents/skills/galdr-ymirsystem/assets/nornir-jobs.md"
|
|
181
|
+
"bin/valknut-load.sh | .pi/** | .opencode/**",".agents/skills/galdr-ymirsystem/assets/harness-integration/README.md"
|
|
182
|
+
"bin/smidja* | .agents/skills/smidja/**",".agents/skills/galdr-ymirsystem/assets/smidja.md"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The Pi extension `.pi/extensions/syn-turnend-guard.ts` relays it: `read` of an
|
|
186
|
+
asset is recorded, and an `edit`/`write` of a governed path is blocked with the
|
|
187
|
+
reason. The guard's own liveness check is **zombie-aware** too — `/proc/<pid>/stat`
|
|
188
|
+
field 3 (Z/X = a killed-but-unreaped or dead holder) fails a stale lock even when
|
|
189
|
+
`kill(0)` would report the pid alive, with `kill(0)` as the fallback when `/proc`
|
|
190
|
+
is unavailable. The same routes are stated in `AGENTS.md` and printed in the session
|
|
191
|
+
digest under `ASSET ROUTING`, and `compliance-check.sh` fails on a governed file
|
|
192
|
+
changed without its asset (the `assets` gate).
|
|
193
|
+
|
|
194
|
+
### Part 5 (optional) — Re-arm / stop auto-arm
|
|
195
|
+
|
|
196
|
+
Some harnesses cannot synchronously own the watcher at Stop. The supported pattern is an **async rewrite** hook (Claude Code `"asyncRewake": true`; Cursor `followup_message` loop) that re-runs the arm and surfaces actionable output on stderr. If the harness has no such mechanism, do not fake it — declare the harness **turn-end-only** (Codex, Cursor) and rely on `einherjar-spawn.sh` fail-closed dispatch.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 4. The adapter matrix
|
|
201
|
+
|
|
202
|
+
Legend: ✅ implemented · ⚠️ partial/inert-by-design · ❌ not implemented.
|
|
203
|
+
|
|
204
|
+
| Harness | Session-open injection | Watch arm owner | Turn-end guard | Pretool (arm) | Pretool (cd) | Re-arm |
|
|
205
|
+
|---|---|---|---|---|---|---|
|
|
206
|
+
| **OpenCode** | ✅ `.agents/harness/opencode/plugins/saga-sessionstart.js` | ✅ `.agents/harness/opencode/plugins/syn-watch-arm.js` (`session.idle`, coordinator key) | ✅ `.agents/harness/opencode/plugins/syn-turnend-guard.js` | ✅ `syn-pretool-check.js` | ✅ `syn-cd-check.js` | ✅ plugin-owned retries |
|
|
207
|
+
| **Pi** | ✅ `.pi/extensions/syn-turnend-guard.ts` (`before_agent_start`) | ✅ `.pi/extensions/gna-pi-watch.ts` (`gna_watch_arm` tool) | ✅ same extension (`agent_settled`) | ✅ same extension (`tool_call`) | ✅ same extension (`tool_call`) | ✅ Gná retry/backoff |
|
|
208
|
+
| **Claude Code** | ✅ `.claude/settings.json` `SessionStart` | ✅ `Stop` + `syn-watch-arm.sh --restart` (`asyncRewake`) | ✅ `Stop` + `syn-turnend-guard.sh --claude` | ❌ | ❌ | ✅ async rewake |
|
|
209
|
+
| **Codex** | ✅ `.codex/hooks.json` `SessionStart` | ⚠️ no long-lived arm | ✅ `Stop` + `syn-turnend-guard.sh` | ✅ `PreToolUse` matcher `Bash` | ✅ `PreToolUse` matcher `Bash` | ❌ |
|
|
210
|
+
| **Cursor** | ✅ `.cursor/hooks.json` `sessionStart` | ⚠️ interactive only | ✅ `stop` → `{"followup_message":...}` | ✅ `preToolUse` matcher `Shell` | ✅ `preToolUse` matcher `Shell` | ❌ |
|
|
211
|
+
| **Grok** | ❌ no `.grok/` in Ymir | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
212
|
+
|
|
213
|
+
### Adapter files at a glance
|
|
214
|
+
|
|
215
|
+
| Path | Exports / shape | Contract parts |
|
|
216
|
+
|---|---|---|
|
|
217
|
+
| `.agents/harness/opencode/plugins/saga-sessionstart.js` | `export const SagaSessionstart` | 1 |
|
|
218
|
+
| `.agents/harness/opencode/plugins/syn-watch-arm.js` | `export const SynWatchArm` | 2 |
|
|
219
|
+
| `.agents/harness/opencode/plugins/syn-turnend-guard.js` | `export const SynTurnendGuard` | 2 (consult coordinator), 3 |
|
|
220
|
+
| `.agents/harness/opencode/plugins/syn-pretool-check.js` | `export const SynPretoolCheck` | 4 (arm) |
|
|
221
|
+
| `.agents/harness/opencode/plugins/syn-cd-check.js` | `export const SynCdCheck` | 4 (cd) |
|
|
222
|
+
| `.agents/harness/opencode/plugins/lib/rodd-operational-input.js` | `encodeRoddOperationalInput(root, kind, content)` | shared wire |
|
|
223
|
+
| `.pi/extensions/syn-turnend-guard.ts` | `export default function (pi: ExtensionAPI)` | 1, 3, 4 |
|
|
224
|
+
| `.pi/extensions/gna-pi-watch.ts` | `export default function (pi: ExtensionAPI)` | 2 |
|
|
225
|
+
| `.pi/extensions/ro.ts` | Ró — the calm presentation preference (`/calm`), state/ro | user |
|
|
226
|
+
| `.pi/shared/extensions/open-editor.ts` | `/edit [path]` and `ctrl+shift+e` — opens files from cwd in the Allfather's editor; strictly user-facing, no LLM tool. **Resolution:** `$VISUAL` → `$EDITOR` → the first editor that exists (`code cursor zed subl nvim vim hx helix nano micro emacs vi`), so a host that is not Omarchy — where Omarchy's own launcher or a bare `vi` may be absent — still gets a working editor instead of an ENOENT | user |
|
|
227
|
+
| `.pi/shared/extensions/herdr-agent-state.ts` | reports pane agent lifecycle state to herdr | 2 |
|
|
228
|
+
| `.pi/shared/extensions/todo.ts` | the todo surface | user |
|
|
229
|
+
| `.pi/shared/extensions/ymir-subagents.ts` | **the Eindri roster as a Pi tool** — reads the canonical `.agents/agents/*.md` tree and exposes every figure through a `subagent` tool (and a `/subagents` command). See "Pi has no agent loader" below | user |
|
|
230
|
+
| `.pi/shared/extensions/lib/rodd-operational-input.ts` | `encodeRoddOperationalInput`, `classifyRoddOperationalText`, `classifyRoddCurrentOperationalText` | shared wire |
|
|
231
|
+
| `.pi/extensions/lib/vordr-sessionstart-supervisor.mjs` | detached child supervisor (Vörðr) | 1 (transport) |
|
|
232
|
+
| `.claude/settings.json` | `hooks.SessionStart[]`, `hooks.Stop[]` | 1, 3, 5 |
|
|
233
|
+
| `.codex/hooks.json` | `hooks.SessionStart[]`, `hooks.PreToolUse[]`, `hooks.Stop[]` | 1, 3, 4 |
|
|
234
|
+
| `.cursor/hooks.json` | `hooks.sessionStart[]`, `hooks.preToolUse[]`, `hooks.stop[]` | 1, 3, 4 |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 5. The environment contract
|
|
239
|
+
|
|
240
|
+
Every adapter and script resolves the same runtime roots. The overrides exist so tests and realm homes can relocate the runtime without touching the launcher.
|
|
241
|
+
|
|
242
|
+
| Variable | Meaning | Default |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| `BROKK_ROOT_OVERRIDE` | tracked code root (holds `bin/`, `AGENTS.md`) | resolved from script location |
|
|
245
|
+
| `BROKK_HOME` | private home (holds `data/ state/ config/`) | `BROKK_ROOT_OVERRIDE` or repo root |
|
|
246
|
+
| `BROKK_STATE_OVERRIDE` | state dir | `$BROKK_HOME/state` |
|
|
247
|
+
| `BROKK_DATA_OVERRIDE` | data dir | `$BROKK_HOME/data` |
|
|
248
|
+
| `BROKK_CONFIG_OVERRIDE` | config dir | `$BROKK_HOME/config` |
|
|
249
|
+
| `BROKK_REALM` | active realm | `data/realm.md` line 1, else `way-of` |
|
|
250
|
+
| `BROKK_SESSION_PID` | **live harness PID** bound by the session lock | `${BROKK_SESSION_PID:-$$}` |
|
|
251
|
+
| `BROKK_SESSIONSTART_INELIGIBLE` | `1` makes Pi's prerequisite exit 3 | unset |
|
|
252
|
+
|
|
253
|
+
`BROKK_SESSION_PID` is the load-bearing variable. The lock must bind to the **live harness process**, not the short-lived digest helper: Pi/OpenCode adapters pass `BROKK_SESSION_PID=String(process.pid)` into the spawned digest/arm child (`.pi/extensions/syn-turnend-guard.ts:277`, `.agents/harness/opencode/plugins/syn-watch-arm.js:428`). `bin/gleipnir-lock-lib.sh` writes it to `state/.lock`.
|
|
254
|
+
|
|
255
|
+
Full variable inventory: [`../runtime-components.md`](../runtime-components.md) §5.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 6. Fail-closed dispatch rules
|
|
260
|
+
|
|
261
|
+
Dispatch is owned by `bin/einherjar-spawn.sh` (Norse: **Einherjar**). It **never silently falls back** to an unverified harness.
|
|
262
|
+
|
|
263
|
+
| Rule | Where | Behavior |
|
|
264
|
+
|---|---|---|
|
|
265
|
+
| Verified adapter set | `bin/einherjar-spawn.sh:53` | `VERIFIED_HARNESSES='opencode pi pi-signed'` |
|
|
266
|
+
| Unverified harness | `bin/einherjar-spawn.sh:224-232` | `error: harness '<h>' is not verified for direct launch` → exit 1 |
|
|
267
|
+
| Missing executable | `bin/einherjar-spawn.sh:233-236` | `error: harness '<h>' executable not found on PATH` → exit 1 |
|
|
268
|
+
| Missing auth/dependency | adapter scripts | report a plain reason; never a silent fallback |
|
|
269
|
+
| Raw launch escape hatch | `bin/einherjar-spawn.sh:207-211` | a `--harness` value containing whitespace is treated as a raw command, warns loudly, and is *not* on the verified set |
|
|
270
|
+
| Active dispatch profiles | `bin/einherjar-spawn.sh:212-214` | if `config/eindri-dispatch.json` exists, a fresh spawn **must** pass an explicit `--harness` resolved from its rules |
|
|
271
|
+
| Brief/flag drift | `bin/einherjar-spawn.sh:327-335` | refuses a ship launch whose brief's `Delivery contract: mode=<m>` disagrees with `--mode` |
|
|
272
|
+
| Isolation dependency | `bin/einherjar-spawn.sh:340-359` | `--isolation on` requires docker + `utgard-runner:latest`, else exit 1; `auto` reports the decision |
|
|
273
|
+
|
|
274
|
+
**Adding a harness to the verified set is a deliberate act:** implement all four contract parts, smoke-test them, then add the adapter name to `VERIFIED_HARNESSES` in `bin/einherjar-spawn.sh` (see §8).
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## 7. How to add a new harness (step-by-step)
|
|
279
|
+
|
|
280
|
+
A harness is a runtime that can host Brokk. Adding one is a five-stage task.
|
|
281
|
+
|
|
282
|
+
### Stage 0 — Inventory the harness's lifecycle
|
|
283
|
+
|
|
284
|
+
Answer these before writing anything:
|
|
285
|
+
|
|
286
|
+
1. Does a **session-open** hook exist, and can it inject stdout into context (run-tier) or only post a message (nudge-tier)?
|
|
287
|
+
2. Does an **idle/turn-end** event exist for the guard?
|
|
288
|
+
3. Can a **long-lived arm process** be spawned at Stop, or only a synchronous hook?
|
|
289
|
+
4. Is there a **pre-tool / before-tool** event for shell commands, and can it block?
|
|
290
|
+
5. What env var names does the harness export (project dir, workspace root, agent marker)?
|
|
291
|
+
|
|
292
|
+
### Stage 1 — Add detection to Hamr
|
|
293
|
+
|
|
294
|
+
`bin/hamr-harness.sh` (Norse: **Hamr**, "the shape a being wears") is the single source of harness identity. Two layers, in precedence order:
|
|
295
|
+
|
|
296
|
+
- **Layer 1 — verified env markers** (`bin/hamr-harness.sh:112-135`). Add your marker *after* the Cursor/Claude/Pi/Grok markers, documenting the version you verified it on.
|
|
297
|
+
- **Layer 2 — process ancestry** (`bin/hamr-harness.sh:136-169`). Add a `*<name>*` case to the `comm` matcher and to the bare-interpreter `args` matcher.
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# bin/hamr-harness.sh — Layer 1 pattern
|
|
301
|
+
[ "${MYHARNESS_AGENT:-}" = "1" ] && { echo myharness; return; }
|
|
302
|
+
# Layer 2 pattern
|
|
303
|
+
case "$(basename -- "$comm")" in
|
|
304
|
+
*myharness*) echo myharness; return ;;
|
|
305
|
+
esac
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Reuse the shared Cursor identity helpers (`hamr_cursor_process_matches`, `hamr_cursor_argv0_for_pid`) if your harness shares an interpreter.
|
|
309
|
+
|
|
310
|
+
### Stage 2 — Write the adapter
|
|
311
|
+
|
|
312
|
+
Pick the closest existing adapter in the table (§4) and mirror its structure. The rules are non-negotiable:
|
|
313
|
+
|
|
314
|
+
- **Resolve the root** the same way: prefer `worktree` → `git -C <dir> rev-parse --show-toplevel` → `realpathSync(dir)`.
|
|
315
|
+
- **Call only `bin/` owner scripts.** Never re-implement digest, arm, guard, or classification logic.
|
|
316
|
+
- **Session-open:** call `bin/saga-sessionstart-run.sh`. Never `bin/saga-session-start.sh` directly from an adapter.
|
|
317
|
+
- **Watch arm:** require a live lock. If the arm reports `read-only`, stop; do not retry.
|
|
318
|
+
- **Turn-end:** re-prompt on exit 2. On any other exit, do nothing.
|
|
319
|
+
- **Seatbelts:** relay exit 2 as a block.
|
|
320
|
+
- **Encode operational text** with the Rödd bridge (`lib/rodd-operational-input.*`) before delivery.
|
|
321
|
+
|
|
322
|
+
### Stage 3 — Register the hooks
|
|
323
|
+
|
|
324
|
+
Create the harness's config file (`.<harness>/...`) matching the real schema. See the deep-dive file for the exact JSON shape per harness. The absolute rule: **the hook must be self-locating** (use the harness's own project-dir env var or `pwd -P`) and must **no-op safely** when the runtime is absent.
|
|
325
|
+
|
|
326
|
+
### Stage 4 — Verify (all four parts)
|
|
327
|
+
|
|
328
|
+
Run the commands in §9 and confirm the four contract parts. Do not mark the adapter done on a happy-path session-open alone; a guard that never fires is indistinguishable from a guard that is not wired.
|
|
329
|
+
|
|
330
|
+
### Stage 5 — Mark verified + document
|
|
331
|
+
|
|
332
|
+
1. Add the harness name to `VERIFIED_HARNESSES` in `bin/einherjar-spawn.sh:53`.
|
|
333
|
+
2. Add a row to the matrix in §4 of this file and a deep-dive file next to it.
|
|
334
|
+
3. If you want it as the default for dispatched Eindri, set `config/eindri-harness` (one line: `<harness> [<model>] [<effort>]`).
|
|
335
|
+
4. Record the verified version and any marker quirks in this file's Gotchas and in `data/learnings.md`.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## 8. Adding a new harness to `VERIFIED_HARNESSES`
|
|
340
|
+
|
|
341
|
+
The verified set is the fail-closed gate. Edit exactly this line and nothing else:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# bin/einherjar-spawn.sh:53
|
|
345
|
+
VERIFIED_HARNESSES='opencode pi pi-signed'
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Notes:
|
|
349
|
+
|
|
350
|
+
- `pi-signed` is a Pi variant (`BROKK_PI_HARNESS=pi-signed` / `FM_PI_HARNESS`); it maps to `pi` in `einherjar-spawn.sh`'s inline fallback but is a distinct token for the launch command (`bin/einherjar-spawn.sh:419-430`).
|
|
351
|
+
- Adding a raw command is **not** a substitute: `--harness "mycmd --flag"` bypasses verification and warns.
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## 9. Verification
|
|
356
|
+
|
|
357
|
+
### Syntax and schema
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
cd "$BROKK_HOME"
|
|
361
|
+
for f in bin/*.sh; do bash -n "$f" || echo "SYNTAX FAIL: $f"; done
|
|
362
|
+
python3 -m json.tool config/eindri-dispatch.json >/dev/null && echo "dispatch JSON ok"
|
|
363
|
+
python3 -m json.tool .claude/settings.json >/dev/null && echo "claude JSON ok"
|
|
364
|
+
python3 -m json.tool .codex/hooks.json >/dev/null && echo "codex JSON ok"
|
|
365
|
+
python3 -m json.tool .cursor/hooks.json >/dev/null && echo "cursor JSON ok"
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Session-open injects, Go digest
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
# Run as the harness would; it must print the Sága digest and exit 0.
|
|
372
|
+
bin/saga-sessionstart-run.sh --source startup | head -n 20
|
|
373
|
+
echo "exit=$?"
|
|
374
|
+
|
|
375
|
+
# Re-emit path after a completed startup:
|
|
376
|
+
test -f state/.session-start-complete && bin/saga-sessionstart-run.sh --source compact | head -n 3
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Watch arm arms, heartbeat, and exits on a wake
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
# In one shell (must own the lock):
|
|
383
|
+
bin/syn-watch-arm.sh --restart # prints "watcher: started pid=... recovery-generation=..."
|
|
384
|
+
test -f state/.supervision-armed && echo "armed marker written"
|
|
385
|
+
test -s state/.watch.heartbeat && echo "heartbeat written"
|
|
386
|
+
# In another shell, drop a wake and watch the arm exit with "signal: wake queue":
|
|
387
|
+
: > state/.wake-queue
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Turn-end guard
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
# Inert before first arm:
|
|
394
|
+
rm -f state/.supervision-armed
|
|
395
|
+
echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "expected 0, got $?"
|
|
396
|
+
# Armed but stale heartbeat → exit 2:
|
|
397
|
+
touch state/.supervision-armed
|
|
398
|
+
rm -f state/.watch.heartbeat
|
|
399
|
+
echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "expected 2, got $?"
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Seatbelts
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh --restart &'; echo "expected 2, got $?"
|
|
406
|
+
bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh --restart'; echo "expected 0, got $?"
|
|
407
|
+
bin/syn-cd-pretool-check.sh --command 'cd ../../etc'; echo "expected 2, got $?"
|
|
408
|
+
bin/syn-cd-pretool-check.sh --command 'ls -la'; echo "expected 0, got $?"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Session lock ownership
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
bin/saga-session-start.sh | sed -n '1,12p' # LOCK section: held vs READ-ONLY
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## 10. Gotchas
|
|
420
|
+
|
|
421
|
+
- **The digest helper must never hold the lock.** Bind `BROKK_SESSION_PID` to the live harness process or a second session will read the lock as stale and mutate shared state.
|
|
422
|
+
- **`saga-session-start.sh` acquires the lock but never releases it.** Release is the harness's business (process exit). A refused lock means **read-only**: no spawn, steer, merge, drain, or repair.
|
|
423
|
+
- **Don't call `bin/saga-session-start.sh` directly from an adapter.** Use `bin/saga-sessionstart-run.sh`; only the wrapper knows the source-routing rules (`startup` runs, `clear`/`compact` re-emits, `resume`/`reload`/`fork` nudges).
|
|
424
|
+
- **The turn-end guard is inert until `.supervision-armed` exists.** A guard test that never arms proves nothing. Arm first, then force a stale heartbeat.
|
|
425
|
+
- **`session.idle` fires often.** On OpenCode, the watch-arm plugin acts first and publishes `globalThis.__brokkOpenCodeWatchArm`; the guard plugin consults it and only calls `bin/syn-turnend-guard.sh` when the coordinator could not arm. Calling the guard first produces a false "turn would end blind" prompt during normal re-arms.
|
|
426
|
+
- **Never background the arm from the model's bash tool.** `syn-arm-pretool-check.sh` denies it; the adapter owns continuity. The arm is a plugin/extension child, not a tool call.
|
|
427
|
+
- **Exit-code semantics differ by host.** Claude's `SessionStart` exit 2 blocks initialization, so the run wrapper always exits 0 on the transport path; Pi's prerequisite uses exit 3 internally so preflight can distinguish a stand-down from a silent failure.
|
|
428
|
+
- **`hamr-harness.sh` has no `crew` subcommand — its subcommand is `eindri`.** `bin/einherjar-spawn.sh:170` calls `hamr-harness.sh crew`, which falls through to `detect_own` (`bin/hamr-harness.sh:231-236`); see §11. Until that call is fixed, `config/eindri-harness` is only honoured by the inline fallback, not the Hamr path.
|
|
429
|
+
- **Plugin auto-loading is path-based, not declared.** OpenCode loads `.agents/harness/opencode/plugins/*.js` automatically; there is no `plugin` array in `opencode.json`. The `package.json` only declares `"type": "module"`.
|
|
430
|
+
- **Grok is not wired in Ymir.** Upstream Brokk ships `.grok/hooks/*.json`; Ymir has no `.grok/`. Treat Grok as unverified (see §11).
|
|
431
|
+
- **Windows timing.** OpenCode and Pi raise the arm-ready budget to 35s on `win32` so a slow Git Bash cold start is not SIGTERMed mid-confirmation (`.agents/harness/opencode/plugins/syn-watch-arm.js:17-19`, `.pi/extensions/gna-pi-watch.ts:91-94`).
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## 11. Known code-vs-doc disagreements (truth is the code)
|
|
436
|
+
|
|
437
|
+
| Plan 29 says | Code says (truth) |
|
|
438
|
+
|---|---|
|
|
439
|
+
| `.agents/harness/opencode/plugins/syn-sessionstart.js` | actual file is `.agents/harness/opencode/plugins/saga-sessionstart.js` |
|
|
440
|
+
| `.agents/harness/opencode/plugins/gna-watch-arm.js` (plan §1) | actual file is `.agents/harness/opencode/plugins/syn-watch-arm.js` (OpenCode's watcher is **Sýn**, not Gná; Gná exists only on Pi) |
|
|
441
|
+
| Plan §13 "still to build: `bin/hamr-harness.sh`; the `.opencode`/Claude/Codex/Cursor adapters; `bin/einherjar-spawn.sh`; …" | all of these are **now landed**; plan §13 is stale |
|
|
442
|
+
| Digest §6 lists 9 stages including **NETWORK CHECKS** and **FLEET DIGEST from `data/backlog.md`** | `bin/saga-session-start.sh` currently prints **8** sections (LOCK, BOOTSTRAP, WAKE QUEUE, SUPERVISION, FLEET DIGEST, CONTEXT DIGEST, CRON START, NEXT STEP); there is **no NETWORK CHECKS section**, and the fleet digest counts `state/*.meta` + `docs/masterplan.md` orders, not `data/backlog.md` |
|
|
443
|
+
| Plan §7 "Cursor … run interactive only (no headless turn-end)" | `.cursor/hooks.json` **does** implement `sessionStart` (`additional_context`) and `stop` (`followup_message`) |
|
|
444
|
+
| Plan §7 "Codex … bounded foreground checkpoint … nudge-tier" | `.codex/hooks.json` implements run-tier `SessionStart` + `PreToolUse` + `Stop` |
|
|
445
|
+
| Plan §7 "Grok — project hooks (`grok --trust`)" | no `.grok/` exists in Ymir; Grok is unimplemented |
|
|
446
|
+
| Plan §7 "Claude Code … SessionStart + Stop hooks" | correct, but Ymir's `.claude/settings.json` has **no `PreToolUse`** seatbelt entries (upstream Brokk does) |
|
|
447
|
+
|
|
448
|
+
The authoritative interface is always the code listed in [`../runtime-components.md`](../runtime-components.md); report drift there.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## 12. Provenance
|
|
453
|
+
|
|
454
|
+
The adapter pattern is ported from the validated upstream **Brokk** agent-distro harness adapters (`bin/fm-harness.sh`, `bin/fm-sessionstart-run.sh`, `.agents/harness/opencode/plugins/fm-primary-*.js`, `.pi/extensions/fm-primary-*.ts`, `.claude/settings.json`, `.codex/hooks.json`, `.cursor/hooks.json`, `.grok/hooks/*.json`). Ymir adopts the *mechanism* and renames every component per plan 29 §12 (Sága, Sýn, Gná, Vörðr, Rödd, Gleipnir, Hamr, Einherjar, Erindi, Vör, Nornir). The upstream names (`fm-*`, "Allfather") are provenance only and must never name a Ymir component.
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 13. The Well — memory for every harness (engram)
|
|
459
|
+
|
|
460
|
+
The well is **Mimirsbrunn**, backed by the validated OSS engine **engram**. It is
|
|
461
|
+
one repo-local store, `.agents/memory/kaia.engram`, reached two ways:
|
|
462
|
+
|
|
463
|
+
**HTTP bridge (`:4602`)** — `bin/mimir-bridge.py`, raised by
|
|
464
|
+
`bin/mimir-bridge.sh` (and by `scripts/start.sh` + `bin/saga-session-start.sh`).
|
|
465
|
+
It wraps the engram library so the gate API, `bin/mimir.sh`, and
|
|
466
|
+
`bin/mimir-ingest.sh` can drink over the small HTTP contract:
|
|
467
|
+
|
|
468
|
+
```
|
|
469
|
+
GET /health -> {status, store, episodes, agents}
|
|
470
|
+
GET /recall?q&k&mode -> {results:[{score, distance, episode}]}
|
|
471
|
+
GET /recent?limit -> {episodes:[...]}
|
|
472
|
+
GET /timeline?entity -> {facts:[...]}
|
|
473
|
+
GET /inspect -> {episodes, agents, store}
|
|
474
|
+
POST /observe {content,...} -> {id}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**MCP server (stdio)** — `engram-mcp --db <store> --agent-id <harness>`, so any
|
|
478
|
+
MCP-capable harness gets `remember`, `recall`, `why`, `forget`, `stats` with no
|
|
479
|
+
integration code. Registered per harness (each writes under its own agent id):
|
|
480
|
+
|
|
481
|
+
| Harness | Config | Agent id |
|
|
482
|
+
|---|---|---|
|
|
483
|
+
| OpenCode | `opencode.json` → `mcp.engram` (+ `~/.config/opencode/opencode.json`) | `opencode` |
|
|
484
|
+
| Pi | `.pi/mcp.json` (pass `pi --mcp-config .pi/mcp.json`) | `pi` |
|
|
485
|
+
| Claude Code | `~/.claude.json` → `mcpServers.engram` | `claude` |
|
|
486
|
+
| Cursor | `~/.cursor/mcp.json` → `mcpServers.engram` | `cursor` |
|
|
487
|
+
| Codex | `~/.codex/config.toml` → `[mcp_servers.engram]` | `codex` |
|
|
488
|
+
|
|
489
|
+
The engine needs the `mcp<2` SDK for `engram-mcp` (v2 renamed `FastMCP` to
|
|
490
|
+
`MCPServer`, which breaks engram 1.x/2.x):
|
|
491
|
+
`python3 -m pip install --user --break-system-packages 'mcp<2'`.
|
|
492
|
+
|
|
493
|
+
Rule: **drink before you act, water it after** — recall on the way in, and
|
|
494
|
+
`POST /observe` (or the `remember` MCP tool) after a lesson lands.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## 14. Agent locations — `.agents/agents` is the source of truth
|
|
499
|
+
|
|
500
|
+
Agent profiles live **only** in `.agents/agents/*.md` (the canonical, with the
|
|
501
|
+
harness config like `mode`/`model`/`permission` in their frontmatter). The
|
|
502
|
+
harness directories **bind** them by symlink — they are never hand-written
|
|
503
|
+
duplicates:
|
|
504
|
+
|
|
505
|
+
- OpenCode: `.opencode/agents/<name>.md` → `../../.agents/agents/<profile>.md`
|
|
506
|
+
- Pi: `.pi/agents/<profile>.md` → the same canonical files
|
|
507
|
+
|
|
508
|
+
`bin/valknut-load.sh` creates the symlinks (`--opencode`, `--pi`, `--global`,
|
|
509
|
+
`--all`). **Every harness gets EVERY agent** — claude, codex, cursor and opencode
|
|
510
|
+
are bound by the same loader pass as pi, so no harness is left holding a
|
|
511
|
+
hand-made subset. Naming differs by harness and must be respected:
|
|
512
|
+
|
|
513
|
+
```
|
|
514
|
+
agent_binding[5]{harness,dir,name_rule}:
|
|
515
|
+
"opencode",".opencode/agents/","the frontmatter `name:` — bragi.md -> bragi-marketer.md"
|
|
516
|
+
"pi",".pi/agents/","the profile file name — bragi-marketer.md"
|
|
517
|
+
"claude",".claude/agents/","the profile file name"
|
|
518
|
+
"codex",".codex/agents/","the profile file name"
|
|
519
|
+
"cursor",".cursor/agents/","the profile file name"
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
To change an agent, edit `.agents/agents/*.md` and re-run the loader; never edit
|
|
523
|
+
a harness directory (they are all links).
|
|
524
|
+
|
|
525
|
+
### Skill location — the same law, one tree
|
|
526
|
+
|
|
527
|
+
Skills have **one** tree too: `.agents/skills/`. Every harness reaches it, each
|
|
528
|
+
by the mechanism that harness actually reads — and a harness that silently
|
|
529
|
+
loads nothing is invisible from the code, so `compliance-check.sh`'s `harnesses`
|
|
530
|
+
gate asserts all four:
|
|
531
|
+
|
|
532
|
+
| Harness | How it reaches `.agents/skills` |
|
|
533
|
+
|---|---|
|
|
534
|
+
| **opencode** | `skills.paths: [".agents/skills"]` in `opencode.json` (the loader merges it in and re-asserts it on every run) |
|
|
535
|
+
| **pi** | **native discovery** — it walks up from the cwd to `.agents/skills` (and `~/.agents/skills`). No link, no config: a second root under `.pi/` would invite double-loading, exactly as the extensions rule warns |
|
|
536
|
+
| **claude · codex · cursor** | `<harness>/skills -> ../.agents/skills`, created by `bin/valknut-load.sh` (their project scope is their own directory) |
|
|
537
|
+
|
|
538
|
+
**Do not** copy a `SKILL.md` into a harness directory: a copy is drift, and a
|
|
539
|
+
nested `SKILL.md` carrying frontmatter is loaded as a *second, phantom* skill by
|
|
540
|
+
every recursive scanner (the `harnesses` gate refuses it).
|
|
541
|
+
|
|
542
|
+
### opencode.json has two writers — and neither may overwrite
|
|
543
|
+
|
|
544
|
+
`opencode.json` is untracked (it carries absolute paths) and two things write it:
|
|
545
|
+
|
|
546
|
+
```
|
|
547
|
+
writers[2]{writer,owns}:
|
|
548
|
+
"bin/valknut-load.sh","STRUCTURE — the base keys, the agent blocks, the skills path; rendered from opencode.json.example"
|
|
549
|
+
"bin/agents-config.sh apply","the ROSTER — providers and per-agent models, from config/agents.yaml"
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
**Both merge; neither overwrites.** The loader's `config_out` adds missing keys (
|
|
553
|
+
deep, `setdefault`-style), ensures `skills.paths`, and re-asserts nothing else;
|
|
554
|
+
`agents-config` does the same for providers and models — and it writes **only
|
|
555
|
+
OpenCode agents** into `opencode.json`. A `pi` (or `hermes`) agent's model is that
|
|
556
|
+
harness's own id (e.g. `llamacpp/qwen3.5-9b`), which OpenCode cannot resolve, so
|
|
557
|
+
those agents are deliberately left out rather than handed to OpenCode broken. This is not tidiness —
|
|
558
|
+
the loader used to re-render from the example with `sed` + `mv`, and because the
|
|
559
|
+
example carried only `llama.cpp`, **every loader run deleted the Apodex
|
|
560
|
+
provider**, which lived only in the live file. A blind render of a file two
|
|
561
|
+
writers share is a silent data loss; the merge is the fix.
|
|
562
|
+
|
|
563
|
+
## 15. The Eindri roster (bound agents)
|
|
564
|
+
|
|
565
|
+
Every skill names an owner agent in `.agents/skills/README.md`; the fleet below
|
|
566
|
+
is the full set of canonical profiles, all bound into all five harnesses.
|
|
567
|
+
|
|
568
|
+
Canonical profiles in `.agents/agents/*.md`, bound as symlinks:
|
|
569
|
+
|
|
570
|
+
```
|
|
571
|
+
einherjar[20]{figure,craft,domain,engine}:
|
|
572
|
+
"Brokk","primary — the bellows","ymirlabs","—"
|
|
573
|
+
"Sindri","developer / smith","brokkforge","Chrome DevTools"
|
|
574
|
+
"Bragi","marketer / skald","utgard","Firecrawl + browser-use (+ Scrapy)"
|
|
575
|
+
"Hnoss","designer / shaper","utgard","OpenDesign"
|
|
576
|
+
"Huginn","researcher / sage","muninn","—"
|
|
577
|
+
"Mímir","planner / the wise","ymirlabs","—"
|
|
578
|
+
"Forseti","reviewer / the just","runestone","—"
|
|
579
|
+
"Snotra","documenter / the wise-woman","runestone","—"
|
|
580
|
+
"Kvasir","scout / the knowing","ymirlabs","—"
|
|
581
|
+
"Galdr","builder — CLI ergonomics","ymirlabs","—"
|
|
582
|
+
"Týr","judge — the 10 principles + the gates","runestone","—"
|
|
583
|
+
"Sága","seeress — bearings + recap","ymirlabs","—"
|
|
584
|
+
"Muninn","rememberer — memory curation","muninn","—"
|
|
585
|
+
"Urðr","fate — the hold lifecycle","ymirlabs","—"
|
|
586
|
+
"Frigg","knowing — consent gate","ymirlabs","—"
|
|
587
|
+
"Vör","aware — diagnostics","ymirlabs","—"
|
|
588
|
+
"Sýn","seeing — stuck-worker recovery","ymirlabs","—"
|
|
589
|
+
"Jörð","grounded — project registry","ymirlabs","—"
|
|
590
|
+
"Gróa","renewer — self-update","ymirlabs","—"
|
|
591
|
+
"Völundr","master smith — Smíðja's orchestrator","brokkforge","—"
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Bind with `bin/valknut-load.sh --all` (OpenCode: `.opencode/agents/<name>.md`; Pi:
|
|
595
|
+
`.pi/agents/<profile>.md`) — never edit the harness dirs.
|
|
596
|
+
|
|
597
|
+
## Pi has no agent loader (2026-09-17)
|
|
598
|
+
|
|
599
|
+
**Pi core does not load `.pi/agents/`.** Agent loading in Pi is a *package*
|
|
600
|
+
(`pi-agents`, `pi-agent-mode`, `pi-simple-agents`), not a core feature, and Ymir
|
|
601
|
+
installs none of them. So `.pi/agents/` held twenty correct profile links that
|
|
602
|
+
**nothing in Pi ever read** — the same failure as OpenCode's singular
|
|
603
|
+
`.opencode/agent/`, arrived at from the other side.
|
|
604
|
+
|
|
605
|
+
The fix lives in the repo, not in a root-pi package: **`.pi/shared/extensions/ymir-subagents.ts`**
|
|
606
|
+
discovers the canonical `.agents/agents/*.md` tree itself and registers a
|
|
607
|
+
`subagent` tool. A call runs the chosen figure as a nested model call in the
|
|
608
|
+
current session — the figure's markdown body is its system prompt, its
|
|
609
|
+
frontmatter `model:` picks the model where the machine serves it.
|
|
610
|
+
|
|
611
|
+
```
|
|
612
|
+
subagent({ agent: "kvasir", task: "find every AGENTS.md" }) # dispatch
|
|
613
|
+
subagent({}) # list the roster
|
|
614
|
+
/subagents # list the roster
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
Rules this extension follows, learned the hard way:
|
|
618
|
+
|
|
619
|
+
- **No imports.** `@earendil-works/pi-coding-agent` is **not installed as a
|
|
620
|
+
package**, so an extension that imports its types cannot load at all. Every
|
|
621
|
+
working extension in this tree takes `pi` as `any` and declares tool
|
|
622
|
+
`parameters` as a plain JSON schema object. `typebox` *is* installed, but the
|
|
623
|
+
plain object needs nothing.
|
|
624
|
+
- **One home.** It lives in `.pi/shared/extensions/` (deployed), never in
|
|
625
|
+
`.pi/extensions/` — a copy in both makes pi refuse the duplicate tool.
|
|
626
|
+
- **The canonical tree is the source.** It reads `.agents/agents/`; it never
|
|
627
|
+
copies from it (Rule 02).
|
|
628
|
+
|
|
629
|
+
### A rename that left a reader behind (same day)
|
|
630
|
+
|
|
631
|
+
`skuld-branch-supervision.ts` imported `calmTranscriptClassIsVisible` and
|
|
632
|
+
`CalmPresentationState` from `./lib/ro-visibility.ts`, but that module exports
|
|
633
|
+
`roTranscriptClassIsVisible` and `RoPresentationState` — the names were renamed
|
|
634
|
+
and the importer was not. Pi refuses the **whole extension** at load with
|
|
635
|
+
`does not provide an export named …`, so Skuld's supervision branch was dead in
|
|
636
|
+
every session while nothing reported it. Fixed in the same change.
|
|
637
|
+
|
|
638
|
+
**Check every extension actually loads**, not just that its file exists:
|
|
639
|
+
|
|
640
|
+
```bash
|
|
641
|
+
cd ~/.pi/agent/extensions
|
|
642
|
+
for f in *.ts; do
|
|
643
|
+
node --input-type=module --eval "import('file://$PWD/$f').then(()=>console.log('$f LOADS')).catch(e=>console.log('$f FAIL: '+e.message.split('\n')[0]))"
|
|
644
|
+
done
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
Run it after every deploy. A module that cannot resolve is invisible from the
|
|
648
|
+
file listing, and pi reports it only as a startup line that scrolls away.
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
Pi loads **both** the project `.pi/extensions/` and the global
|
|
653
|
+
`~/.pi/agent/extensions/` directories; because it does not de-duplicate by
|
|
654
|
+
extension or tool name, an extension present in both makes `pi` exit with
|
|
655
|
+
`Tool "<name>" conflicts with …` and **no agent can be seated** (herdr reports
|
|
656
|
+
"the pane must sit at an interactive shell prompt", a confusing symptom).
|
|
657
|
+
|
|
658
|
+
Rule: **one home per extension.**
|
|
659
|
+
|
|
660
|
+
- Shared extensions (`todo.ts`, `herdr-agent-state.ts`, `open-editor.ts`) live
|
|
661
|
+
**only** in `~/.pi/agent/extensions/` — used by every project, Ymir and
|
|
662
|
+
Omarchy alike.
|
|
663
|
+
- The repo `.pi/extensions/` holds **only Ymir-unique** extensions
|
|
664
|
+
(`gna-pi-watch.ts`, `ro.ts`, `skuld-branch-supervision.ts`,
|
|
665
|
+
`syn-turnend-guard.ts`, `lib/`).
|
|
666
|
+
- Never copy a shared extension back into the repo; that re-arms the collision.
|
|
667
|
+
|
|
668
|
+
**Shipping the shared extensions (added 2026-09-12).** A rule that keeps the
|
|
669
|
+
extensions outside the repo would also keep them from every new operator, so the
|
|
670
|
+
repo carries their **source** at `.pi/shared/extensions/` — a path pi does not
|
|
671
|
+
load, therefore collision-free — and the loader deploys it into the single home:
|
|
672
|
+
|
|
673
|
+
```bash
|
|
674
|
+
bin/valknut-load.sh --pi # deploys .pi/shared/extensions/*.ts -> ~/.pi/agent/extensions/
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
The deploy copies (never links: a broken link would silently disable a tool),
|
|
678
|
+
skips files that are already identical, and reports what it placed. It runs
|
|
679
|
+
whenever the Pi surface is bound, with or without `--global`. Adding a shared
|
|
680
|
+
extension is therefore two steps: put the source in `.pi/shared/extensions/`, and
|
|
681
|
+
let the loader place it — **never** place it in `.pi/extensions/`.
|
|
682
|
+
|
|
683
|
+
## OpenCode agent `tools` key (2026-09-12)
|
|
684
|
+
|
|
685
|
+
OpenCode requires the frontmatter `tools:` key to be an **object** of its own
|
|
686
|
+
built-in tools. Our profiles list Ymir capabilities (`vector_db`,
|
|
687
|
+
`hermes_runner`, `herder`, `yggdrasil`, `supabase`, `opendesign`,
|
|
688
|
+
`chrome_devtools`), which are not OpenCode tools and which OpenCode rejects as
|
|
689
|
+
`Expected object | undefined, got [...] tools`. Those lists are therefore carried
|
|
690
|
+
under **`ymir_tools:`**; permission is expressed by the `permission:` block.
|
|
691
|
+
|
|
692
|
+
## Canonical layout — the ONE remap (authoritative; do not redo)
|
|
693
|
+
|
|
694
|
+
**Source of truth is `.agents/`. Harness directories are symlinks, never copies.**
|
|
695
|
+
|
|
696
|
+
```
|
|
697
|
+
canonical[3]{kind,canonical,load_path}:
|
|
698
|
+
"agent profiles",".agents/agents/<profile>.md",".opencode/agents/<name>.md · .pi/agents/<name>.md (symlinks)"
|
|
699
|
+
"OpenCode plugins",".agents/harness/opencode/plugins/",".opencode/plugins (symlink)"
|
|
700
|
+
"skills",".agents/skills/","loaded via opencode.json skills.paths"
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
Rules:
|
|
704
|
+
- **Edit only `.agents/`.** Never edit a file under `.opencode/` or `.pi/` — those are
|
|
705
|
+
symlinks to `.agents/` (e.g. `.opencode/agents/bragi.md` links to
|
|
706
|
+
`.agents/agents/bragi-marketer.md`).
|
|
707
|
+
- After any change: `bin/valknut-load.sh --all` to rebind.
|
|
708
|
+
- **OpenCode requires REAL `.opencode/{node_modules,package.json,.gitignore}`** — the
|
|
709
|
+
dependency store. Symlinking them hit ELOOP + untracked files and was reverted.
|
|
710
|
+
- So `.opencode` holds: symlinked `agent/` + `plugins`, and the real dep store. It
|
|
711
|
+
cannot be deleted; it is already minimized. No agent/profile content lives there.
|
|
712
|
+
|
|
713
|
+
## Asking the Allfather — `ask_user_question` (2026-09-12)
|
|
714
|
+
|
|
715
|
+
The system can ask the Allfather instead of guessing. Adopted (open-source-first)
|
|
716
|
+
from `@juicesharp/rpiv-ask-user-question` (MIT), pinned **project-locally** in
|
|
717
|
+
`.pi/settings.json` so every machine/user that has the repo gets it.
|
|
718
|
+
|
|
719
|
+
- Gives Pi one tool, `ask_user_question`: a terminal dialog of up to four
|
|
720
|
+
questions with authored options (+ descriptions/previews), a free-text row,
|
|
721
|
+
per-question and global notes, and a Submit review tab.
|
|
722
|
+
- Non-interactive runs simply don't see the tool (never a failing call).
|
|
723
|
+
- Config (read-only): `~/.config/rpiv-ask-user-question/config.json`.
|
|
724
|
+
- Use it at real decision points — where a wrong assumption costs a rework.
|
|
725
|
+
|
|
726
|
+
**Two extension paths, and they are not interchangeable** (2026-09-12):
|
|
727
|
+
|
|
728
|
+
| Path | Loaded by | Holds |
|
|
729
|
+
|---|---|---|
|
|
730
|
+
| `.pi/extensions/` | pi, as **project-local** extensions | the governance set: `syn-turnend-guard.ts`, `gna-pi-watch.ts`, `ro.ts`, `skuld-branch-supervision.ts` |
|
|
731
|
+
| `.pi/shared/extensions/` | **deployed** by `bin/valknut-load.sh --pi` into `${HOME}/.pi/agent/extensions/` | the user-facing trio: `open-editor.ts`, `herdr-agent-state.ts`, `todo.ts` |
|
|
732
|
+
|
|
733
|
+
The same extension in **both** paths makes pi exit with a tool-name conflict and
|
|
734
|
+
no agent can be seated — which is why the shared trio has exactly one home and is
|
|
735
|
+
deployed, never duplicated. Editing a path from the table above without checking
|
|
736
|
+
which of the two it is will edit a file that is not there.
|