session-orchestrator 5.2.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/architecture/SKILL.md +3 -1
- package/.agents/skills/autopilot/SKILL.md +5 -1
- package/.agents/skills/autopilot/agents/openai.yaml +5 -0
- package/.agents/skills/bootstrap/SKILL.md +5 -1
- package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
- package/.agents/skills/brainstorm/SKILL.md +5 -1
- package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +4 -2
- package/.agents/skills/close/SKILL.md +5 -1
- package/.agents/skills/close/agents/openai.yaml +5 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
- package/.agents/skills/debug/SKILL.md +5 -1
- package/.agents/skills/debug/agents/openai.yaml +5 -0
- package/.agents/skills/discovery/SKILL.md +5 -1
- package/.agents/skills/discovery/agents/openai.yaml +5 -0
- package/.agents/skills/dispatcher/SKILL.md +5 -1
- package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ecosystem-health/SKILL.md +3 -1
- package/.agents/skills/eli5/SKILL.md +5 -1
- package/.agents/skills/eli5/agents/openai.yaml +5 -0
- package/.agents/skills/eval/SKILL.md +6 -2
- package/.agents/skills/eval/agents/openai.yaml +5 -0
- package/.agents/skills/evolve/SKILL.md +6 -2
- package/.agents/skills/evolve/agents/openai.yaml +5 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
- package/.agents/skills/gitlab-ops/SKILL.md +3 -1
- package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
- package/.agents/skills/go/SKILL.md +5 -1
- package/.agents/skills/go/agents/openai.yaml +5 -0
- package/.agents/skills/grill/SKILL.md +5 -1
- package/.agents/skills/grill/agents/openai.yaml +5 -0
- package/.agents/skills/harness-audit/SKILL.md +5 -1
- package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
- package/.agents/skills/hook-development/SKILL.md +3 -1
- package/.agents/skills/mcp-builder/SKILL.md +3 -1
- package/.agents/skills/memory-cleanup/SKILL.md +5 -1
- package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.agents/skills/mode-selector/SKILL.md +3 -1
- package/.agents/skills/navigator/SKILL.md +22 -0
- package/.agents/skills/navigator/agents/openai.yaml +5 -0
- package/.agents/skills/npm-publish/SKILL.md +4 -2
- package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
- package/.agents/skills/persona-panel/SKILL.md +5 -1
- package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
- package/.agents/skills/plan/SKILL.md +5 -1
- package/.agents/skills/plan/agents/openai.yaml +5 -0
- package/.agents/skills/playwright-driver/SKILL.md +3 -1
- package/.agents/skills/portfolio/SKILL.md +5 -1
- package/.agents/skills/portfolio/agents/openai.yaml +5 -0
- package/.agents/skills/quality-gates/SKILL.md +3 -1
- package/.agents/skills/reconcile/SKILL.md +5 -1
- package/.agents/skills/reconcile/agents/openai.yaml +5 -0
- package/.agents/skills/release/SKILL.md +5 -1
- package/.agents/skills/release/agents/openai.yaml +5 -0
- package/.agents/skills/remote-offload/SKILL.md +3 -1
- package/.agents/skills/repo-audit/SKILL.md +5 -1
- package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
- package/.agents/skills/session/SKILL.md +21 -0
- package/.agents/skills/session/agents/openai.yaml +5 -0
- package/.agents/skills/session-end/SKILL.md +3 -1
- package/.agents/skills/session-plan/SKILL.md +3 -1
- package/.agents/skills/session-start/SKILL.md +3 -1
- package/.agents/skills/spinout/SKILL.md +5 -1
- package/.agents/skills/spinout/agents/openai.yaml +5 -0
- package/.agents/skills/sunset-review/SKILL.md +5 -1
- package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
- package/.agents/skills/templates-ack/SKILL.md +21 -0
- package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
- package/.agents/skills/test/SKILL.md +5 -1
- package/.agents/skills/test/agents/openai.yaml +5 -0
- package/.agents/skills/test-audit/SKILL.md +21 -0
- package/.agents/skills/test-audit/agents/openai.yaml +5 -0
- package/.agents/skills/test-runner/SKILL.md +3 -1
- package/.agents/skills/tmux-layout/SKILL.md +3 -1
- package/.agents/skills/using-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ux-grill/SKILL.md +5 -1
- package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
- package/.agents/skills/vault-mirror/SKILL.md +3 -1
- package/.agents/skills/vault-sync/SKILL.md +3 -1
- package/.agents/skills/wave-executor/SKILL.md +3 -1
- package/.agents/skills/write-executable-plan/SKILL.md +3 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +4 -4
- package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -3
- package/.codex-plugin/skills/eval/SKILL.md +1 -1
- package/.codex-plugin/skills/evolve/SKILL.md +1 -1
- package/.codex-plugin/skills/navigator/SKILL.md +22 -0
- package/.codex-plugin/skills/{convergence-monitoring → navigator}/agents/openai.yaml +2 -2
- package/.codex-plugin/skills/npm-publish/SKILL.md +1 -3
- package/.codex-plugin/skills/session/SKILL.md +1 -1
- package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
- package/.codex-plugin/skills/{npm-publish → test-audit}/agents/openai.yaml +1 -1
- package/.cursor/commands/eval.md +1 -1
- package/.cursor/commands/navigator.md +15 -0
- package/.cursor/commands/session.md +1 -1
- package/.cursor/commands/test-audit.md +14 -0
- package/.cursor/rules/000-session-orchestrator.mdc +0 -2
- package/.cursor/rules/050-plan.mdc +1 -1
- package/.cursor/rules/060-evolve.mdc +27 -12
- package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/navigator/SKILL.md +13 -0
- package/.cursor/skills/npm-publish/SKILL.md +1 -0
- package/.cursor/skills/test-audit/SKILL.md +12 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.orchestrator/policy/blocked-commands.json +12 -3
- package/AGENTS.md +9 -30
- package/CHANGELOG.md +206 -0
- package/README.md +13 -9
- package/SECURITY.md +12 -0
- package/agents/dialectic-deriver.md +13 -10
- package/agents/eval-judge.md +67 -45
- package/agents/skill-applied-judge.md +34 -19
- package/commands/session.md +7 -3
- package/docs/agent-authoring.md +2 -2
- package/docs/baseline.md +22 -7
- package/docs/ci-setup.md +57 -4
- package/docs/codex-setup.md +14 -2
- package/docs/components.md +12 -10
- package/docs/events-schema.md +65 -15
- package/docs/persona-panel.md +5 -4
- package/docs/rule-authoring.md +84 -17
- package/docs/scope-collision-guard.md +26 -4
- package/docs/session-config-reference.md +154 -12
- package/docs/session-config-template.md +41 -3
- package/docs/telemetry.md +2 -0
- package/hooks/_lib/hook-import-set.json +87 -6
- package/hooks/_lib/subagent-transcript.mjs +582 -31
- package/hooks/config-protection.mjs +11 -3
- package/hooks/cwd-change-restore.mjs +11 -3
- package/hooks/enforce-commands.mjs +70 -23
- package/hooks/enforce-scope.mjs +143 -33
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +5 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/loop-guard.mjs +11 -3
- package/hooks/on-session-end.mjs +58 -23
- package/hooks/on-session-start.mjs +101 -11
- package/hooks/on-stop.mjs +170 -22
- package/hooks/operator-steer.mjs +11 -3
- package/hooks/post-bash-issue-budget-refund.mjs +18 -8
- package/hooks/post-bash-write-verify.mjs +3 -2
- package/hooks/post-edit-import-probe.mjs +17 -9
- package/hooks/post-edit-validate.mjs +13 -5
- package/hooks/post-subagent-discovery-validator.mjs +98 -13
- package/hooks/post-tool-batch-wave-signal.mjs +202 -38
- package/hooks/post-tool-failure-corrective-context.mjs +11 -5
- package/hooks/post-tooluse-frontend-slop.mjs +10 -4
- package/hooks/pre-auq-clarity.mjs +15 -2
- package/hooks/pre-bash-destructive-guard.mjs +80 -9
- package/hooks/pre-bash-issue-budget.mjs +16 -11
- package/hooks/pre-bash-memory-propose-audit.mjs +137 -56
- package/hooks/pre-bash-sessions-ledger-guard.mjs +419 -22
- package/hooks/pre-bash-staging-fence.mjs +335 -31
- package/hooks/pre-bash-templates-first.mjs +19 -14
- package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
- package/hooks/pre-task-scope-disjoint.mjs +792 -74
- package/hooks/subagent-telemetry.mjs +111 -38
- package/hooks/wave-scope-commit-guard.mjs +197 -100
- package/monitors/monitors.json +1 -1
- package/output-styles/wave-summary.md +1 -1
- package/package.json +3 -3
- package/pi/prompts/eval.md +1 -1
- package/pi/prompts/navigator.md +12 -0
- package/pi/prompts/session.md +1 -1
- package/pi/prompts/test-audit.md +12 -0
- package/rules/README.md +7 -2
- package/rules/_index.md +3 -3
- package/rules/always-on/bash-harness-pitfalls.md +7 -1
- package/rules/opt-in-domain/prompt-caching.md +6 -2
- package/rules/opt-in-stack/backend-data.md +10 -2
- package/rules/opt-in-stack/backend.md +10 -4
- package/rules/opt-in-stack/frontend.md +7 -2
- package/rules/opt-in-stack/security-web.md +10 -4
- package/rules/opt-in-stack/swift.md +6 -2
- package/scripts/apply-session-learnings.mjs +492 -0
- package/scripts/archive-closed-prds.mjs +2 -1
- package/scripts/autopilot.mjs +70 -53
- package/scripts/backfill-abandoned-sessions.mjs +118 -16
- package/scripts/baseline-archetypes.mjs +1 -1
- package/scripts/check-package-manager.mjs +62 -5
- package/scripts/check-sessions-integrity.mjs +300 -0
- package/scripts/cursor-install.mjs +1 -4
- package/scripts/dialectic-deriver.mjs +50 -13
- package/scripts/emit-session.mjs +371 -31
- package/scripts/eval-session.mjs +65 -3
- package/scripts/export-hw-learnings.mjs +22 -3
- package/scripts/fleet-checkin.mjs +147 -0
- package/scripts/generate-agents-skills.mjs +102 -29
- package/scripts/generate-cursor-adapter.mjs +61 -16
- package/scripts/lib/agent-frontmatter.mjs +3 -3
- package/scripts/lib/agent-status.mjs +2 -31
- package/scripts/lib/auq/clarity.mjs +10 -2
- package/scripts/lib/auq/parse.mjs +12 -31
- package/scripts/lib/auq/schema.mjs +56 -41
- package/scripts/lib/auto-dialectic.mjs +304 -15
- package/scripts/lib/auto-dream.mjs +7 -6
- package/scripts/lib/autopilot/flags.mjs +18 -2
- package/scripts/lib/autopilot/kill-switches.mjs +6 -3
- package/scripts/lib/autopilot/loop.mjs +19 -2
- package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
- package/scripts/lib/baseline-archetypes.mjs +41 -22
- package/scripts/lib/ci-status-banner.mjs +376 -16
- package/scripts/lib/command-blocker.mjs +275 -28
- package/scripts/lib/config/dialectic.mjs +12 -3
- package/scripts/lib/config/gate.mjs +74 -0
- package/scripts/lib/config/host-paths.mjs +79 -0
- package/scripts/lib/config/persona-gate-wave.mjs +3 -3
- package/scripts/lib/config/reaper.mjs +163 -0
- package/scripts/lib/config-schema.mjs +13 -0
- package/scripts/lib/config.mjs +85 -10
- package/scripts/lib/convergence-monitor.mjs +74 -11
- package/scripts/lib/ecosystem-health.mjs +11 -0
- package/scripts/lib/eval/engine.mjs +421 -53
- package/scripts/lib/eval/judge.mjs +463 -40
- package/scripts/lib/eval/schema.mjs +10 -1
- package/scripts/lib/events-rotation.mjs +221 -25
- package/scripts/lib/events-schema.mjs +114 -0
- package/scripts/lib/events.mjs +545 -7
- package/scripts/lib/fleet-protocol.mjs +270 -0
- package/scripts/lib/frontmatter-guard.mjs +21 -10
- package/scripts/lib/gates/gate-baseline.mjs +40 -5
- package/scripts/lib/gates/gate-full.mjs +35 -5
- package/scripts/lib/gates/gate-helpers.mjs +336 -23
- package/scripts/lib/gates/gate-incremental.mjs +49 -23
- package/scripts/lib/gates/gate-per-file.mjs +42 -8
- package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
- package/scripts/lib/instruction-budget-guard.mjs +208 -8
- package/scripts/lib/io.mjs +42 -8
- package/scripts/lib/issue-close-strip-labels.mjs +207 -49
- package/scripts/lib/js-mask.mjs +197 -0
- package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
- package/scripts/lib/learnings/expiry-sweep.mjs +34 -3
- package/scripts/lib/learnings/io.mjs +154 -26
- package/scripts/lib/learnings/schema.mjs +163 -15
- package/scripts/lib/learnings/sizing-subject.mjs +2 -2
- package/scripts/lib/maintenance-due-banner.mjs +53 -88
- package/scripts/lib/memory-proposals/schema.mjs +11 -5
- package/scripts/lib/named-baseline-resolver.mjs +53 -28
- package/scripts/lib/named-vault-resolver.mjs +104 -5
- package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
- package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
- package/scripts/lib/orphan-reaper/reaper-audit.mjs +291 -0
- package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
- package/scripts/lib/orphan-reaper/scan-throttle.mjs +92 -0
- package/scripts/lib/orphan-reaper/scan.mjs +506 -0
- package/scripts/lib/orphan-reaper.mjs +316 -0
- package/scripts/lib/owner-yaml.mjs +104 -6
- package/scripts/lib/peer-cards/merger.mjs +48 -10
- package/scripts/lib/peer-cards/reader.mjs +78 -2
- package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
- package/scripts/lib/process-group.mjs +950 -0
- package/scripts/lib/project-hygiene.mjs +21 -1
- package/scripts/lib/quality-gate.mjs +152 -33
- package/scripts/lib/reconcile/backlog.mjs +368 -0
- package/scripts/lib/reconcile/engine.mjs +55 -188
- package/scripts/lib/reconcile/rule-expiry-sweep.mjs +302 -60
- package/scripts/lib/reconcile/sanitize.mjs +69 -3
- package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
- package/scripts/lib/resource-probe/parsers.mjs +31 -0
- package/scripts/lib/resource-probe.mjs +1 -1
- package/scripts/lib/rule-loader.mjs +141 -74
- package/scripts/lib/rules-sync.mjs +27 -12
- package/scripts/lib/scope-baseline.mjs +3 -4
- package/scripts/lib/scope-echo.mjs +39 -2
- package/scripts/lib/scope-gate.mjs +605 -1
- package/scripts/lib/session-close-backfill.mjs +33 -6
- package/scripts/lib/session-id.mjs +9 -20
- package/scripts/lib/session-invocation.mjs +20 -0
- package/scripts/lib/session-record-repair.mjs +183 -26
- package/scripts/lib/session-registry.mjs +27 -2
- package/scripts/lib/session-schema/constants.mjs +56 -2
- package/scripts/lib/session-schema/normalizer.mjs +56 -4
- package/scripts/lib/session-schema/validator.mjs +28 -1
- package/scripts/lib/session-schema.mjs +8 -3
- package/scripts/lib/session-start-probes.mjs +95 -10
- package/scripts/lib/session-token-rollup.mjs +245 -52
- package/scripts/lib/sessions-canonical.mjs +118 -4
- package/scripts/lib/sessions-integrity-banner.mjs +7 -1
- package/scripts/lib/sessions-staleness-banner.mjs +193 -51
- package/scripts/lib/sh-quote.mjs +29 -0
- package/scripts/lib/skill-evidence-window.mjs +891 -0
- package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
- package/scripts/lib/skill-evolution/engine.mjs +18 -9
- package/scripts/lib/skill-judge.mjs +45 -3
- package/scripts/lib/subagents-schema.mjs +30 -3
- package/scripts/lib/tail-window.mjs +56 -0
- package/scripts/lib/telemetry/pricing.mjs +118 -71
- package/scripts/lib/telemetry/schema.mjs +30 -0
- package/scripts/lib/telemetry/sync.mjs +61 -6
- package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
- package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
- package/scripts/lib/tests-src-ratio.mjs +140 -23
- package/scripts/lib/tmux-layout/layouts.mjs +1 -11
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +72 -13
- package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
- package/scripts/lib/user-invocable-skills.mjs +23 -3
- package/scripts/lib/ux-grill/reconcile.mjs +48 -22
- package/scripts/lib/validate/check-agents-skills.mjs +26 -15
- package/scripts/lib/validate/check-agents.mjs +1 -1
- package/scripts/lib/validate/check-cursor-adapter.mjs +1 -0
- package/scripts/lib/validate/check-entry-guard.mjs +13 -50
- package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
- package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
- package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
- package/scripts/lib/validate/check-rules.mjs +7 -5
- package/scripts/lib/validate/check-skill-links.mjs +9 -1
- package/scripts/lib/validate/check-skill-script-paths.mjs +239 -27
- package/scripts/lib/validate/check-test-git-config-target.mjs +24 -34
- package/scripts/lib/validate/check-test-value-bans.mjs +87 -14
- package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
- package/scripts/lib/validate/check-untracked-test-deps.mjs +7 -102
- package/scripts/lib/validate/check-unwired-features.mjs +130 -27
- package/scripts/lib/validate/check-validator-registration.mjs +34 -10
- package/scripts/lib/validate/confidential-names.mjs +10 -0
- package/scripts/lib/validate-vendored-rules.mjs +210 -84
- package/scripts/lib/vault-mirror/namespace.mjs +46 -8
- package/scripts/lib/vault-mirror/process.mjs +10 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
- package/scripts/lib/vault-mirror/telemetry.mjs +8 -1
- package/scripts/lib/vault-status/board-writer.mjs +48 -11
- package/scripts/lib/vault-status/narrative-mirror.mjs +71 -16
- package/scripts/lib/vault-yaml.mjs +118 -0
- package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
- package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
- package/scripts/lib/wave-resource-gate.mjs +34 -8
- package/scripts/lib/worktree/lifecycle.mjs +153 -1
- package/scripts/memory-propose.mjs +18 -5
- package/scripts/release-session-lock.mjs +306 -0
- package/scripts/release.mjs +40 -8
- package/scripts/repair-invalid-sessions.mjs +37 -4
- package/scripts/resolve-session-invocation.mjs +59 -0
- package/scripts/run-migrate-v2-cross-repo.mjs +158 -30
- package/scripts/run-quality-gate.mjs +357 -197
- package/scripts/site-numbers.mjs +163 -5
- package/scripts/sweep-expired-learnings.mjs +56 -5
- package/scripts/sweep-expired-rules.mjs +16 -4
- package/scripts/validate-plugin.mjs +19 -0
- package/scripts/validate-wave-scope.mjs +32 -105
- package/scripts/vault-integration-watcher.mjs +2 -1
- package/scripts/vault-mirror.mjs +81 -47
- package/scripts/wave-scope-binding.mjs +2 -1
- package/skills/_shared/config-reading.md +3 -3
- package/skills/_shared/fleet-protocol.md +131 -0
- package/skills/_shared/platform-tools.md +23 -11
- package/skills/_shared/state-ownership.md +5 -0
- package/skills/autopilot/SKILL.md +47 -18
- package/skills/bootstrap/SKILL.md +1 -1
- package/skills/bootstrap/_shared-template.md +1 -1
- package/skills/bootstrap/fast-template.md +1 -1
- package/skills/bootstrap/private-contract.md +2 -1
- package/skills/bootstrap/public-fallback.md +6 -3
- package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
- package/skills/claude-md-drift-check/SKILL.md +10 -10
- package/skills/claude-md-drift-check/checker.mjs +26 -18
- package/skills/convergence-monitoring/README.md +8 -1
- package/skills/convergence-monitoring/SIGNALS.md +50 -6
- package/skills/convergence-monitoring/SKILL.md +15 -6
- package/skills/eval/SKILL.md +39 -24
- package/skills/eval/rubric-v1.md +1 -0
- package/skills/eval/rubric-v2.md +457 -0
- package/skills/evolve/SKILL.md +3 -3
- package/skills/evolve/references/evolve-analyze-mode.md +10 -6
- package/skills/evolve/references/evolve-dialectic-mode.md +42 -25
- package/skills/gitlab-ops/SKILL.md +3 -2
- package/skills/memory-cleanup/SKILL.md +1 -1
- package/skills/navigator/SKILL.md +193 -0
- package/skills/navigator/references/account-check.sh +87 -0
- package/skills/navigator/references/fleet-decisions.mjs +231 -0
- package/skills/navigator/references/slot-check.sh +114 -0
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/persona-panel/SKILL.md +2 -2
- package/skills/persona-panel/persona-format.md +2 -2
- package/skills/persona-panel/presets/designer-lens.md +1 -1
- package/skills/persona-panel/presets/engineer-lens.md +1 -1
- package/skills/persona-panel/presets/pm-lens.md +1 -1
- package/skills/plan/mode-retro.md +19 -4
- package/skills/quality-gates/SKILL.md +6 -4
- package/skills/reconcile/SKILL.md +11 -0
- package/skills/remote-offload/SKILL.md +4 -2
- package/skills/session-end/SKILL.md +13 -16
- package/skills/session-end/discovery-scan.md +1 -1
- package/skills/session-end/learning-patterns.md +22 -12
- package/skills/session-end/metrics-collection.md +5 -6
- package/skills/session-end/phase-3-6-tail.md +55 -9
- package/skills/session-end/references/phase-3-documentation-updates.md +2 -2
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
- package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
- package/skills/session-end/references/session-summary-template.md +1 -1
- package/skills/session-end/session-metrics-write.md +32 -60
- package/skills/session-plan/SKILL.md +17 -8
- package/skills/session-plan/references/session-plan-task-classification.md +2 -2
- package/skills/session-start/SKILL.md +6 -0
- package/skills/session-start/references/operations-contract.md +4 -0
- package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
- package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
- package/skills/test-audit/SKILL.md +152 -0
- package/skills/test-audit/references/campaign.md +111 -0
- package/skills/test-audit/references/mutate.sh +50 -0
- package/skills/ux-grill/SKILL.md +1 -1
- package/skills/wave-executor/SKILL.md +9 -5
- package/skills/wave-executor/circuit-breaker.md +2 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +8 -3
- package/skills/wave-executor/references/wave-loop-dispatch.md +5 -2
- package/skills/wave-executor/references/wave-loop-review.md +3 -5
- package/templates/personas/README.md +5 -5
- package/templates/personas/accounting-compliance.v1.md +1 -1
- package/templates/personas/accounting-tax-advisor.v1.md +1 -1
- package/templates/personas/buyer-p1-cto.v1.md +1 -1
- package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
- package/templates/personas/buyer-p3-build.v1.md +1 -1
- package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
- package/templates/personas/buyer-p5-solo.v1.md +1 -1
- package/templates/personas/buyer-p6-ld.v1.md +1 -1
- package/templates/personas/klima-ai-expert.v1.md +1 -1
- package/templates/personas/klima-physicist.v1.md +1 -1
- package/.cursor/commands/convergence-monitoring.md +0 -13
- package/.cursor/commands/npm-publish.md +0 -13
- package/pi/prompts/convergence-monitoring.md +0 -11
- package/pi/prompts/npm-publish.md +0 -11
package/scripts/vault-mirror.mjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 2 — filesystem error
|
|
19
19
|
*
|
|
20
20
|
* Output: one JSON line per action on stdout:
|
|
21
|
-
* {"action":"created|updated|skipped-noop|skipped-handwritten|skipped-collision-resolved|skipped-invalid|skipped-quality-low","path":"...","kind":"...","id":"..."}
|
|
21
|
+
* {"action":"created|updated|skipped-noop|skipped-handwritten|skipped-collision-resolved|skipped-invalid|skipped-quality-low|skipped-abandoned|skipped-duplicate-session","path":"...","kind":"...","id":"..."}
|
|
22
22
|
*
|
|
23
23
|
* Idempotency rules:
|
|
24
24
|
* 1. File does not exist → create.
|
|
@@ -48,22 +48,27 @@
|
|
|
48
48
|
* Part of session-orchestrator vault-mirror (Issue #14).
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
|
-
import { spawnSync } from 'node:child_process';
|
|
52
51
|
import { existsSync } from 'node:fs';
|
|
53
|
-
import { resolve } from 'node:path';
|
|
52
|
+
import { basename, resolve } from 'node:path';
|
|
54
53
|
import { createInterface } from 'node:readline';
|
|
55
54
|
import { createReadStream } from 'node:fs';
|
|
56
55
|
|
|
57
|
-
import {
|
|
56
|
+
import {
|
|
57
|
+
processLearning,
|
|
58
|
+
processSession,
|
|
59
|
+
getMaskerStats,
|
|
60
|
+
emitAction,
|
|
61
|
+
} from './lib/vault-mirror/process.mjs';
|
|
58
62
|
import { emitMirrorEvent, emitMirrorRunEvent } from './lib/vault-mirror/telemetry.mjs';
|
|
59
63
|
import { emitEvent } from './lib/events.mjs';
|
|
60
64
|
import { autoCommitVaultMirror } from './lib/vault-mirror/auto-commit.mjs';
|
|
61
65
|
import { parseColumnFlags, CliFlagError } from './lib/cli-flags.mjs';
|
|
62
66
|
import { resolveRepoNamespace } from './lib/vault-mirror/namespace.mjs';
|
|
63
|
-
import {
|
|
67
|
+
import { checkCanonicalVault, describeOriginForLog, normalizeRemote } from './lib/named-vault-resolver.mjs';
|
|
64
68
|
import { loadOwnerConfig } from './lib/owner-yaml.mjs';
|
|
65
69
|
import { canonicalizeSessions } from './lib/sessions-canonical.mjs';
|
|
66
70
|
import { isMainModule } from './lib/is-main-module.mjs';
|
|
71
|
+
import { expandTilde } from './lib/common.mjs';
|
|
67
72
|
|
|
68
73
|
// ── Canonical-vault helpers (#600 D2 / #607 D2) ────────────────────────────────
|
|
69
74
|
// These are module-level (above the CLI bootstrap) so the module is import-safe
|
|
@@ -85,7 +90,7 @@ export function _resolveCanonicalSuffix(envValue) {
|
|
|
85
90
|
return envValue && envValue.trim() ? envValue.trim() : '/agents/vault';
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
// Kept for documentation; the guard now uses
|
|
93
|
+
// Kept for documentation; the guard now uses checkCanonicalVault() which
|
|
89
94
|
// generalises this to N suffixes. The `_` prefix satisfies the no-unused-vars rule.
|
|
90
95
|
const _CANONICAL_VAULT_SUFFIX = _resolveCanonicalSuffix(
|
|
91
96
|
process.env.VAULT_MIRROR_CANONICAL_SUFFIX,
|
|
@@ -93,18 +98,14 @@ const _CANONICAL_VAULT_SUFFIX = _resolveCanonicalSuffix(
|
|
|
93
98
|
|
|
94
99
|
/**
|
|
95
100
|
* Normalize a git remote URL to a host/path tail for canonical-suffix matching
|
|
96
|
-
* (#607 D2 — exported for unit tests).
|
|
97
|
-
*
|
|
101
|
+
* (#607 D2 — exported for unit tests). Since #1450 the ONE implementation is
|
|
102
|
+
* `normalizeRemote` in lib/named-vault-resolver.mjs, shared with the board
|
|
103
|
+
* writer's guard; this name is kept for the existing test imports.
|
|
98
104
|
* @param {string} url
|
|
99
105
|
* @returns {string}
|
|
100
106
|
*/
|
|
101
107
|
export function _normalizeRemote(url) {
|
|
102
|
-
return
|
|
103
|
-
.trim()
|
|
104
|
-
.replace(/\.git$/, '')
|
|
105
|
-
.replace(/^git@([^:]+):/, '$1/')
|
|
106
|
-
.replace(/^[a-z]+:\/\//, '')
|
|
107
|
-
.replace(/\/+$/, '');
|
|
108
|
+
return normalizeRemote(url);
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
// ── Mirror telemetry (#1116) ──────────────────────────────────────────────────
|
|
@@ -235,7 +236,11 @@ if (flagValues.help === true) {
|
|
|
235
236
|
process.exit(0);
|
|
236
237
|
}
|
|
237
238
|
|
|
238
|
-
|
|
239
|
+
// Expand a leading `~` before anything touches the path: owner.yaml `vault-dirs:` /
|
|
240
|
+
// `paths.vault-dir` and the committed Session Config all accept `~/…`, and a quoted
|
|
241
|
+
// `--vault-dir "~/…"` reaches us literally. `resolve('~/x')` would yield `<cwd>/~/x`
|
|
242
|
+
// and the existsSync check below would abort with `missing-vault-dir` (agents/vault#319).
|
|
243
|
+
const vaultDir = expandTilde(flagValues['vault-dir']);
|
|
239
244
|
const source = flagValues.source;
|
|
240
245
|
const kind = flagValues.kind;
|
|
241
246
|
const dryRun = flagValues['dry-run'] === true;
|
|
@@ -323,6 +328,21 @@ if (kind !== 'learning' && kind !== 'session') {
|
|
|
323
328
|
// imports) so they are import-safe and unit-testable; see _resolveCanonicalSuffix
|
|
324
329
|
// / _normalizeRemote there (#607 D2).
|
|
325
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Render a CLI path flag for a stderr line as its basename only (#1479).
|
|
333
|
+
*
|
|
334
|
+
* This CLI's stderr lands in CI logs and session transcripts, and an absolute
|
|
335
|
+
* `--vault-dir` / `--source` carries the operator's home directory — the
|
|
336
|
+
* owner-leakage class `.claude/rules/security.md` § Owner-Privacy guards. The
|
|
337
|
+
* basename still says WHICH value was wrong; the caller passed the full path
|
|
338
|
+
* and already knows it.
|
|
339
|
+
* @param {string} p
|
|
340
|
+
* @returns {string}
|
|
341
|
+
*/
|
|
342
|
+
function pathForLog(p) {
|
|
343
|
+
return `.../${basename(String(p ?? ''))}`;
|
|
344
|
+
}
|
|
345
|
+
|
|
326
346
|
// ── Run-level accounting + run close-out (#1147) ──────────────────────────────
|
|
327
347
|
//
|
|
328
348
|
// Deliberately OUTSIDE main(): the run event's whole contract is that it is
|
|
@@ -430,32 +450,29 @@ async function main() {
|
|
|
430
450
|
// are all `0`, and `aborted` is what makes that zero readable as "never
|
|
431
451
|
// started" rather than "ran over an empty source".
|
|
432
452
|
if (!existsSync(resolve(vaultDir))) {
|
|
433
|
-
process.stderr.write(`vault-mirror: vault-dir not found: ${vaultDir}\n`);
|
|
453
|
+
process.stderr.write(`vault-mirror: vault-dir not found: ${pathForLog(vaultDir)}\n`);
|
|
434
454
|
await finishRun('missing-vault-dir');
|
|
435
455
|
process.exit(2);
|
|
436
456
|
}
|
|
437
457
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
await finishRun('vault-not-canonical');
|
|
453
|
-
process.exit(2);
|
|
454
|
-
}
|
|
458
|
+
// The check itself — origin probe, suffix match, the SKIP_CANONICAL_CHECK
|
|
459
|
+
// escape hatch — is the shared `checkCanonicalVault` (#1450), the same one the
|
|
460
|
+
// board writer applies, so the two vault writers cannot drift apart again.
|
|
461
|
+
const canonical = checkCanonicalVault({
|
|
462
|
+
vaultDir: resolve(vaultDir),
|
|
463
|
+
ownerConfig: loadOwnerConfig().config,
|
|
464
|
+
env: process.env,
|
|
465
|
+
});
|
|
466
|
+
if (!canonical.ok) {
|
|
467
|
+
process.stderr.write(
|
|
468
|
+
`vault-mirror: refusing to mirror — vault is not the canonical Meta-Vault (expected git origin ending in one of: ${canonical.expected.join(', ')}; got ${describeOriginForLog(canonical.got) || 'no git origin'})\n`,
|
|
469
|
+
);
|
|
470
|
+
await finishRun('vault-not-canonical');
|
|
471
|
+
process.exit(2);
|
|
455
472
|
}
|
|
456
473
|
|
|
457
474
|
if (!existsSync(resolve(source))) {
|
|
458
|
-
process.stderr.write(`vault-mirror: source file not found: ${source}\n`);
|
|
475
|
+
process.stderr.write(`vault-mirror: source file not found: ${pathForLog(source)}\n`);
|
|
459
476
|
await finishRun('missing-source');
|
|
460
477
|
process.exit(2);
|
|
461
478
|
}
|
|
@@ -485,6 +502,10 @@ async function main() {
|
|
|
485
502
|
kind,
|
|
486
503
|
force,
|
|
487
504
|
vaultName,
|
|
505
|
+
// #1389: the repo whose `.vault.yaml` declares the namespace slug. This CLI
|
|
506
|
+
// has no repo-root flag, so it is the invocation cwd — bound ONCE here and
|
|
507
|
+
// shared by every processor call and the auto-commit below.
|
|
508
|
+
repoRoot: process.cwd(),
|
|
488
509
|
qualityMinNarrativeChars,
|
|
489
510
|
qualityMinConfidence,
|
|
490
511
|
};
|
|
@@ -650,18 +671,27 @@ async function main() {
|
|
|
650
671
|
if (isIdentifiable(entry) && !survivors.has(entry)) {
|
|
651
672
|
// A losing duplicate: an earlier line whose `session_id` a LATER line
|
|
652
673
|
// in this same batch supersedes or overwrites (crash-recovery
|
|
653
|
-
// re-append, #1068 stub/supersede pair).
|
|
654
|
-
//
|
|
655
|
-
//
|
|
656
|
-
//
|
|
657
|
-
//
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
//
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
674
|
+
// re-append, #1068 stub/supersede pair). Never dispatched — the winning
|
|
675
|
+
// occurrence (dispatched below, at its own position) produces the ONE
|
|
676
|
+
// note this physical session gets. It is still ACCOUNTED for (#1291):
|
|
677
|
+
// `skipped-duplicate-session` goes through the same per-entry path as
|
|
678
|
+
// every other skip (stdout line + per-entry ledger record, no `path`
|
|
679
|
+
// because no target file exists for it) and into the tally, so
|
|
680
|
+
// `created+updated+skipped+failed === total` partitions a `--kind
|
|
681
|
+
// session` run that collapsed duplicates, and the ledger names WHICH
|
|
682
|
+
// lines were collapsed, not just how many notes were written.
|
|
683
|
+
tally(
|
|
684
|
+
await emitAction({
|
|
685
|
+
action: 'skipped-duplicate-session',
|
|
686
|
+
path: null,
|
|
687
|
+
kind,
|
|
688
|
+
id: entry.session_id,
|
|
689
|
+
vaultDir: ctx.vaultDir,
|
|
690
|
+
meta: { line: sessionLineNums[i] },
|
|
691
|
+
line: sessionLineNums[i],
|
|
692
|
+
dryRun,
|
|
693
|
+
}),
|
|
694
|
+
);
|
|
665
695
|
continue;
|
|
666
696
|
}
|
|
667
697
|
await dispatchEntry(entry, sessionLineNums[i]);
|
|
@@ -693,7 +723,11 @@ async function main() {
|
|
|
693
723
|
// Opt-in: triggers only when --session-id is provided. Callers (session-end, evolve)
|
|
694
724
|
// pass it explicitly; bare invocations stay quiet to preserve legacy behaviour.
|
|
695
725
|
if (!dryRun && !noCommit && sessionIdArg) {
|
|
696
|
-
autoCommitVaultMirror(
|
|
726
|
+
autoCommitVaultMirror(
|
|
727
|
+
resolve(vaultDir),
|
|
728
|
+
sessionIdArg,
|
|
729
|
+
resolveRepoNamespace({ vaultName, repoRoot: ctx.repoRoot }),
|
|
730
|
+
);
|
|
697
731
|
}
|
|
698
732
|
}
|
|
699
733
|
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
39
|
import { parseArgs } from 'node:util';
|
|
40
|
+
import path from 'node:path';
|
|
40
41
|
import { attributionForRecord, emitEvent } from './lib/events.mjs';
|
|
41
42
|
import { MANIFEST_SESSION_KEYS } from './lib/session-identity/own-session.mjs';
|
|
42
43
|
import { isMainModule } from './lib/is-main-module.mjs';
|
|
@@ -109,7 +110,7 @@ async function main(argv) {
|
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
const repoRoot = parsed.values['repo-root'] ?? process.cwd();
|
|
113
|
+
const repoRoot = path.resolve(parsed.values['repo-root'] ?? process.cwd());
|
|
113
114
|
const binding = resolveBinding(repoRoot);
|
|
114
115
|
|
|
115
116
|
if (Object.keys(binding).length === 0) {
|
|
@@ -133,14 +133,14 @@ Learnings live exclusively in `.orchestrator/metrics/learnings.jsonl`. The pre-`
|
|
|
133
133
|
|
|
134
134
|
The learning lifecycle states are:
|
|
135
135
|
|
|
136
|
-
- **Created**: `confidence: 0.5`, `expires_at
|
|
137
|
-
- **Confirmed** (same type+subject seen again): `confidence += 0.15` (cap 1.0), `expires_at` reset
|
|
136
|
+
- **Created**: `confidence: 0.5`, `expires_at` = `created_at` + a per-TYPE TTL — `deriveExpiresAt(created_at, type)` with `LEARNING_TTL_DAYS[type] ?? LEARNING_TTL_DAYS.default` (`scripts/lib/learnings/schema.mjs`; 30–90 days per type, 60 for an unknown type). A caller-supplied `expires_at` is kept. `learning-expiry-days` does NOT set it: `scripts/lib/config.mjs` still parses that key (default 30), but no script or hook reads the parsed value — it survives only in skill prose (the `/evolve` Review-mode *Extend* action).
|
|
137
|
+
- **Confirmed** (same type+subject seen again): `confidence += 0.15` (cap 1.0), `expires_at` reset to `deriveExpiresAt(now, type)`
|
|
138
138
|
- **Contradicted** (evidence against): `confidence -= 0.2` — do NOT reset `expires_at` (let the learning decay naturally if contradicted)
|
|
139
139
|
- **Decayed** (untouched this session): `confidence -= learning-decay-rate` (from Session Config, default `0.05`). Applied at session-end after touched-set update, before prune. Clamped to 0.0. Does NOT reset `expires_at`.
|
|
140
140
|
- **Expired**: `expires_at < current date` — removed on next write
|
|
141
141
|
- **Dead**: `confidence <= 0.0` — removed on next write
|
|
142
142
|
|
|
143
|
-
**Expiration check semantics:**
|
|
143
|
+
**Expiration check semantics:** The code compares full timestamps, not dates: `pruneLearnings()` (`scripts/lib/learnings/expiry-sweep.mjs`) archives when `expires_at < now`; the time-driven sweep archives only after a 14-day grace window past `expires_at`. When writing `expires_at`, derive it with `deriveExpiresAt()` (full ISO timestamp, no midnight rounding) — never from `learning-expiry-days`.
|
|
144
144
|
|
|
145
145
|
**Confidence bounds enforcement:** After EVERY increment or decrement, clamp confidence to [0.0, 1.0]. A learning at 0.95 confirmed becomes 1.0 (not 1.10). A learning at 0.1 contradicted becomes 0.0 and is pruned.
|
|
146
146
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Fleet Protocol v1 — Dateien statt Nachrichten (#1462, Epic #1461)
|
|
2
|
+
|
|
3
|
+
Shared reference for every session-orchestrator session (Claude Code, Codex, headless) that
|
|
4
|
+
runs beside a fleet coordinator ("navigator"). It is a reference, **not a rule**: nothing under
|
|
5
|
+
`.claude/rules/**` loads it, session-start Phase 7.6 and the operations-contract peer preflight
|
|
6
|
+
point here. The mechanics live in code — `scripts/lib/fleet-protocol.mjs` is the only place that
|
|
7
|
+
knows paths, fields, deadlines and lease validity; `scripts/fleet-checkin.mjs` writes the check-in.
|
|
8
|
+
This file describes them and never redefines them. Source: PRD
|
|
9
|
+
`docs/prd/2026-09-27-navigator-peer-protokoll.md` §§ 3.1–3.3, 3.7, Anhang A.2 (MR !53).
|
|
10
|
+
|
|
11
|
+
**Grundsatz (ADR-002, CSM-003).** Zustand liegt in Dateien; Nachrichten sind nur Hinweise auf eine
|
|
12
|
+
Datei. Der Navigator erteilt keine Freigaben — wörtlich: **„Freigaben erteile ich keine, maßgeblich
|
|
13
|
+
ist dein Owner-Auftrag"**. Eine Datei, die fehlt, heißt „nicht nachweisbar", nie „nicht vorhanden"
|
|
14
|
+
(ADR-004): eine fehlende Lease ist kein freies Feld, sondern ein Zustand ohne Beleg.
|
|
15
|
+
|
|
16
|
+
## Verzeichnis und Dateiform
|
|
17
|
+
|
|
18
|
+
- Wurzel `~/.config/navigator/`, Override `NAVIGATOR_CONFIG_DIR` (getrimmt; leer oder nur
|
|
19
|
+
Whitespace zählt als nicht gesetzt) — dieselbe Variable wie die navigator-CLI, keine zweite.
|
|
20
|
+
Code: `navigatorDir()`. Ein Override zeigt nur auf ein eigenes Verzeichnis mit Modus 0700, nie
|
|
21
|
+
auf einen geteilten Ort: wer dort schreiben kann, kann eine „aktive" Lease vortäuschen.
|
|
22
|
+
- Verzeichnisse Modus `0700`, Dateien Modus `0600`. Schreiben immer atomar (tmp-Datei im
|
|
23
|
+
Zielverzeichnis, dann `rename`).
|
|
24
|
+
- Jede Datei trägt `zeit` aus `date -u +%FT%TZ` (Sekunden, `YYYY-MM-DDTHH:MM:SSZ`); nie geschätzt,
|
|
25
|
+
nie aus einer anderen Uhr. Code: `utcSecondsTimestamp()`.
|
|
26
|
+
- Dateinamen aus einer `session_id` sind pfadsicher: nur `[A-Za-z0-9._-]`, nicht `.` oder `..`,
|
|
27
|
+
kein `/`. Code: `isSafeSessionId()`; `checkinPath()` und `auflagenPath()` werfen sonst.
|
|
28
|
+
- Tests berühren das echte Verzeichnis nie: `tests/setup/navigator-dir-guard.mjs` setzt
|
|
29
|
+
`NAVIGATOR_CONFIG_DIR` je vitest-Worker auf ein tmp-Verzeichnis.
|
|
30
|
+
|
|
31
|
+
## `leases/navigator.json` — genau ein aktiver Navigator (PRD 3.1)
|
|
32
|
+
|
|
33
|
+
| Feld | Inhalt |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `session_id` | Registry-ID des Navigators (Pflicht; pfadsicher wie oben, höchstens 128 Zeichen) |
|
|
36
|
+
| `plattform` | `claude` \| `codex` \| `kopflos` (Pflicht) |
|
|
37
|
+
| `adresse` | `ListAgents`-Name, wenn Claude (`[A-Za-z0-9._:@-]`, 1–128 Zeichen); sonst `null` |
|
|
38
|
+
| `seit` | Zeit des Erwerbs, UTC mit `Z`, Sekunden oder Millisekunden (Pflicht) |
|
|
39
|
+
| `laeuft_ab` | UTC mit `Z`; Erneuerung je Ticker-Runde, Ablauf 30 min nach der letzten (Pflicht) |
|
|
40
|
+
| `uebergabe_an` | `null` oder Session-ID des Nachfolgers |
|
|
41
|
+
|
|
42
|
+
**„Aktiv" heißt ausschließlich: gültige Lease.** `readNavigatorLease()` liefert genau eines von
|
|
43
|
+
`active` (Datei lesbar, Pflichtfelder da, `laeuft_ab` in der Zukunft), `none` (Datei fehlt oder
|
|
44
|
+
`laeuft_ab` überschritten) oder `unreadable` (kaputtes JSON, fehlende Pflichtfelder, Lesefehler, oder ein Feld außerhalb der
|
|
45
|
+
Tabellenform: unbekannte `plattform`, Steuerzeichen in `session_id`/`adresse`, eine Zeit ohne `Z`
|
|
46
|
+
oder mit Offset — sie würde in lokaler Zeit gelesen und könnte die Lease verlängern).
|
|
47
|
+
Unlesbar oder abgelaufen ist **nie** aktiv (fail-closed). Registry-Heartbeat (`role: navigator`,
|
|
48
|
+
`scripts/lib/session-registry.mjs`) und `ListAgents` sind Zusatzsignale, keine Lebendbeweise.
|
|
49
|
+
Erwerb und Übergabe der Lease sind S4 (agents/navigator#36), nicht Teil dieses Repos.
|
|
50
|
+
|
|
51
|
+
## `checkin/<session_id>.json` — Session an Navigator (PRD 3.2)
|
|
52
|
+
|
|
53
|
+
**Schreibend** heißt: Änderung an Repo-Inhalt oder VCS-Zustand (Datei im Arbeitsbaum außerhalb
|
|
54
|
+
`.orchestrator/` und `.claude/`, Commit, Branch, Push, MR, Issue, Kommentar). SO-eigener
|
|
55
|
+
Sitzungszustand zählt nicht: Phase 1.1 (CLAUDE.md-Migration, einmalig), 1.2 `session.lock`, 1.5
|
|
56
|
+
`STATE.md`, 1.6 Metriken, 1.7 Live-Status-Board. Phase 1.1 ist eine Repo-Datei und wird deshalb
|
|
57
|
+
als Ausnahme im Check-in genannt (`vorab_geschrieben`). (`CLAUDE.md` heißt auf Codex CLI `AGENTS.md`, siehe
|
|
58
|
+
`skills/_shared/instruction-file-resolution.md`.)
|
|
59
|
+
|
|
60
|
+
Der Check-in liegt **vor der ersten schreibenden Aktion** (Phase 7.6, oder der Peer-Preflight der
|
|
61
|
+
Operations-Route). Schreiber: `node scripts/fleet-checkin.mjs` liest das JSON von stdin, ergänzt
|
|
62
|
+
`zeit`, validiert (`validateCheckin()`), schreibt atomar mit Modus 0600 und emittiert
|
|
63
|
+
`orchestrator.fleet.checkin` (Payload `session`, `repo`, `modus`, `kandidaten`, `navigator_state`).
|
|
64
|
+
Exit 0 geschrieben, 2 ungültige Eingabe (Fehlerliste auf stderr, keine Datei), 1 Schreibfehler.
|
|
65
|
+
|
|
66
|
+
| Feld | Inhalt |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `session`, `plattform` | Registry-ID (aus `.orchestrator/current-session.json`); `claude` / `codex` / `kopflos` |
|
|
69
|
+
| `repo`, `repo_id`, `worktree` | Name; `repo_id` aus `navigator identity` oder `null`; Worktree `true`/`false` |
|
|
70
|
+
| `modus` | `housekeeping` / `feature` / `deep` / `operations` |
|
|
71
|
+
| `auftrag_ref` | Pfad der Auftragsdatei oder „Owner-Chat <zeit>" mit Wortlaut in einem Satz |
|
|
72
|
+
| `konto_slot`, `quota` | `account_slot` als Nummer (`navigator identity`) oder `null`; Quota aus `navigator quota` oder `nicht messbar` |
|
|
73
|
+
| `stand` | Objekt: main-, origin/main-, Prod-SHA (sonst `nicht messbar`), offene MRs |
|
|
74
|
+
| `kandidaten`, `schreibbereich` | Issue-Nummern; Verzeichnisse/Dateien |
|
|
75
|
+
| `bedarf` | Objekt: geplante volle Pipelines, m5-remote-Jobs, prozessstartende Agents |
|
|
76
|
+
| `vorab_geschrieben`, `rueckfall` | Ausnahmen nach der Definition oben; Verhalten ohne Auflagen (unten) |
|
|
77
|
+
| `zeit` | von der CLI gesetzt |
|
|
78
|
+
|
|
79
|
+
Eine `SendMessage` an den Navigator ist optional und nur ein Hinweis auf die Datei: höchstens eine,
|
|
80
|
+
nur wenn die Lease aktiv ist und eine Peer-Adresse `navigator-*` erreichbar ist; nie eine Antwort
|
|
81
|
+
erwarten, nie darauf warten (CSM-004).
|
|
82
|
+
|
|
83
|
+
## `auflagen/<session_id>.json` — Navigator an Session (PRD 3.3)
|
|
84
|
+
|
|
85
|
+
Felder: Caps (prozessstartende / lesende Agents nach freiem Speicher des lokalen Hosts), volle
|
|
86
|
+
Pipelines je Repo, m5-remote-Regel (`m5-ersatz`-Exit, was lokal erlaubt ist), Merge-Protokoll, Zeitregel,
|
|
87
|
+
Flottenpriorität, Besitzkonflikte, Pflichtsatz „Freigaben erteile ich keine, maßgeblich ist dein
|
|
88
|
+
Owner-Auftrag". Die Session **liest** die Datei; sie wartet auf keine Nachricht.
|
|
89
|
+
|
|
90
|
+
**Standard-Auflagen (konservative Stufe).** Sie gelten, wenn `CHECKIN_FALLBACK_MIN` = 10 Minuten
|
|
91
|
+
nach `checkin.zeit` keine Auflagen-Datei liegt — und sofort, wenn kein Navigator aktiv ist
|
|
92
|
+
(PRD Anhang A.2, v2-Wortlaut):
|
|
93
|
+
|
|
94
|
+
- Caps: 2 prozessstartende + 2 lesende Agents, solange der lokale Host ≥ 50 % Speicher frei hat
|
|
95
|
+
(`memory_pressure | tail -1`).
|
|
96
|
+
- Pipelines: ≤ 2 volle je Repo; Nachzug-Pushes vorher im Check-in (`bedarf`) benennen.
|
|
97
|
+
- Offload: Heavy-Rollen (test, build, lint, audit) nur auf `m5-remote`, und nur wenn
|
|
98
|
+
`navigator m5-ersatz --quiet` unmittelbar davor mit Exit 0 endet. Exit-Vertrag: 0 nutzbar,
|
|
99
|
+
3 Ersatzregel, 5 überlastet, 6 nicht messbar; jeder Exit außer 0 (auch ein fehlender Befehl)
|
|
100
|
+
heißt: kein neues Offload-Gate. Schwelle und Hysterese leben allein in diesem Befehl — hier und
|
|
101
|
+
in den Skills steht bewusst keine Lastzahl. Lokal nur `vitest` bzw. `eslint` je Datei mit `timeout`.
|
|
102
|
+
- Zeiten nur aus `date`.
|
|
103
|
+
- Kein Merge ohne Befugnis nach PRD 3.5: `navigator authority query <repo> merge --exit-code` mit
|
|
104
|
+
Exit 0 **oder** ein ausdrücklicher Owner-Auftrag, der Merge für genau dieses Repo nennt
|
|
105
|
+
(`auftrag_ref`). Ohne navigator-CLI ist jeder Merge `einzeln`.
|
|
106
|
+
|
|
107
|
+
Lesende Arbeit und Schreiben im eigenen Worktree laufen währenddessen weiter; der Rückfall ist ein
|
|
108
|
+
Dateistand mit Frist, kein Warten auf eine Antwort.
|
|
109
|
+
|
|
110
|
+
## Verhalten ohne Navigator (PRD 3.7)
|
|
111
|
+
|
|
112
|
+
Lease `none` oder `unreadable`: die Check-in-Datei wird **trotzdem** geschrieben (sie ist der
|
|
113
|
+
zählbare Beleg), die Standard-Auflagen gelten sofort, es geht keine Nachricht ab. Kopflose Läufe
|
|
114
|
+
sind per Nachricht nicht erreichbar und nutzen dieselben Dateien; ihr Brief verlangt, vor jeder
|
|
115
|
+
Welle und vor jedem MR `auflagen/` und `merge/` zu lesen.
|
|
116
|
+
|
|
117
|
+
## Vorschau: `merge/<repo_id>/*` (S2, #1463 — hier keine Mechanik)
|
|
118
|
+
|
|
119
|
+
Ansage `ansage-<mr>.json` (MR, gepinnte Head-SHA, Pipeline-ID, Jobliste, Gate-Log-SHA, Review-Stand,
|
|
120
|
+
Migration, `laeuft_ab` +20 min), Lease `lease-<mr>.json` (Navigator, +15 min), Meldung
|
|
121
|
+
`done-<mr>.json` (Merge-SHA, main-Pipeline-ID, Prod-SHA). Verfall bei Ablauf, MR nicht mehr
|
|
122
|
+
`opened` oder geändertem Head. Nichts davon ist in diesem Repo implementiert; bis S2 gilt PRD 3.4
|
|
123
|
+
Punkt 3: selbst messen und nach 3.5 mergen, oder `navigator ask --aktion merge`.
|
|
124
|
+
|
|
125
|
+
## See Also
|
|
126
|
+
|
|
127
|
+
`skills/session-start/SKILL.md` Phase 7.6 · `skills/session-start/references/operations-contract.md`
|
|
128
|
+
(Peer-Preflight) · `skills/_shared/state-ownership.md` § Session Identity and Lock Ownership (`role`) ·
|
|
129
|
+
`docs/events-schema.md` (`orchestrator.fleet.checkin`) · `.claude/rules/cross-session-messaging.md`
|
|
130
|
+
(CSM-003/004) · `scripts/lib/fleet-protocol.mjs` · `scripts/fleet-checkin.mjs` ·
|
|
131
|
+
`skills/navigator/SKILL.md` (`/session-orchestrator:navigator`)
|
|
@@ -8,15 +8,17 @@ The current platform is determined by the `scripts/lib/platform.mjs` library:
|
|
|
8
8
|
- `$SO_PLATFORM` = `claude` | `codex` | `cursor` | `pi`
|
|
9
9
|
- Environment: `$CLAUDE_PLUGIN_ROOT` (Claude Code), `$CODEX_PLUGIN_ROOT` (Codex CLI), `$CURSOR_RULES_DIR` (Cursor IDE), or `$PI_PLUGIN_ROOT` (Pi)
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
11
|
+
## File and Shell Tool Adaptation
|
|
12
|
+
|
|
13
|
+
Skill bodies use Claude Code names as operations, not as a requirement that every
|
|
14
|
+
harness expose those exact tools. Use the current runtime's available tools.
|
|
15
|
+
Measured in Codex Desktop 0.153.4 on 2026-09-19: `exec_command` runs shell
|
|
16
|
+
commands (`cat`, `rg`, `rg --files` for Read/Grep/Glob); `apply_patch` performs
|
|
17
|
+
file edits. These may be exposed through a `functions.exec` tools namespace.
|
|
18
|
+
Never call an unavailable `Read`, `Bash`, or `Skill` tool by name. An instruction
|
|
19
|
+
to invoke `session-orchestrator:<name>` means read and follow the canonical
|
|
20
|
+
`skills/<name>/SKILL.md` relative to the plugin root when no Skill tool exists.
|
|
21
|
+
Keep the user's project as the working directory for project operations.
|
|
20
22
|
|
|
21
23
|
## Platform-Specific Tool Mapping
|
|
22
24
|
|
|
@@ -24,7 +26,7 @@ These tools have the same name and behavior on all platforms. Cursor IDE uses eq
|
|
|
24
26
|
|
|
25
27
|
| Function | Claude Code | Codex CLI | Cursor IDE | Pi |
|
|
26
28
|
|----------|------------|-----------|------------|----|
|
|
27
|
-
| Present choices to user | `AskUserQuestion` tool with structured options |
|
|
29
|
+
| Present choices to user | `AskUserQuestion` tool with structured options | Available native user-input tool, respecting its mode restrictions; plain-text fallback when unavailable | Available native choice tool or numbered Markdown list | Numbered Markdown list v1; native UI adapter planned |
|
|
28
30
|
| Dispatch subagent | `Agent({ description, prompt, subagent_type })` | Native multi-agent collaboration namespace: `spawn_agent`, `list_agents`, `wait_agent`, `send_message`, `followup_task`, `interrupt_agent`, `close_agent`. Measured 2026-08-25 on `codex-cli 0.141.0` — `codex features list` → `multi_agent stable true`. | No native in-session Agent tool. Coordinator-side foreign dispatch via the headless `cursor-agent` CLI exists (`scripts/lib/wave-executor/foreign-dispatch.mjs`, #1150) — measured 2026-08-25 on `cursor-agent 2026.08.11-e8db854`. | Sequential execution v1. Do not assume native subagents until the Pi SDK dispatcher exists. |
|
|
29
31
|
| Track tasks | `TaskCreate` / `TaskUpdate` / `TaskList` | Plain-text checklist in response context | Plain-text checklist (same as Codex) | Plain-text checklist (same as Codex) |
|
|
30
32
|
| Enter plan mode | `EnterPlanMode` / `ExitPlanMode` tools | `/plan` slash command (prompt-level, not tool-based) | Instruction-based: "Focus on analysis and planning. Do not modify files until the user approves." | `/plan` prompt template; use instruction-based planning when tool mode is unavailable |
|
|
@@ -37,7 +39,13 @@ When a skill instructs "Use the AskUserQuestion tool", apply this pattern:
|
|
|
37
39
|
|
|
38
40
|
**On Claude Code:** Use the AskUserQuestion tool with structured options as documented.
|
|
39
41
|
|
|
40
|
-
**On Codex
|
|
42
|
+
**On Codex:** Prefer the available native user-input tool. In the measured Desktop
|
|
43
|
+
0.153.4 runtime (2026-09-19), `request_user_input_async` allows a question while
|
|
44
|
+
independent work continues; `request_user_input` has mode restrictions. Follow
|
|
45
|
+
the live tool contract. Existing user authorization remains valid; do not ask
|
|
46
|
+
again merely because a workflow names `AskUserQuestion`.
|
|
47
|
+
|
|
48
|
+
**When no suitable native tool is available (including Cursor IDE / Pi):** Present the same choices as a numbered Markdown list and ask the user to respond:
|
|
41
49
|
```
|
|
42
50
|
Choose one:
|
|
43
51
|
1. Option A — description
|
|
@@ -85,6 +93,10 @@ No Session Orchestrator Pi subagent dispatcher exists in v1. Execute wave tasks
|
|
|
85
93
|
|
|
86
94
|
Skills use `model-preference` (Claude), `model-preference-codex` (Codex), `model-preference-cursor` (Cursor), and active-model fallback on Pi in YAML frontmatter.
|
|
87
95
|
|
|
96
|
+
These are preferences, not authority to replace a user's selected model,
|
|
97
|
+
reasoning effort, or service tier. Preserve the current settings unless the user
|
|
98
|
+
requests a change; inherit them for native subagents.
|
|
99
|
+
|
|
88
100
|
## State Directory
|
|
89
101
|
|
|
90
102
|
- **Claude Code:** `.claude/` (STATE.md, wave-scope.json)
|
|
@@ -104,6 +104,11 @@ layer.
|
|
|
104
104
|
contract requires a trusted native resume identifier and remains a follow-up.
|
|
105
105
|
In particular, a host rotation that changes both raw and semantic values has
|
|
106
106
|
no guaranteed continuity.
|
|
107
|
+
- **Registry `role` (`'navigator'`) is display, never ownership.** The
|
|
108
|
+
authoritative claim is the navigator lease (`leases/navigator.json` under
|
|
109
|
+
`~/.config/navigator/`, see `skills/_shared/fleet-protocol.md`); `registerSelf()`
|
|
110
|
+
does not carry the field across a repeated SessionStart, so the `/navigator`
|
|
111
|
+
skill re-sets it each ticker round via `heartbeat(id, { role })` (#1462).
|
|
107
112
|
|
|
108
113
|
The peer-discovery and issue-budget procedures below apply these rules at their
|
|
109
114
|
narrow surfaces; neither creates a second ownership model.
|
|
@@ -39,11 +39,19 @@ the invocation surface only:
|
|
|
39
39
|
Headless requirements:
|
|
40
40
|
|
|
41
41
|
- Anthropic API key configured for `claude -p` (Claude Code CLI auth).
|
|
42
|
-
- `scripts/autopilot.mjs`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
- `scripts/autopilot.mjs` starts each child with `--session-id <fresh uuid>` and, after it
|
|
43
|
+
exits, reads the one canonical `sessions.jsonl` record whose `raw_session_id` is that uuid
|
|
44
|
+
to construct the `sessionRunner` return shape — the spawned session must complete cleanly
|
|
45
|
+
and append its record (session-end Phase 3.7 handles this). No such record, or more than
|
|
46
|
+
one, stops the loop with `failed-wave` instead of reading the ledger tail (#1457). So does
|
|
47
|
+
a unique record that is only a backfill stub (no waves/agents/token totals — the child never
|
|
48
|
+
closed): its token usage is unknown, not 0, so it is never counted as a healthy 0-token
|
|
49
|
+
iteration (#1457 F2).
|
|
50
|
+
- `AUTOPILOT_RUN_ID` env var is set in the child's env, but **nothing reads it yet**
|
|
51
|
+
(measured 2026-10-01: `rg -n "AUTOPILOT_RUN_ID" scripts hooks skills` finds only the writer
|
|
52
|
+
in `scripts/autopilot.mjs` and this line). CLI-driven iterations therefore carry no
|
|
53
|
+
`autopilot_run_id` on their `sessions.jsonl` record yet; join them to `autopilot.jsonl` via
|
|
54
|
+
the `sessions` list there, not via that field.
|
|
47
55
|
|
|
48
56
|
Do NOT re-implement loop logic inline — this skill and `scripts/lib/autopilot.mjs` are
|
|
49
57
|
authoritative. Kill-switches are enforced by `scripts/lib/autopilot.mjs`, not inline by
|
|
@@ -111,7 +119,7 @@ intent for THIS run, not a standing policy.
|
|
|
111
119
|
## Command Surface
|
|
112
120
|
|
|
113
121
|
```
|
|
114
|
-
/autopilot [--max-sessions=N] [--max-hours=H] [--confidence-threshold=0.X] [--dry-run]
|
|
122
|
+
/autopilot [--max-sessions=N] [--max-hours=H] [--confidence-threshold=0.X] [--max-tokens=N] [--dry-run]
|
|
115
123
|
```
|
|
116
124
|
|
|
117
125
|
| Flag | Default | Bounds | Meaning |
|
|
@@ -119,6 +127,7 @@ intent for THIS run, not a standing policy.
|
|
|
119
127
|
| `--max-sessions` | `5` | 1..50 | Iteration cap (graceful exit when reached) |
|
|
120
128
|
| `--max-hours` | `4.0` | 0.5..24.0 | Wall-clock budget for entire loop |
|
|
121
129
|
| `--confidence-threshold` | `0.85` | 0.0..1.0 | Minimum `selectMode` confidence for auto-execute |
|
|
130
|
+
| `--max-tokens` | `0` (off) | 0..10000000 | Token budget for `token-budget-exceeded`. Unit: cumulative **subagent OUTPUT** tokens, summed from each `sessions.jsonl` record's `total_token_output` (falling back to `total_tokens`, which is subagent-only as well) — coordinator tokens are not counted. Off by default until calibrated: one measured deep session's subagents produced 450 499 output tokens, so a six-figure budget stops the loop after about one deep session |
|
|
122
131
|
| `--dry-run` | `false` | — | Print planned iterations without executing |
|
|
123
132
|
|
|
124
133
|
Out-of-range values silently clamp to bounds. `--dry-run` exits after printing — never
|
|
@@ -136,7 +145,7 @@ WHILE state.iterations_completed < max-sessions:
|
|
|
136
145
|
kill_switch := 'max-sessions-reached'; break
|
|
137
146
|
IF (now() - state.started_at) > max-hours:
|
|
138
147
|
kill_switch := 'max-hours-exceeded'; break
|
|
139
|
-
IF cumulative_tokens_used >= max-tokens:
|
|
148
|
+
IF max-tokens > 0 AND cumulative_tokens_used >= max-tokens:
|
|
140
149
|
kill_switch := 'token-budget-exceeded'; break
|
|
141
150
|
IF resource_verdict() == 'critical' AND peer_count() > autopilot-peer-abort:
|
|
142
151
|
kill_switch := 'resource-overload'; break
|
|
@@ -222,7 +231,7 @@ session — drives `runLoop` between manual `/session` invocations. The headless
|
|
|
222
231
|
| Field | Signature | Source |
|
|
223
232
|
|---|---|---|
|
|
224
233
|
| `modeSelector` | `() => Promise<{mode, confidence, rationale?}>` | wraps `selectMode(await buildLiveSignals())` |
|
|
225
|
-
| `sessionRunner` | `({mode, autopilotRunId}) => Promise<{session_id, agent_summary?, effectiveness?}>` | wraps a `/session <mode>` invocation; reads `
|
|
234
|
+
| `sessionRunner` | `({mode, autopilotRunId}) => Promise<{session_id, agent_summary?, effectiveness?}>` | wraps a `/session <mode>` invocation; reads the child's own record (matched on `raw_session_id`) to construct return value |
|
|
226
235
|
| `resourceEvaluator` | `() => {verdict}` | calls `evaluate(cachedProbeSnapshot, thresholds)` from `resource-probe.mjs` over a snapshot `peerCounter` refreshed on the prior iteration — never calls `probe()` itself, which is what keeps it synchronous |
|
|
227
236
|
| `peerCounter` | `() => Promise<number>` | returns `peers.length` from `detectPeers({ sessionId, freshnessMin: 15 })` (a SESSION count, not a process count — see `host-resources.md` HR-103) while refreshing the cached `probe()` snapshot `resourceEvaluator` reads |
|
|
228
237
|
|
|
@@ -235,6 +244,7 @@ import { runLoop, parseFlags } from '$PLUGIN_ROOT/scripts/lib/autopilot.mjs';
|
|
|
235
244
|
import { buildLiveSignals } from '$PLUGIN_ROOT/scripts/lib/build-live-signals.mjs';
|
|
236
245
|
import { selectMode } from '$PLUGIN_ROOT/scripts/lib/mode-selector.mjs';
|
|
237
246
|
import { probe, evaluate } from '$PLUGIN_ROOT/scripts/lib/resource-probe.mjs';
|
|
247
|
+
import { detectPeers } from '$PLUGIN_ROOT/scripts/lib/session-registry.mjs';
|
|
238
248
|
|
|
239
249
|
const flags = parseFlags(process.argv.slice(2));
|
|
240
250
|
|
|
@@ -250,20 +260,37 @@ const modeSelector = async () => {
|
|
|
250
260
|
return selectMode(signals);
|
|
251
261
|
};
|
|
252
262
|
|
|
263
|
+
let cachedProbeSnapshot = null; // written by peerCounter, read by resourceEvaluator
|
|
264
|
+
|
|
253
265
|
const resourceEvaluator = () => {
|
|
254
|
-
|
|
255
|
-
|
|
266
|
+
// Synchronous by contract: never calls probe() itself (it is async) — reads
|
|
267
|
+
// the snapshot peerCounter refreshed on the prior iteration.
|
|
268
|
+
if (cachedProbeSnapshot === null) {
|
|
269
|
+
return { verdict: 'warn', reasons: ['probe not yet available'], recommended_agents_per_wave_cap: null };
|
|
270
|
+
}
|
|
271
|
+
return evaluate(cachedProbeSnapshot, thresholds);
|
|
256
272
|
};
|
|
257
273
|
|
|
258
|
-
const peerCounter = () => {
|
|
259
|
-
//
|
|
260
|
-
|
|
274
|
+
const peerCounter = async () => {
|
|
275
|
+
// A SESSION count, not a process count (host-resources.md HR-103) —
|
|
276
|
+
// claude_processes_count runs ~6 processes per session. `ownSessionId` is
|
|
277
|
+
// this coordinator's registry id, so detectPeers() excludes it.
|
|
278
|
+
const [peers, snapshot] = await Promise.all([
|
|
279
|
+
detectPeers({ sessionId: ownSessionId, freshnessMin: 15 }),
|
|
280
|
+
probe(),
|
|
281
|
+
]);
|
|
282
|
+
cachedProbeSnapshot = snapshot;
|
|
283
|
+
return peers.length;
|
|
261
284
|
};
|
|
262
285
|
|
|
263
286
|
const sessionRunner = async ({ mode, autopilotRunId }) => {
|
|
264
287
|
// The coordinator (Claude) invokes /session <mode> manually here. After the
|
|
265
288
|
// session completes (/close runs, sessions.jsonl appended), this function
|
|
266
289
|
// reads the tail entry and projects it into the runLoop return-shape.
|
|
290
|
+
// CAUTION: a tail read has the peer-append error class — a parallel session
|
|
291
|
+
// that appends after this one supplies ITS record (and token usage). A real
|
|
292
|
+
// run should read its own record by raw session id, as scripts/autopilot.mjs
|
|
293
|
+
// does (readOwnSession → raw_session_id match, #1457).
|
|
267
294
|
const tail = readSessionsJsonlTail(1); // last line, normalized
|
|
268
295
|
return {
|
|
269
296
|
session_id: tail.session_id,
|
|
@@ -289,8 +316,9 @@ The in-process driver has Claude (the coordinator) call `/session <mode>` betwee
|
|
|
289
316
|
- **Pro:** zero new infra. Reuses canonical kill-switch logic. Validates `buildLiveSignals`
|
|
290
317
|
against real Phase 7.5 swap before headless complexity. Each iteration carries
|
|
291
318
|
inter-session memory through STATE.md / sessions.jsonl / learnings.
|
|
292
|
-
- **Con:** not truly autonomous — Claude must stay in the chat.
|
|
293
|
-
walk-away UX
|
|
319
|
+
- **Con:** not truly autonomous — Claude must stay in the chat. The in-process
|
|
320
|
+
driver does not deliver walk-away UX; that is the shipped headless driver
|
|
321
|
+
(`--headless`, `scripts/autopilot.mjs`, Phase C-5; see § Headless Driver Wiring).
|
|
294
322
|
|
|
295
323
|
### Headless Driver Wiring (Option A — `scripts/autopilot.mjs`)
|
|
296
324
|
|
|
@@ -299,9 +327,10 @@ four required `runLoop` dependencies (`modeSelector`, `sessionRunner`,
|
|
|
299
327
|
`resourceEvaluator`, `peerCounter`) plus the optional `abortSignal` to production
|
|
300
328
|
sources — distinct from, and more concrete than, the in-process skeleton above:
|
|
301
329
|
|
|
302
|
-
- `sessionRunner` — spawns `claude -p '/session <mode>'
|
|
303
|
-
exits cleanly, reads the `sessions.jsonl`
|
|
304
|
-
`
|
|
330
|
+
- `sessionRunner` — spawns `claude -p '/session <mode>' --session-id <uuid>` as a child
|
|
331
|
+
process; after it exits cleanly, reads the one canonical `sessions.jsonl` record whose
|
|
332
|
+
`raw_session_id` is that uuid to construct the return shape
|
|
333
|
+
`{session_id, agent_summary?, effectiveness?, usage?}` (`scripts/autopilot.mjs` `sessionRunner`).
|
|
305
334
|
- `resourceEvaluator` — calls `evaluate(cachedProbeSnapshot, thresholds)` from
|
|
306
335
|
`scripts/lib/resource-probe.mjs`, reading a snapshot refreshed by `peerCounter` on the
|
|
307
336
|
prior iteration so the function itself stays synchronous, per the `runLoop` contract
|
|
@@ -94,7 +94,7 @@ Store `INVOCATION_MODE = transitive | direct`.
|
|
|
94
94
|
|
|
95
95
|
- `private`: the existing host-local config resolution found a baseline directory and its reduced contract validated. Use `private-contract.md` for selection, templates, commands, CI and rules.
|
|
96
96
|
- `public`: the resolved baseline is absent, empty, or points to a missing directory. Use plugin-bundled templates.
|
|
97
|
-
- Existing but invalid configured baseline: abort before dispatch; report the reader's sanitized error reason.
|
|
97
|
+
- Existing but invalid configured baseline: abort before dispatch; report the reader's sanitized error reason; for `producer-missing` also surface the `message` and the migrate-or-unconfigure choice (see `public-fallback.md` § Step 1).
|
|
98
98
|
|
|
99
99
|
Pass `PATH_TYPE` into Phase 1 and all subsequent phases. All tier templates (`fast-template.md`, `standard-template.md`, `deep-template.md`) must consult `public-fallback.md` for CLAUDE.md generation and archetype file sourcing when `PATH_TYPE = public`.
|
|
100
100
|
|
|
@@ -17,7 +17,7 @@ Vendor the canonical always-on rules from the plugin's `rules/` library into `$R
|
|
|
17
17
|
|
|
18
18
|
Idempotency is handled by the writer itself:
|
|
19
19
|
- Missing → create
|
|
20
|
-
- Exists, plugin-owned (
|
|
20
|
+
- Exists, plugin-owned (the `<!-- source: session-orchestrator plugin ... -->` header is on line 1, or is the first line after a line-1 frontmatter's closing `---` — `isPluginOwnedContent()`, #1449) and byte-identical → skip silently
|
|
21
21
|
- Exists, plugin-owned and stale → overwrite (the plugin copy is canonical)
|
|
22
22
|
- Exists WITHOUT that header → preserved untouched (a repo-private rule the operator authored)
|
|
23
23
|
|