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
|
@@ -18,7 +18,11 @@
|
|
|
18
18
|
* over the target (atomic), and the result is then re-verified against BOTH
|
|
19
19
|
* `validateSession` and `checkSessionsIntegrity`. A failed verification restores
|
|
20
20
|
* the backup byte-identically and exits 3 — the ledger is never left in a state
|
|
21
|
-
* worse than the one this CLI found.
|
|
21
|
+
* worse than the one this CLI found. Records with no defensible repair (a
|
|
22
|
+
* timestamp that is not ISO-8601 at all, a waves entry that is not an object)
|
|
23
|
+
* are kept byte-identical and do NOT trigger that rollback (#1442): the repair
|
|
24
|
+
* of every other line is kept, and the run exits 4 so a caller can tell "clean"
|
|
25
|
+
* from "clean except N lines nobody can repair".
|
|
22
26
|
*
|
|
23
27
|
* TARGET CONSTRAINT (MED-3): `--file` MUST resolve inside
|
|
24
28
|
* `<repo-root>/.orchestrator/metrics/`. Any target outside it — including a
|
|
@@ -32,6 +36,10 @@
|
|
|
32
36
|
* 1 — user/input error (bad flag, unknown argument)
|
|
33
37
|
* 2 — system error (unreadable/unwritable ledger, I/O failure)
|
|
34
38
|
* 3 — post-verification failed; the backup was restored and nothing was kept
|
|
39
|
+
* 4 — completed, but N unrepairable lines remain (apply: every repairable
|
|
40
|
+
* line was fixed and verified, the N were kept byte-identical; dry-run:
|
|
41
|
+
* the N lines that WOULD remain are listed). Checked after 3: a
|
|
42
|
+
* rolled-back run is always 3, never 4.
|
|
35
43
|
*/
|
|
36
44
|
|
|
37
45
|
import fs from 'node:fs';
|
|
@@ -53,7 +61,9 @@ const USAGE =
|
|
|
53
61
|
');\n' +
|
|
54
62
|
' must resolve inside <repo-root>/.orchestrator/metrics/\n' +
|
|
55
63
|
' --repo-root project root (default: resolved project dir)\n' +
|
|
56
|
-
'Exit codes: 0 completed, 1 arg error, 2 system error, 3 post-verification failed\n'
|
|
64
|
+
'Exit codes: 0 completed, 1 arg error, 2 system error, 3 post-verification failed\n' +
|
|
65
|
+
' (backup restored), 4 unrepairable remain (N lines kept byte-identical;\n' +
|
|
66
|
+
' every repairable line fixed — dry-run: would remain)\n';
|
|
57
67
|
|
|
58
68
|
/**
|
|
59
69
|
* Resolve `--file` and REFUSE any target outside
|
|
@@ -127,7 +137,10 @@ export function renderHuman(s) {
|
|
|
127
137
|
}
|
|
128
138
|
if (s.backup_path) lines.push(` backup: ${s.backup_path}`);
|
|
129
139
|
if (s.errors.length > 0) {
|
|
130
|
-
|
|
140
|
+
// #1442: name every line that stays invalid — in dry-run BEFORE anything is
|
|
141
|
+
// written, so the operator knows the remainder --apply will leave behind.
|
|
142
|
+
const verb = s.mode === 'apply' ? 'remain' : 'would remain';
|
|
143
|
+
lines.push(` unrepairable: ${s.errors.length} (${verb} invalid; original line kept byte-identical)`);
|
|
131
144
|
for (const e of s.errors) lines.push(` line ${e.line} ${e.session_id ?? '<no session_id>'}: ${e.error}`);
|
|
132
145
|
}
|
|
133
146
|
if (s.post_verify && s.post_verify.integrity !== 'clean' && s.post_verify.integrity !== 'skipped-not-canonical-path') {
|
|
@@ -135,10 +148,30 @@ export function renderHuman(s) {
|
|
|
135
148
|
}
|
|
136
149
|
if (s.ok === false) {
|
|
137
150
|
lines.push(' POST-VERIFICATION FAILED — backup restored, ledger unchanged.');
|
|
151
|
+
} else if (s.errors.length > 0) {
|
|
152
|
+
lines.push(
|
|
153
|
+
s.mode === 'apply'
|
|
154
|
+
? ` Repairable lines fixed and verified; ${s.errors.length} unrepairable line(s) left as they were (exit 4).`
|
|
155
|
+
: ` --apply would fix every repairable line and leave ${s.errors.length} unrepairable line(s) as they are (exit 4).`
|
|
156
|
+
);
|
|
138
157
|
}
|
|
139
158
|
return lines.join('\n') + '\n';
|
|
140
159
|
}
|
|
141
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Map a `repairLedger` summary to the exit-code contract in the header.
|
|
163
|
+
* Rollback (3) wins over an unrepairable remainder (4): a restored ledger kept
|
|
164
|
+
* nothing, so "N remain" would describe a write that did not happen.
|
|
165
|
+
*
|
|
166
|
+
* @param {object} summary
|
|
167
|
+
* @returns {0|3|4}
|
|
168
|
+
*/
|
|
169
|
+
export function exitCodeFor(summary) {
|
|
170
|
+
if (summary.ok === false) return 3;
|
|
171
|
+
if (summary.unrepairable > 0) return 4;
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
142
175
|
async function main() {
|
|
143
176
|
let parsed;
|
|
144
177
|
try {
|
|
@@ -197,7 +230,7 @@ async function main() {
|
|
|
197
230
|
} else {
|
|
198
231
|
process.stdout.write(renderHuman(summary));
|
|
199
232
|
}
|
|
200
|
-
process.exit(summary
|
|
233
|
+
process.exit(exitCodeFor(summary));
|
|
201
234
|
}
|
|
202
235
|
|
|
203
236
|
const isDirectRun =isMainModule(import.meta.url);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Stdin-only boundary for commands/session.md; never executes task context. */
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { parseArgs } from 'node:util';
|
|
5
|
+
import { resolveSessionInvocation } from './lib/session-invocation.mjs';
|
|
6
|
+
|
|
7
|
+
const HELP = `Usage: node scripts/resolve-session-invocation.mjs [--json] < arguments.txt
|
|
8
|
+
|
|
9
|
+
Read the complete /session argument text from UTF-8 stdin.
|
|
10
|
+
Resolve the leading housekeeping, feature, deep or ultradeep token; preserve
|
|
11
|
+
the rest as task context. Empty input defaults to deep. An invalid mode emits
|
|
12
|
+
a warning and resolves to deep, as the session command has always specified.
|
|
13
|
+
|
|
14
|
+
--json Emit one JSON object instead of a human-readable summary
|
|
15
|
+
--help Show this help
|
|
16
|
+
--version Show the plugin version
|
|
17
|
+
|
|
18
|
+
Example: node scripts/resolve-session-invocation.mjs --json < arguments.txt
|
|
19
|
+
Write arguments.txt with a file tool; do not interpolate user text into a shell.
|
|
20
|
+
Exit codes: 0 resolved (including fallback), 1 bad CLI arguments, 2 stdin I/O error
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
let options;
|
|
24
|
+
try {
|
|
25
|
+
options = parseArgs({
|
|
26
|
+
options: { json: { type: 'boolean' }, help: { type: 'boolean' }, version: { type: 'boolean' } },
|
|
27
|
+
allowPositionals: false,
|
|
28
|
+
}).values;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
process.stderr.write(`session-invocation: ${error.message}\n`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (options.help) {
|
|
35
|
+
process.stdout.write(HELP);
|
|
36
|
+
} else if (options.version) {
|
|
37
|
+
process.stdout.write(
|
|
38
|
+
`${JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version}\n`,
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
let input;
|
|
42
|
+
try {
|
|
43
|
+
input = readFileSync(0, 'utf8');
|
|
44
|
+
} catch {
|
|
45
|
+
process.stderr.write('session-invocation: could not read UTF-8 stdin\n');
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
const resolved = resolveSessionInvocation(input);
|
|
49
|
+
if (resolved.invalidMode !== undefined) {
|
|
50
|
+
process.stderr.write(
|
|
51
|
+
`Invalid session type '${resolved.invalidMode}'. Valid types: housekeeping, feature, deep (alias: ultradeep). Falling back to deep.\n`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
process.stdout.write(
|
|
55
|
+
options.json
|
|
56
|
+
? `${JSON.stringify(resolved)}\n`
|
|
57
|
+
: `Session type: ${resolved.sessionType}${resolved.profile ? ` (profile: ${resolved.profile})` : ''}\nTask context: ${resolved.context}\n`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* run-migrate-v2-cross-repo.mjs — cross-repo Migrate-CLI v2 runner.
|
|
4
4
|
*
|
|
5
5
|
* Walks a list of repos, applies the v2 migration to each repo's learnings.jsonl,
|
|
6
|
-
* and reports pre/post invalid-rate per repo
|
|
6
|
+
* and reports pre/post invalid-rate per repo — plus, per repo and in the
|
|
7
|
+
* aggregate, the count of invalid records per validation error class before and
|
|
8
|
+
* after migration (`errorClassesPre` / `errorClassesPost`, GitHub #69 / GitLab
|
|
9
|
+
* #1446). An error class is the validateLearning message up to `, got:`
|
|
10
|
+
* (e.g. `scope must be one of local|private|public`), so a dry run shows which
|
|
11
|
+
* failure kinds the migration fixes and which remain.
|
|
7
12
|
*
|
|
8
13
|
* Usage:
|
|
9
14
|
* node scripts/run-migrate-v2-cross-repo.mjs [--repos <comma-list>] [--apply] [--json] [--out <path>]
|
|
@@ -11,15 +16,20 @@
|
|
|
11
16
|
* Flags:
|
|
12
17
|
* --repos <comma-list> Comma-separated repo paths (absolute or ~-prefixed).
|
|
13
18
|
* When omitted, uses the hardcoded ROLLOUT_REPOS list.
|
|
14
|
-
* --apply Write migrated records back to each file (atomic)
|
|
15
|
-
*
|
|
19
|
+
* --apply Write migrated records back to each file (atomic),
|
|
20
|
+
* under that store's lock (`withLearningsLock`, the
|
|
21
|
+
* `<store>.lock` every learnings writer takes), so a
|
|
22
|
+
* live session appending in that repo is never lost.
|
|
23
|
+
* DEFAULT is dry-run (no writes, no lock).
|
|
16
24
|
* --json Output machine-readable JSON instead of Markdown table.
|
|
17
25
|
* --out <path> Write output to file instead of stdout.
|
|
18
26
|
*
|
|
19
27
|
* Exit codes:
|
|
20
28
|
* 0 Success (including repos with no learnings.jsonl — gracefully skipped)
|
|
21
29
|
* 1 Input/argument error
|
|
22
|
-
* 2 I/O error
|
|
30
|
+
* 2 I/O error — incl. a store lock not acquired under --apply: that repo
|
|
31
|
+
* is left unwritten and reported `status: 'error'`, the run continues
|
|
32
|
+
* with the next repo, and exits 2 at the end
|
|
23
33
|
*/
|
|
24
34
|
|
|
25
35
|
import { existsSync, readFileSync, writeFileSync, copyFileSync, renameSync } from 'node:fs';
|
|
@@ -30,6 +40,7 @@ import {
|
|
|
30
40
|
migrateLegacyLearning,
|
|
31
41
|
validateLearning,
|
|
32
42
|
} from './lib/learnings.mjs';
|
|
43
|
+
import { LearningsLockError, withLearningsLock } from './lib/learnings/io.mjs';
|
|
33
44
|
import { getCrossRepoProjects, getConfinementRoot } from './lib/config/cross-repo.mjs';
|
|
34
45
|
import { validatePathInsideProject } from './lib/path-utils.mjs';
|
|
35
46
|
|
|
@@ -135,47 +146,102 @@ if (reposArg) {
|
|
|
135
146
|
* @property {number} invalidPost - invalid records after migration
|
|
136
147
|
* @property {number} fixedByV2 - records that became valid after migration
|
|
137
148
|
* @property {number} malformed - JSON-parse failures (preserved, not counted in invalid)
|
|
149
|
+
* @property {Record<string, number>} errorClassesPre - invalid-pre count per error class
|
|
150
|
+
* @property {Record<string, number>} errorClassesPost - invalid-post count per error class
|
|
138
151
|
* @property {string|null} error - error message if status=error
|
|
139
152
|
*/
|
|
140
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Reduce a validateLearning error message to its class: the text before the
|
|
156
|
+
* record-specific `, got: <value>` tail. Messages without that tail (e.g.
|
|
157
|
+
* `learning missing required field: subject`) are their own class.
|
|
158
|
+
*
|
|
159
|
+
* @param {unknown} err
|
|
160
|
+
* @returns {string}
|
|
161
|
+
*/
|
|
162
|
+
function errorClassOf(err) {
|
|
163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
164
|
+
const idx = message.indexOf(', got:');
|
|
165
|
+
return idx === -1 ? message : message.slice(0, idx);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {Record<string, number>} counts
|
|
170
|
+
* @param {string} cls
|
|
171
|
+
*/
|
|
172
|
+
function bump(counts, cls) {
|
|
173
|
+
counts[cls] = (counts[cls] ?? 0) + 1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* A RepoResult that counted nothing.
|
|
178
|
+
*
|
|
179
|
+
* @param {string} repoPath
|
|
180
|
+
* @param {string} status
|
|
181
|
+
* @param {string|null} error
|
|
182
|
+
* @returns {RepoResult}
|
|
183
|
+
*/
|
|
184
|
+
function emptyResult(repoPath, status, error) {
|
|
185
|
+
return {
|
|
186
|
+
repo: repoPath,
|
|
187
|
+
status,
|
|
188
|
+
total: 0,
|
|
189
|
+
invalidPre: 0,
|
|
190
|
+
invalidPost: 0,
|
|
191
|
+
fixedByV2: 0,
|
|
192
|
+
malformed: 0,
|
|
193
|
+
errorClassesPre: {},
|
|
194
|
+
errorClassesPost: {},
|
|
195
|
+
error,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Repos whose store lock was not acquired under --apply (nothing written there). */
|
|
200
|
+
const lockFailedRepos = [];
|
|
201
|
+
|
|
141
202
|
/**
|
|
142
203
|
* Process a single repo. Returns a RepoResult.
|
|
143
204
|
*
|
|
205
|
+
* Under --apply the WHOLE read → backup → rename runs inside the store lock:
|
|
206
|
+
* these are other repos, where a live session may append between this read
|
|
207
|
+
* and the rename — outside the lock that record would be silently replaced.
|
|
208
|
+
* A dry run writes nothing and takes no lock.
|
|
209
|
+
*
|
|
144
210
|
* @param {string} repoPath - resolved absolute path to the repo
|
|
145
211
|
* @param {boolean} apply - whether to write changes back
|
|
146
|
-
* @returns {RepoResult}
|
|
212
|
+
* @returns {Promise<RepoResult>}
|
|
147
213
|
*/
|
|
148
|
-
function processRepo(repoPath, apply) {
|
|
214
|
+
async function processRepo(repoPath, apply) {
|
|
149
215
|
const learningsPath = join(repoPath, LEARNINGS_REL);
|
|
150
216
|
|
|
151
|
-
if (!existsSync(learningsPath))
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
error: null,
|
|
161
|
-
};
|
|
217
|
+
if (!existsSync(learningsPath)) return emptyResult(repoPath, 'skipped', null);
|
|
218
|
+
if (!apply) return migrateStore(repoPath, learningsPath, false);
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
return await withLearningsLock(learningsPath, () => migrateStore(repoPath, learningsPath, true));
|
|
222
|
+
} catch (err) {
|
|
223
|
+
if (!(err instanceof LearningsLockError)) throw err;
|
|
224
|
+
lockFailedRepos.push(repoPath);
|
|
225
|
+
return emptyResult(repoPath, 'error', err.message);
|
|
162
226
|
}
|
|
227
|
+
}
|
|
163
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Read, migrate and (when `apply`) atomically rewrite one store. Under --apply
|
|
231
|
+
* the caller holds the store lock.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} repoPath
|
|
234
|
+
* @param {string} learningsPath
|
|
235
|
+
* @param {boolean} apply
|
|
236
|
+
* @returns {RepoResult}
|
|
237
|
+
*/
|
|
238
|
+
function migrateStore(repoPath, learningsPath, apply) {
|
|
164
239
|
// Read
|
|
165
240
|
let raw;
|
|
166
241
|
try {
|
|
167
242
|
raw = readFileSync(learningsPath, 'utf8');
|
|
168
243
|
} catch (err) {
|
|
169
|
-
return {
|
|
170
|
-
repo: repoPath,
|
|
171
|
-
status: 'error',
|
|
172
|
-
total: 0,
|
|
173
|
-
invalidPre: 0,
|
|
174
|
-
invalidPost: 0,
|
|
175
|
-
fixedByV2: 0,
|
|
176
|
-
malformed: 0,
|
|
177
|
-
error: `read failed: ${err.message}`,
|
|
178
|
-
};
|
|
244
|
+
return emptyResult(repoPath, 'error', `read failed: ${err.message}`);
|
|
179
245
|
}
|
|
180
246
|
|
|
181
247
|
const lines = raw.split('\n').filter((l) => l.trim().length > 0);
|
|
@@ -184,6 +250,10 @@ function processRepo(repoPath, apply) {
|
|
|
184
250
|
let invalidPre = 0;
|
|
185
251
|
let invalidPost = 0;
|
|
186
252
|
let fixedByV2 = 0;
|
|
253
|
+
/** @type {Record<string, number>} */
|
|
254
|
+
const errorClassesPre = {};
|
|
255
|
+
/** @type {Record<string, number>} */
|
|
256
|
+
const errorClassesPost = {};
|
|
187
257
|
const outputLines = [];
|
|
188
258
|
|
|
189
259
|
for (const line of lines) {
|
|
@@ -201,9 +271,10 @@ function processRepo(repoPath, apply) {
|
|
|
201
271
|
let wasValidPre = true;
|
|
202
272
|
try {
|
|
203
273
|
validateLearning({ ...parsed, schema_version: parsed.schema_version ?? 1 });
|
|
204
|
-
} catch {
|
|
274
|
+
} catch (err) {
|
|
205
275
|
wasValidPre = false;
|
|
206
276
|
invalidPre++;
|
|
277
|
+
bump(errorClassesPre, errorClassOf(err));
|
|
207
278
|
}
|
|
208
279
|
|
|
209
280
|
// Migrate
|
|
@@ -217,9 +288,10 @@ function processRepo(repoPath, apply) {
|
|
|
217
288
|
...migrated,
|
|
218
289
|
schema_version: migrated.schema_version ?? 1,
|
|
219
290
|
});
|
|
220
|
-
} catch {
|
|
291
|
+
} catch (err) {
|
|
221
292
|
isValidPost = false;
|
|
222
293
|
invalidPost++;
|
|
294
|
+
bump(errorClassesPost, errorClassOf(err));
|
|
223
295
|
}
|
|
224
296
|
|
|
225
297
|
if (!wasValidPre && isValidPost) {
|
|
@@ -259,6 +331,8 @@ function processRepo(repoPath, apply) {
|
|
|
259
331
|
invalidPost,
|
|
260
332
|
fixedByV2,
|
|
261
333
|
malformed,
|
|
334
|
+
errorClassesPre,
|
|
335
|
+
errorClassesPost,
|
|
262
336
|
error: `write failed: ${err.message}`,
|
|
263
337
|
};
|
|
264
338
|
}
|
|
@@ -272,6 +346,8 @@ function processRepo(repoPath, apply) {
|
|
|
272
346
|
invalidPost,
|
|
273
347
|
fixedByV2,
|
|
274
348
|
malformed,
|
|
349
|
+
errorClassesPre,
|
|
350
|
+
errorClassesPost,
|
|
275
351
|
error: null,
|
|
276
352
|
};
|
|
277
353
|
}
|
|
@@ -280,7 +356,10 @@ function processRepo(repoPath, apply) {
|
|
|
280
356
|
// Run across all repos
|
|
281
357
|
// ---------------------------------------------------------------------------
|
|
282
358
|
|
|
283
|
-
|
|
359
|
+
// Sequential: one store lock at a time, and a lock failure in one repo never
|
|
360
|
+
// stops the next.
|
|
361
|
+
const results = [];
|
|
362
|
+
for (const r of repos) results.push(await processRepo(r, applyFlag));
|
|
284
363
|
|
|
285
364
|
// ---------------------------------------------------------------------------
|
|
286
365
|
// Aggregate
|
|
@@ -294,6 +373,12 @@ const aggregate = results.reduce(
|
|
|
294
373
|
acc.totalMalformed += r.malformed;
|
|
295
374
|
acc.totalReposProcessed += r.status !== 'skipped' ? 1 : 0;
|
|
296
375
|
acc.totalReposSkipped += r.status === 'skipped' ? 1 : 0;
|
|
376
|
+
for (const [cls, n] of Object.entries(r.errorClassesPre)) {
|
|
377
|
+
acc.errorClassesPre[cls] = (acc.errorClassesPre[cls] ?? 0) + n;
|
|
378
|
+
}
|
|
379
|
+
for (const [cls, n] of Object.entries(r.errorClassesPost)) {
|
|
380
|
+
acc.errorClassesPost[cls] = (acc.errorClassesPost[cls] ?? 0) + n;
|
|
381
|
+
}
|
|
297
382
|
return acc;
|
|
298
383
|
},
|
|
299
384
|
{
|
|
@@ -303,6 +388,10 @@ const aggregate = results.reduce(
|
|
|
303
388
|
totalMalformed: 0,
|
|
304
389
|
totalReposProcessed: 0,
|
|
305
390
|
totalReposSkipped: 0,
|
|
391
|
+
/** @type {Record<string, number>} */
|
|
392
|
+
errorClassesPre: {},
|
|
393
|
+
/** @type {Record<string, number>} */
|
|
394
|
+
errorClassesPost: {},
|
|
306
395
|
}
|
|
307
396
|
);
|
|
308
397
|
|
|
@@ -319,6 +408,26 @@ function fmtPct(count, total) {
|
|
|
319
408
|
return `${count} (${((count / total) * 100).toFixed(1)}%)`;
|
|
320
409
|
}
|
|
321
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Markdown table of invalid-record counts per error class, pre vs post
|
|
413
|
+
* migration. Classes are the union of both sides, sorted by pre count desc.
|
|
414
|
+
*
|
|
415
|
+
* @param {Record<string, number>} pre
|
|
416
|
+
* @param {Record<string, number>} post
|
|
417
|
+
* @returns {string[]}
|
|
418
|
+
*/
|
|
419
|
+
function errorClassTable(pre, post) {
|
|
420
|
+
const classes = [...new Set([...Object.keys(pre), ...Object.keys(post)])].sort(
|
|
421
|
+
(a, b) => (pre[b] ?? 0) - (pre[a] ?? 0) || a.localeCompare(b)
|
|
422
|
+
);
|
|
423
|
+
if (classes.length === 0) return ['_No validation errors._'];
|
|
424
|
+
const rows = ['| Error class | Invalid pre | Invalid post |', '|-------------|-------------|--------------|'];
|
|
425
|
+
for (const cls of classes) {
|
|
426
|
+
rows.push(`| ${cls.replaceAll('|', '\\|')} | ${pre[cls] ?? 0} | ${post[cls] ?? 0} |`);
|
|
427
|
+
}
|
|
428
|
+
return rows;
|
|
429
|
+
}
|
|
430
|
+
|
|
322
431
|
function buildMarkdown(results, aggregate, mode) {
|
|
323
432
|
const lines = [];
|
|
324
433
|
lines.push(`# Cross-Repo Migrate-CLI v2 — ${mode} report`);
|
|
@@ -345,6 +454,17 @@ function buildMarkdown(results, aggregate, mode) {
|
|
|
345
454
|
lines.push(`- Repos processed: **${aggregate.totalReposProcessed}**`);
|
|
346
455
|
lines.push(`- Repos skipped (no learnings.jsonl): **${aggregate.totalReposSkipped}**`);
|
|
347
456
|
lines.push('');
|
|
457
|
+
lines.push('## Error classes (all repos)');
|
|
458
|
+
lines.push('');
|
|
459
|
+
lines.push(...errorClassTable(aggregate.errorClassesPre, aggregate.errorClassesPost));
|
|
460
|
+
lines.push('');
|
|
461
|
+
for (const r of results) {
|
|
462
|
+
if (r.status === 'skipped') continue;
|
|
463
|
+
lines.push(`### ${repoName(r.repo)}`);
|
|
464
|
+
lines.push('');
|
|
465
|
+
lines.push(...errorClassTable(r.errorClassesPre, r.errorClassesPost));
|
|
466
|
+
lines.push('');
|
|
467
|
+
}
|
|
348
468
|
return lines.join('\n');
|
|
349
469
|
}
|
|
350
470
|
|
|
@@ -382,4 +502,12 @@ process.stderr.write(
|
|
|
382
502
|
`${aggregate.totalStillInvalidPost} still-invalid\n`
|
|
383
503
|
);
|
|
384
504
|
|
|
505
|
+
if (lockFailedRepos.length > 0) {
|
|
506
|
+
process.stderr.write(
|
|
507
|
+
`run-migrate-v2: ERROR learnings store lock not acquired, nothing written in ${lockFailedRepos.length} repo(s): ` +
|
|
508
|
+
`${lockFailedRepos.join(', ')}\n`
|
|
509
|
+
);
|
|
510
|
+
process.exit(2);
|
|
511
|
+
}
|
|
512
|
+
|
|
385
513
|
process.exit(0);
|