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
|
@@ -2,21 +2,39 @@
|
|
|
2
2
|
* autopilot/stall-sampler.mjs — Stateless progress sampler for STALL_TIMEOUT
|
|
3
3
|
* kill-switch (ADR-364, issue #371).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* autopilot loop writes one record per session atomically (tmp+rename), so the
|
|
7
|
-
* file mtime advances exactly when the loop makes progress. No false-positive
|
|
8
|
-
* churn from in-place writes, no need to parse JSON, microsecond precision.
|
|
5
|
+
* PROGRESS MARKER PRECEDENCE (HR-102: a better signal REPLACES a worse one).
|
|
9
6
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* 1. `session.lock` `last_heartbeat` (schema v2) — advances DURING a run:
|
|
8
|
+
* `hooks/on-stop.mjs` refreshes it at every turn-end and
|
|
9
|
+
* `hooks/post-tool-batch-wave-signal.mjs` at every tool batch.
|
|
10
|
+
* 2. `autopilot.jsonl` mtime — the legacy marker, used only when no lock path
|
|
11
|
+
* is supplied or the lock is absent/corrupt/timestamp-less.
|
|
12
|
+
*
|
|
13
|
+
* The header of this module used to claim `autopilot.jsonl` carries "one record
|
|
14
|
+
* per session". It does not: `telemetry.mjs` writes ONE record per /autopilot
|
|
15
|
+
* INVOCATION, and `loop.mjs` calls it exactly twice — once for the dry-run
|
|
16
|
+
* preview and once AFTER the `for(;;)` loop. So during a real run the mtime the
|
|
17
|
+
* sampler read belonged to the PREVIOUS autopilot run, typically hours or days
|
|
18
|
+
* old, and the post-session check fired STALL_TIMEOUT after iteration 1 every
|
|
19
|
+
* time. The append-once contract is correct and stays; the marker was wrong.
|
|
20
|
+
*
|
|
21
|
+
* CEILING (BV-004). The heartbeat only advances while some live session owns the
|
|
22
|
+
* lock: `updateHeartbeat()` refuses on a session_id mismatch, and a child
|
|
23
|
+
* `claude -p` spawned while a parent session already holds the lock never
|
|
24
|
+
* acquires one (`hooks/_lib/lock-bootstrap.mjs` bails on `reason: 'active'`).
|
|
25
|
+
* In that one invocation shape — the headless driver started FROM a chat
|
|
26
|
+
* session rather than from a bare shell — the heartbeat freezes and the check
|
|
27
|
+
* degrades to today's behaviour. Revisit if STALL_TIMEOUT is ever observed
|
|
28
|
+
* firing on a run whose child session did real work.
|
|
29
|
+
*
|
|
30
|
+
* Stateless — at most two sync reads per invocation, no side effects, no async.
|
|
13
31
|
*
|
|
14
32
|
* Exports:
|
|
15
33
|
* SAMPLE_CADENCE_MS — shared constant (30_000) defining the "fresh" window
|
|
16
34
|
* sampleProgress(opts) — returns progress descriptor; never throws
|
|
17
35
|
*/
|
|
18
36
|
|
|
19
|
-
import { statSync } from 'node:fs';
|
|
37
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
20
38
|
|
|
21
39
|
// ---------------------------------------------------------------------------
|
|
22
40
|
// Constants
|
|
@@ -32,9 +50,40 @@ export const SAMPLE_CADENCE_MS = 30_000;
|
|
|
32
50
|
const DEFAULT_AUTOPILOT_JSONL = '.orchestrator/metrics/autopilot.jsonl';
|
|
33
51
|
const DEFAULT_STALL_TIMEOUT_SECONDS = 600;
|
|
34
52
|
const MARKER_SUCCESS = 'autopilot.jsonl:mtime';
|
|
53
|
+
const MARKER_HEARTBEAT = 'session.lock:last_heartbeat';
|
|
35
54
|
const MARKER_MISSING = 'missing';
|
|
36
55
|
const MARKER_INVALID = 'invalid';
|
|
37
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Read the live heartbeat timestamp (ms) out of `session.lock`.
|
|
59
|
+
*
|
|
60
|
+
* Returns `null` — meaning "fall back to the mtime marker" — for every failure
|
|
61
|
+
* mode: no path supplied, file absent, unreadable, not JSON, or carrying no
|
|
62
|
+
* parsable timestamp. A missing measurement is NOT a zero here; conflating the
|
|
63
|
+
* two would report a stall of `now` seconds the moment the lock is unreadable.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} [sessionLockPath]
|
|
66
|
+
* @returns {number | null}
|
|
67
|
+
*/
|
|
68
|
+
function readHeartbeatMs(sessionLockPath) {
|
|
69
|
+
if (typeof sessionLockPath !== 'string' || sessionLockPath.length === 0) return null;
|
|
70
|
+
let lock;
|
|
71
|
+
try {
|
|
72
|
+
lock = JSON.parse(readFileSync(sessionLockPath, 'utf8'));
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (typeof lock !== 'object' || lock === null) return null;
|
|
77
|
+
// Same precedence `session-lock.mjs` uses on read: a v1 lock has no
|
|
78
|
+
// `last_heartbeat`, and its `started_at` is the best available stand-in.
|
|
79
|
+
const raw = typeof lock.last_heartbeat === 'string' && lock.last_heartbeat.length > 0
|
|
80
|
+
? lock.last_heartbeat
|
|
81
|
+
: lock.started_at;
|
|
82
|
+
if (typeof raw !== 'string' || raw.length === 0) return null;
|
|
83
|
+
const ms = Date.parse(raw);
|
|
84
|
+
return Number.isFinite(ms) ? ms : null;
|
|
85
|
+
}
|
|
86
|
+
|
|
38
87
|
// ---------------------------------------------------------------------------
|
|
39
88
|
// Progress sampler
|
|
40
89
|
// ---------------------------------------------------------------------------
|
|
@@ -45,6 +94,10 @@ const MARKER_INVALID = 'invalid';
|
|
|
45
94
|
* @param {object} [opts]
|
|
46
95
|
* @param {string} [opts.autopilotJsonlPath] — path to autopilot.jsonl (default
|
|
47
96
|
* '.orchestrator/metrics/autopilot.jsonl').
|
|
97
|
+
* @param {string} [opts.sessionLockPath] — path to `session.lock`. When supplied
|
|
98
|
+
* and readable, its `last_heartbeat` (falling back to `started_at`, the schema
|
|
99
|
+
* v1 normalisation `session-lock.mjs` applies on read) REPLACES the mtime
|
|
100
|
+
* marker. Omitted → mtime only, which is what every pre-existing caller gets.
|
|
48
101
|
* @param {number} [opts.stallTimeoutSeconds] — kill-switch threshold (default
|
|
49
102
|
* 600). NOT range-clamped here; caller is responsible for bounds.
|
|
50
103
|
* @param {() => number} [opts.nowMs] — wall-clock supplier (default Date.now).
|
|
@@ -66,22 +119,26 @@ export function sampleProgress(opts = {}) {
|
|
|
66
119
|
void _stallTimeoutSeconds;
|
|
67
120
|
const nowMs = typeof opts.nowMs === 'function' ? opts.nowMs : Date.now;
|
|
68
121
|
|
|
69
|
-
let
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
122
|
+
let markerMs = readHeartbeatMs(opts.sessionLockPath);
|
|
123
|
+
let markerName = MARKER_HEARTBEAT;
|
|
124
|
+
|
|
125
|
+
if (markerMs === null) {
|
|
126
|
+
markerName = MARKER_SUCCESS;
|
|
127
|
+
try {
|
|
128
|
+
markerMs = statSync(autopilotJsonlPath).mtimeMs;
|
|
129
|
+
} catch (err) {
|
|
130
|
+
const marker = err && err.code === 'ENOENT' ? MARKER_MISSING : MARKER_INVALID;
|
|
131
|
+
return {
|
|
132
|
+
progressed: false,
|
|
133
|
+
lastMarker: null,
|
|
134
|
+
stallSeconds: 0,
|
|
135
|
+
marker,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
81
138
|
}
|
|
82
139
|
|
|
83
140
|
const now = nowMs();
|
|
84
|
-
const deltaMs = now -
|
|
141
|
+
const deltaMs = now - markerMs;
|
|
85
142
|
// Clamp negative deltas (clock skew, file mtime in the future) to 0.
|
|
86
143
|
const stallSeconds = Math.max(0, Math.round(deltaMs / 1000));
|
|
87
144
|
// Fresh if within the sample cadence window (also covers the clock-skew
|
|
@@ -90,8 +147,8 @@ export function sampleProgress(opts = {}) {
|
|
|
90
147
|
|
|
91
148
|
return {
|
|
92
149
|
progressed,
|
|
93
|
-
lastMarker:
|
|
150
|
+
lastMarker: markerMs,
|
|
94
151
|
stallSeconds,
|
|
95
|
-
marker:
|
|
152
|
+
marker: markerName,
|
|
96
153
|
};
|
|
97
154
|
}
|
|
@@ -19,10 +19,11 @@ const BASENAME = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*\.md$/;
|
|
|
19
19
|
const unique = (items) => [...new Set(items)].sort();
|
|
20
20
|
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
21
21
|
|
|
22
|
+
/** `message` must never interpolate a baseline root or any other host path. */
|
|
22
23
|
export class BaselineContractError extends Error {
|
|
23
|
-
constructor(reason
|
|
24
|
+
constructor(reason, message = `Baseline archetype lookup failed (${reason}).`) { super(message); this.name = 'BaselineContractError'; this.reason = reason; }
|
|
24
25
|
}
|
|
25
|
-
function fail(reason = 'invalid-contract') { throw new BaselineContractError(reason); }
|
|
26
|
+
function fail(reason = 'invalid-contract', message) { throw new BaselineContractError(reason, message); }
|
|
26
27
|
function check(condition) { if (!condition) fail(); }
|
|
27
28
|
function shape(value, required, optional = []) {
|
|
28
29
|
check(object(value) && required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => [...required, ...optional].includes(key)));
|
|
@@ -122,24 +123,38 @@ process.stdout.write(JSON.stringify(resolveConfiguredBaselinePath(JSON.parse(rea
|
|
|
122
123
|
return realpathSync(root);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
/** Resolve a canonical relative source and reject symlinks at every component.
|
|
126
|
-
|
|
126
|
+
/** Resolve a canonical relative source and reject symlinks at every component.
|
|
127
|
+
* Only an ENOENT thrown by the per-component `lstatSync` itself maps to
|
|
128
|
+
* `missingReason`; every other failure is `unsafe-source`. Existence is never
|
|
129
|
+
* probed with a link-following call (existsSync/statSync/accessSync/realpathSync):
|
|
130
|
+
* a dangling symlink would then read as "missing" instead of `unsafe-source`.
|
|
131
|
+
*/
|
|
132
|
+
export function baselineSourcePath(root, source, directory = false, { missingReason = 'unsafe-source' } = {}) {
|
|
127
133
|
relative(source);
|
|
134
|
+
// Resolved first: a vanished root is unsafe, never a missing source.
|
|
135
|
+
let realRoot;
|
|
136
|
+
try { realRoot = realpathSync(root); } catch { fail('unsafe-source'); }
|
|
128
137
|
let current = root;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
let stat;
|
|
139
|
+
for (const component of source.split('/')) {
|
|
140
|
+
current = path.join(current, component);
|
|
141
|
+
try { stat = lstatSync(current); } catch (error) { fail(error?.code === 'ENOENT' ? missingReason : 'unsafe-source'); }
|
|
142
|
+
if (stat.isSymbolicLink()) fail('unsafe-source');
|
|
143
|
+
}
|
|
144
|
+
if (directory ? !stat.isDirectory() : !stat.isFile()) fail('unsafe-source');
|
|
145
|
+
let real;
|
|
146
|
+
try { real = realpathSync(current); } catch { fail('unsafe-source'); }
|
|
147
|
+
if (!real.startsWith(`${realRoot}${path.sep}`)) fail('unsafe-source');
|
|
148
|
+
return current;
|
|
139
149
|
}
|
|
140
150
|
|
|
151
|
+
const PRODUCER = 'scripts/archetype-manifest.mjs';
|
|
141
152
|
function projection(root, args, { timeoutMs = 5000, maxBuffer = MAX_BYTES } = {}) {
|
|
142
|
-
|
|
153
|
+
let script;
|
|
154
|
+
try { script = baselineSourcePath(root, PRODUCER, false, { missingReason: 'producer-missing' }); } catch (error) {
|
|
155
|
+
if (error?.reason !== 'producer-missing') throw error;
|
|
156
|
+
fail('producer-missing', `Baseline archetype lookup failed (producer-missing): the configured baseline has no ${PRODUCER} exporter — see docs/baseline.md § How bootstrap finds it.`);
|
|
157
|
+
}
|
|
143
158
|
const result = spawnSync(process.execPath, [script, ...args], {
|
|
144
159
|
cwd: root, encoding: 'utf8', timeout: Math.min(timeoutMs, 5000), maxBuffer: Math.min(maxBuffer, MAX_BYTES),
|
|
145
160
|
shell: false, killSignal: 'SIGKILL', stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -195,7 +210,8 @@ export async function loadBaselineArchetypes(options = {}) {
|
|
|
195
210
|
let manifest;
|
|
196
211
|
try { manifest = validateBaselineContract(JSON.parse(projection(root, ['export'], options))); }
|
|
197
212
|
catch (error) { if (error instanceof BaselineContractError) throw error; fail(); }
|
|
198
|
-
|
|
213
|
+
// An absent declared source is an incomplete baseline, not a security refusal (#1447 3a).
|
|
214
|
+
for (const item of manifest.archetypes) baselineSourcePath(root, item.templatePath, true, { missingReason: 'invalid-contract' });
|
|
199
215
|
const facts = collectFacts(repoRoot);
|
|
200
216
|
const ordered = [...manifest.archetypes].sort((a, b) => a.order - b.order);
|
|
201
217
|
const archetypes = ordered.map(({ id, order, runtimes, packageManagers, ui, api, deploy }) => ({ id, order, runtimes, packageManagers, ui, api, deploy }));
|
|
@@ -220,7 +236,7 @@ export async function loadBaselineArchetypes(options = {}) {
|
|
|
220
236
|
if (!ruleTargets.includes(name) || seen.has(name)) fail('invalid-rule-projection');
|
|
221
237
|
seen.add(name);
|
|
222
238
|
if (owned.includes(name)) continue;
|
|
223
|
-
baselineSourcePath(root, source);
|
|
239
|
+
baselineSourcePath(root, source, false, { missingReason: 'invalid-rule-projection' });
|
|
224
240
|
baselineRules.push({ source, target: `.claude/rules/${name}` });
|
|
225
241
|
}
|
|
226
242
|
if (ruleTargets.some((name) => !seen.has(name))) fail('invalid-rule-projection');
|
|
@@ -230,7 +246,9 @@ export async function loadBaselineArchetypes(options = {}) {
|
|
|
230
246
|
pluginRuleTargets: ruleTargets.filter((name) => owned.includes(name)), baselineRules,
|
|
231
247
|
} };
|
|
232
248
|
} catch (error) {
|
|
233
|
-
|
|
249
|
+
// Only a BaselineContractError message is path-free by construction; others stay opaque.
|
|
250
|
+
const contract = error instanceof BaselineContractError;
|
|
251
|
+
return { status: 'error', reason: contract ? error.reason : 'lookup-failed', ...(contract && { message: error.message }), archetypes: [], selected: null };
|
|
234
252
|
}
|
|
235
253
|
}
|
|
236
254
|
|
|
@@ -290,11 +308,12 @@ function applyCopies(plan) {
|
|
|
290
308
|
return { status: 'applied', created, preserved };
|
|
291
309
|
}
|
|
292
310
|
function applyFailure(error) {
|
|
293
|
-
|
|
311
|
+
const contract = error instanceof BaselineContractError;
|
|
312
|
+
return { status: 'error', reason: contract ? error.reason : 'apply-failed', ...(contract && { message: error.message }), created: [], preserved: [] };
|
|
294
313
|
}
|
|
295
314
|
async function selectedContext(options) {
|
|
296
315
|
const result = await loadBaselineArchetypes(options);
|
|
297
|
-
if (result.status !== 'private' || !result.selected) fail(result.reason);
|
|
316
|
+
if (result.status !== 'private' || !result.selected) fail(result.reason, result.message);
|
|
298
317
|
const root = await resolveBaselineLocation(options);
|
|
299
318
|
if (!root) fail('baseline-unavailable');
|
|
300
319
|
return { root, selected: result.selected };
|
|
@@ -340,7 +359,7 @@ export async function scaffoldBaselineArchetype(options = {}) {
|
|
|
340
359
|
const { repoRoot = process.cwd(), projectName } = options;
|
|
341
360
|
if (typeof projectName !== 'string' || !ID.test(projectName)) fail('invalid-project-name');
|
|
342
361
|
const { root, selected } = await selectedContext(options);
|
|
343
|
-
const template = baselineSourcePath(root, selected.templatePath, true);
|
|
362
|
+
const template = baselineSourcePath(root, selected.templatePath, true, { missingReason: 'invalid-contract' });
|
|
344
363
|
sourceFiles(template);
|
|
345
364
|
const shared = baselineSourcePath(root, 'templates/shared', true);
|
|
346
365
|
sourceFiles(shared);
|
|
@@ -401,7 +420,7 @@ export async function syncBootstrapRules(options = {}) {
|
|
|
401
420
|
// ordinary plugin rules, just as its minimal scaffold does.
|
|
402
421
|
const contract = options.minimal ? { status: 'public', selected: null }
|
|
403
422
|
: await loadBaselineArchetypes({ ...options, repoRoot, pluginRoot, archetype });
|
|
404
|
-
if (contract.status === 'error') fail(contract.reason);
|
|
423
|
+
if (contract.status === 'error') fail(contract.reason, contract.message);
|
|
405
424
|
if (contract.status === 'private' && !contract.selected && !hasUnselectedFastLock(repoRoot)) fail(contract.reason);
|
|
406
425
|
const before = new Set();
|
|
407
426
|
for (const name of pluginRuleTargets(pluginRoot)) {
|