session-orchestrator 3.16.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/.claude-plugin/marketplace.json +29 -0
- package/.claude-plugin/plugin.json +18 -0
- package/.codex-plugin/agents/explorer.toml +14 -0
- package/.codex-plugin/agents/session-reviewer.toml +23 -0
- package/.codex-plugin/agents/wave-worker.toml +15 -0
- package/.codex-plugin/config.toml +20 -0
- package/.codex-plugin/plugin.json +37 -0
- package/.cursor/rules/000-session-orchestrator.mdc +73 -0
- package/.cursor/rules/010-session-workflow.mdc +170 -0
- package/.cursor/rules/020-quality-gates.mdc +128 -0
- package/.cursor/rules/030-wave-execution.mdc +216 -0
- package/.cursor/rules/040-discovery.mdc +242 -0
- package/.cursor/rules/050-plan.mdc +235 -0
- package/.cursor/rules/060-evolve.mdc +232 -0
- package/.cursor/rules/070-gitlab-ops.mdc +246 -0
- package/.cursor/rules/080-ecosystem-health.mdc +145 -0
- package/.mcp.json +8 -0
- package/CHANGELOG.md +1544 -0
- package/LICENSE +21 -0
- package/NOTICE +64 -0
- package/README.md +242 -0
- package/SECURITY.md +90 -0
- package/agents/AGENTS.md +136 -0
- package/agents/analyst.md +99 -0
- package/agents/architect-reviewer.md +93 -0
- package/agents/code-implementer.md +106 -0
- package/agents/db-specialist.md +104 -0
- package/agents/dialectic-deriver.md +139 -0
- package/agents/docs-writer.md +113 -0
- package/agents/eval-judge.md +146 -0
- package/agents/memory-proposal-collector.md +297 -0
- package/agents/qa-strategist.md +102 -0
- package/agents/schemas/analyst.schema.json +46 -0
- package/agents/schemas/architect-reviewer.schema.json +50 -0
- package/agents/schemas/code-implementer.schema.json +61 -0
- package/agents/schemas/db-specialist.schema.json +80 -0
- package/agents/schemas/docs-writer.schema.json +56 -0
- package/agents/schemas/persona-panel-sidecar.schema.json +245 -0
- package/agents/schemas/qa-strategist.schema.json +46 -0
- package/agents/schemas/security-reviewer.schema.json +86 -0
- package/agents/schemas/session-reviewer.schema.json +69 -0
- package/agents/schemas/test-writer.schema.json +69 -0
- package/agents/schemas/ui-developer.schema.json +90 -0
- package/agents/schemas/ux-evaluator.schema.json +51 -0
- package/agents/security-reviewer.md +236 -0
- package/agents/session-reviewer.md +201 -0
- package/agents/skill-applied-judge.md +122 -0
- package/agents/test-writer.md +123 -0
- package/agents/ui-developer.md +109 -0
- package/agents/ux-evaluator.md +161 -0
- package/assets/icon.svg +11 -0
- package/assets/og-card.png +0 -0
- package/assets/og-card.svg +47 -0
- package/commands/autopilot-multi.md +74 -0
- package/commands/autopilot.md +80 -0
- package/commands/bootstrap.md +56 -0
- package/commands/brainstorm.md +48 -0
- package/commands/close.md +24 -0
- package/commands/debug.md +36 -0
- package/commands/discovery.md +32 -0
- package/commands/dispatcher.md +59 -0
- package/commands/eval.md +28 -0
- package/commands/evolve.md +10 -0
- package/commands/go.md +41 -0
- package/commands/grill.md +45 -0
- package/commands/harness-audit.md +26 -0
- package/commands/memory-cleanup.md +25 -0
- package/commands/persona-panel.md +121 -0
- package/commands/plan.md +15 -0
- package/commands/portfolio.md +97 -0
- package/commands/reconcile.md +23 -0
- package/commands/repo-audit.md +24 -0
- package/commands/session.md +30 -0
- package/commands/spinout.md +15 -0
- package/commands/sunset-review.md +27 -0
- package/commands/templates-ack.md +96 -0
- package/commands/test.md +97 -0
- package/docs/README.md +105 -0
- package/docs/USER-GUIDE.md +1403 -0
- package/docs/ci-setup.md +81 -0
- package/docs/codex-setup.md +142 -0
- package/docs/components.md +74 -0
- package/docs/cursor-setup.md +104 -0
- package/docs/events-schema.md +81 -0
- package/docs/migration-v3.md +148 -0
- package/docs/owner-config-schema.md +154 -0
- package/docs/persona-panel.md +433 -0
- package/docs/pi-setup.md +115 -0
- package/docs/plugin-architecture-v3.md +296 -0
- package/docs/pm-skills-marketplace.md +114 -0
- package/docs/policy-cache-validation-2026-04-28.md +118 -0
- package/docs/rule-authoring.md +316 -0
- package/docs/session-config-reference.md +1439 -0
- package/docs/session-config-template.md +961 -0
- package/docs/vault-docs-architecture.md +297 -0
- package/hooks/_lib/lock-bootstrap.mjs +272 -0
- package/hooks/_lib/lock-reconcile.mjs +93 -0
- package/hooks/_lib/profile-gate.mjs +95 -0
- package/hooks/_lib/transcript-history.mjs +211 -0
- package/hooks/agent-teams-h3-test.sh +362 -0
- package/hooks/config-protection.mjs +0 -0
- package/hooks/cwd-change-restore.mjs +131 -0
- package/hooks/enforce-commands.mjs +179 -0
- package/hooks/enforce-scope.mjs +273 -0
- package/hooks/hooks-codex.json +60 -0
- package/hooks/hooks-cursor.json +15 -0
- package/hooks/hooks-pi.json +115 -0
- package/hooks/hooks.json +215 -0
- package/hooks/loop-guard.mjs +260 -0
- package/hooks/on-session-end.mjs +217 -0
- package/hooks/on-session-start.mjs +660 -0
- package/hooks/on-stop.mjs +294 -0
- package/hooks/operator-steer.mjs +64 -0
- package/hooks/post-edit-validate.mjs +225 -0
- package/hooks/post-subagent-discovery-validator.mjs +398 -0
- package/hooks/post-tool-batch-wave-signal.mjs +328 -0
- package/hooks/post-tool-failure-corrective-context.mjs +248 -0
- package/hooks/post-tooluse-frontend-slop.mjs +184 -0
- package/hooks/pre-bash-destructive-guard.mjs +515 -0
- package/hooks/pre-bash-memory-propose-audit.mjs +206 -0
- package/hooks/pre-bash-staging-fence.mjs +223 -0
- package/hooks/pre-bash-templates-first.mjs +404 -0
- package/hooks/run-node.sh +72 -0
- package/hooks/skill-invocation-telemetry.mjs +99 -0
- package/hooks/subagent-telemetry.mjs +249 -0
- package/hooks/wave-scope-commit-guard.mjs +191 -0
- package/monitors/monitors.json +14 -0
- package/output-styles/finding-report.md +48 -0
- package/output-styles/session-report.md +53 -0
- package/output-styles/wave-summary.md +38 -0
- package/package.json +94 -0
- package/pi/extensions/session-orchestrator.ts +25 -0
- package/pi/prompts/autopilot-multi.md +12 -0
- package/pi/prompts/autopilot.md +12 -0
- package/pi/prompts/bootstrap.md +12 -0
- package/pi/prompts/brainstorm.md +12 -0
- package/pi/prompts/close.md +11 -0
- package/pi/prompts/debug.md +12 -0
- package/pi/prompts/discovery.md +12 -0
- package/pi/prompts/dispatcher.md +12 -0
- package/pi/prompts/eval.md +12 -0
- package/pi/prompts/evolve.md +12 -0
- package/pi/prompts/go.md +12 -0
- package/pi/prompts/grill.md +12 -0
- package/pi/prompts/harness-audit.md +12 -0
- package/pi/prompts/memory-cleanup.md +12 -0
- package/pi/prompts/persona-panel.md +12 -0
- package/pi/prompts/plan.md +12 -0
- package/pi/prompts/portfolio.md +12 -0
- package/pi/prompts/reconcile.md +12 -0
- package/pi/prompts/repo-audit.md +12 -0
- package/pi/prompts/session.md +12 -0
- package/pi/prompts/spinout.md +12 -0
- package/pi/prompts/sunset-review.md +12 -0
- package/pi/prompts/templates-ack.md +12 -0
- package/pi/prompts/test.md +12 -0
- package/rules/_index.md +51 -0
- package/rules/always-on/commit-discipline.md +26 -0
- package/rules/always-on/npm-quality-gates.md +26 -0
- package/rules/always-on/parallel-sessions.md +43 -0
- package/rules/opt-in-domain/prompt-caching.md +270 -0
- package/rules/opt-in-stack/backend-data.md +188 -0
- package/rules/opt-in-stack/backend.md +390 -0
- package/rules/opt-in-stack/frontend.md +98 -0
- package/rules/opt-in-stack/security-web.md +194 -0
- package/rules/opt-in-stack/swift.md +65 -0
- package/scripts/archive-closed-prds.mjs +416 -0
- package/scripts/autopilot-multi.mjs +802 -0
- package/scripts/autopilot.mjs +383 -0
- package/scripts/backfill-abandoned-sessions.mjs +265 -0
- package/scripts/backfill-learnings-expires.mjs +196 -0
- package/scripts/backfill-learnings.mjs +203 -0
- package/scripts/backfill-sessions.mjs +282 -0
- package/scripts/check-doc-consistency.sh +279 -0
- package/scripts/check-package-manager.mjs +445 -0
- package/scripts/ci/assert-vitest-green.mjs +267 -0
- package/scripts/codex-install.mjs +435 -0
- package/scripts/compute-grounding-injection.sh +186 -0
- package/scripts/cursor-install.mjs +113 -0
- package/scripts/dialectic-deriver.mjs +573 -0
- package/scripts/emit-event.mjs +160 -0
- package/scripts/emit-session.mjs +212 -0
- package/scripts/eval-session.mjs +262 -0
- package/scripts/export-hw-learnings.mjs +437 -0
- package/scripts/gc-stale-worktrees.mjs +666 -0
- package/scripts/generate-pi-prompts.mjs +127 -0
- package/scripts/harness-audit.mjs +287 -0
- package/scripts/lib/agent-frontmatter.mjs +266 -0
- package/scripts/lib/agent-output-schema.mjs +166 -0
- package/scripts/lib/agent-status.mjs +303 -0
- package/scripts/lib/ajv-loader.mjs +34 -0
- package/scripts/lib/auto-dialectic.mjs +382 -0
- package/scripts/lib/auto-dream.mjs +471 -0
- package/scripts/lib/autonomy/suitability.mjs +212 -0
- package/scripts/lib/autopilot/dep-graph.mjs +417 -0
- package/scripts/lib/autopilot/durable-telemetry.mjs +121 -0
- package/scripts/lib/autopilot/flags.mjs +104 -0
- package/scripts/lib/autopilot/kill-switches.mjs +174 -0
- package/scripts/lib/autopilot/loop.mjs +320 -0
- package/scripts/lib/autopilot/mr-draft.mjs +520 -0
- package/scripts/lib/autopilot/multi-killswitch.mjs +184 -0
- package/scripts/lib/autopilot/recent-runs.mjs +106 -0
- package/scripts/lib/autopilot/stall-sampler.mjs +97 -0
- package/scripts/lib/autopilot/telemetry.mjs +224 -0
- package/scripts/lib/autopilot/worktree-pipeline.mjs +605 -0
- package/scripts/lib/autopilot-telemetry.mjs +11 -0
- package/scripts/lib/autopilot.mjs +39 -0
- package/scripts/lib/backlog-scan.mjs +179 -0
- package/scripts/lib/bootstrap-lock-freshness.mjs +260 -0
- package/scripts/lib/bootstrap-lock-refresh.mjs +186 -0
- package/scripts/lib/build-live-signals.mjs +150 -0
- package/scripts/lib/ci-status-banner.mjs +425 -0
- package/scripts/lib/claude-md-budget-lint.mjs +246 -0
- package/scripts/lib/cli-flags.mjs +158 -0
- package/scripts/lib/codex/plugin-contract.mjs +610 -0
- package/scripts/lib/cold-start-detector.mjs +240 -0
- package/scripts/lib/command-blocker.mjs +458 -0
- package/scripts/lib/common.mjs +333 -0
- package/scripts/lib/config/auto-dream.mjs +77 -0
- package/scripts/lib/config/block-header.mjs +94 -0
- package/scripts/lib/config/broken-window.mjs +114 -0
- package/scripts/lib/config/coercers.mjs +248 -0
- package/scripts/lib/config/cold-start.mjs +92 -0
- package/scripts/lib/config/config-protection.mjs +120 -0
- package/scripts/lib/config/cross-repo.mjs +104 -0
- package/scripts/lib/config/custom-phases.mjs +213 -0
- package/scripts/lib/config/dialectic.mjs +92 -0
- package/scripts/lib/config/discovery-validator.mjs +75 -0
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +240 -0
- package/scripts/lib/config/dispatcher-autonomy.mjs +152 -0
- package/scripts/lib/config/docs-orchestrator.mjs +90 -0
- package/scripts/lib/config/docs-staleness.mjs +96 -0
- package/scripts/lib/config/drift-check.mjs +155 -0
- package/scripts/lib/config/eval.mjs +130 -0
- package/scripts/lib/config/events-rotation.mjs +74 -0
- package/scripts/lib/config/evolve.mjs +308 -0
- package/scripts/lib/config/frontend-slop-hook.mjs +104 -0
- package/scripts/lib/config/gitlab-portfolio.mjs +150 -0
- package/scripts/lib/config/handover-gate.mjs +106 -0
- package/scripts/lib/config/host-paths.mjs +76 -0
- package/scripts/lib/config/io.mjs +54 -0
- package/scripts/lib/config/loop-guard.mjs +117 -0
- package/scripts/lib/config/memory.mjs +150 -0
- package/scripts/lib/config/persona-gate-wave.mjs +258 -0
- package/scripts/lib/config/reconcile.mjs +205 -0
- package/scripts/lib/config/section-extractor.mjs +100 -0
- package/scripts/lib/config/skill-evolution.mjs +112 -0
- package/scripts/lib/config/slopcheck.mjs +99 -0
- package/scripts/lib/config/state-md-lock.mjs +83 -0
- package/scripts/lib/config/templates-first.mjs +94 -0
- package/scripts/lib/config/test.mjs +113 -0
- package/scripts/lib/config/vault-integration.mjs +201 -0
- package/scripts/lib/config/vault-mirror-quality.mjs +99 -0
- package/scripts/lib/config/vault-staleness.mjs +84 -0
- package/scripts/lib/config/vault-sync.mjs +96 -0
- package/scripts/lib/config/verification-auto-fix.mjs +84 -0
- package/scripts/lib/config/wave-reviewers.mjs +133 -0
- package/scripts/lib/config-schema.mjs +345 -0
- package/scripts/lib/config.mjs +474 -0
- package/scripts/lib/convergence-monitor.mjs +389 -0
- package/scripts/lib/coordinator-snapshot.mjs +371 -0
- package/scripts/lib/crypto-digest-utils.mjs +91 -0
- package/scripts/lib/discovery/helpers.mjs +127 -0
- package/scripts/lib/discovery/triage-state.mjs +279 -0
- package/scripts/lib/dispatcher/cli.mjs +257 -0
- package/scripts/lib/dispatcher/enumerate.mjs +243 -0
- package/scripts/lib/dispatcher/rank.mjs +363 -0
- package/scripts/lib/ecosystem-health.mjs +224 -0
- package/scripts/lib/ecosystem-wizard/ci-detector.mjs +18 -0
- package/scripts/lib/ecosystem-wizard/config-parser.mjs +54 -0
- package/scripts/lib/ecosystem-wizard/config-writer.mjs +287 -0
- package/scripts/lib/ecosystem-wizard/package-manager-detector.mjs +42 -0
- package/scripts/lib/ecosystem-wizard/wizard-prompt.mjs +246 -0
- package/scripts/lib/ecosystem-wizard.mjs +48 -0
- package/scripts/lib/env-check.mjs +89 -0
- package/scripts/lib/eval/engine.mjs +605 -0
- package/scripts/lib/eval/judge.mjs +433 -0
- package/scripts/lib/eval/report.mjs +367 -0
- package/scripts/lib/eval/schema.mjs +618 -0
- package/scripts/lib/eval/session-resolve.mjs +137 -0
- package/scripts/lib/eval/sink.mjs +77 -0
- package/scripts/lib/events-rotation.mjs +86 -0
- package/scripts/lib/events-schema.mjs +81 -0
- package/scripts/lib/events.mjs +80 -0
- package/scripts/lib/evolve/autonomy-verdict.mjs +461 -0
- package/scripts/lib/evolve/autopilot-effectiveness.mjs +293 -0
- package/scripts/lib/exclusivity-matrix.mjs +68 -0
- package/scripts/lib/fetch-baseline.mjs +311 -0
- package/scripts/lib/file-lock.mjs +512 -0
- package/scripts/lib/frontend-detect/detect.mjs +138 -0
- package/scripts/lib/frontend-detect/rules.mjs +295 -0
- package/scripts/lib/frontmatter-guard.mjs +241 -0
- package/scripts/lib/gates/echo-stub-detect.mjs +39 -0
- package/scripts/lib/gates/gate-baseline.mjs +42 -0
- package/scripts/lib/gates/gate-full.mjs +85 -0
- package/scripts/lib/gates/gate-helpers.mjs +231 -0
- package/scripts/lib/gates/gate-incremental.mjs +76 -0
- package/scripts/lib/gates/gate-per-file.mjs +55 -0
- package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +447 -0
- package/scripts/lib/gitlab-portfolio/aggregator.mjs +383 -0
- package/scripts/lib/gitlab-portfolio/cli.mjs +428 -0
- package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +289 -0
- package/scripts/lib/gitlab-portfolio/vcs-detect.mjs +182 -0
- package/scripts/lib/handover-gate.mjs +222 -0
- package/scripts/lib/hardening.mjs +43 -0
- package/scripts/lib/hardware-pattern-detector.mjs +238 -0
- package/scripts/lib/harness-audit/categories/category1.mjs +123 -0
- package/scripts/lib/harness-audit/categories/category2.mjs +145 -0
- package/scripts/lib/harness-audit/categories/category3.mjs +143 -0
- package/scripts/lib/harness-audit/categories/category4.mjs +202 -0
- package/scripts/lib/harness-audit/categories/category5.mjs +152 -0
- package/scripts/lib/harness-audit/categories/category6.mjs +211 -0
- package/scripts/lib/harness-audit/categories/category7.mjs +125 -0
- package/scripts/lib/harness-audit/categories/category8.mjs +328 -0
- package/scripts/lib/harness-audit/categories/category9.mjs +294 -0
- package/scripts/lib/harness-audit/categories/helpers.mjs +165 -0
- package/scripts/lib/harness-audit/categories.mjs +19 -0
- package/scripts/lib/historical-guard.mjs +15 -0
- package/scripts/lib/host-identity.mjs +262 -0
- package/scripts/lib/instruction-budget-guard.mjs +332 -0
- package/scripts/lib/io.mjs +304 -0
- package/scripts/lib/issue-close-strip-labels.mjs +161 -0
- package/scripts/lib/language-mappers/README.md +57 -0
- package/scripts/lib/language-mappers/index.mjs +165 -0
- package/scripts/lib/language-mappers/markdown.mjs +149 -0
- package/scripts/lib/language-mappers/python.mjs +249 -0
- package/scripts/lib/language-mappers/swift.mjs +201 -0
- package/scripts/lib/language-mappers/typescript.mjs +433 -0
- package/scripts/lib/learnings/expiry-sweep.mjs +164 -0
- package/scripts/lib/learnings/filters.mjs +43 -0
- package/scripts/lib/learnings/io.mjs +255 -0
- package/scripts/lib/learnings/schema.mjs +518 -0
- package/scripts/lib/learnings/surface.mjs +207 -0
- package/scripts/lib/learnings.mjs +42 -0
- package/scripts/lib/lock-reaper.mjs +648 -0
- package/scripts/lib/locks/index.mjs +31 -0
- package/scripts/lib/locks/lock-body.mjs +62 -0
- package/scripts/lib/locks/staging-fence-lock.mjs +267 -0
- package/scripts/lib/locks/state-md-lock.mjs +351 -0
- package/scripts/lib/loop-readiness-banner.mjs +144 -0
- package/scripts/lib/memory-banner.mjs +478 -0
- package/scripts/lib/memory-cleanup/worktree-sweep.mjs +108 -0
- package/scripts/lib/memory-cleanup-stamp.mjs +56 -0
- package/scripts/lib/memory-paths.mjs +31 -0
- package/scripts/lib/memory-proposals/collector.mjs +334 -0
- package/scripts/lib/memory-proposals/schema.mjs +289 -0
- package/scripts/lib/memory-proposals/sink.mjs +507 -0
- package/scripts/lib/memory-proposals/store.mjs +441 -0
- package/scripts/lib/mission-status-schema.mjs +114 -0
- package/scripts/lib/mode-selector/alternatives.mjs +64 -0
- package/scripts/lib/mode-selector/constants.mjs +29 -0
- package/scripts/lib/mode-selector/context-pressure.mjs +157 -0
- package/scripts/lib/mode-selector/rationale.mjs +55 -0
- package/scripts/lib/mode-selector/scoring.mjs +221 -0
- package/scripts/lib/mode-selector-accuracy.mjs +121 -0
- package/scripts/lib/mode-selector.mjs +160 -0
- package/scripts/lib/multi-provider-build/providers.mjs +64 -0
- package/scripts/lib/multi-provider-build/templating.mjs +130 -0
- package/scripts/lib/named-baseline-resolver.mjs +233 -0
- package/scripts/lib/named-vault-resolver.mjs +433 -0
- package/scripts/lib/owner-config/coerce.mjs +29 -0
- package/scripts/lib/owner-config/constants.mjs +21 -0
- package/scripts/lib/owner-config/defaults.mjs +50 -0
- package/scripts/lib/owner-config/error.mjs +19 -0
- package/scripts/lib/owner-config/index.mjs +13 -0
- package/scripts/lib/owner-config/merge.mjs +52 -0
- package/scripts/lib/owner-config/validate.mjs +259 -0
- package/scripts/lib/owner-config-banner.mjs +126 -0
- package/scripts/lib/owner-config-loader.mjs +159 -0
- package/scripts/lib/owner-config.example.yaml +72 -0
- package/scripts/lib/owner-config.mjs +28 -0
- package/scripts/lib/owner-interview.mjs +243 -0
- package/scripts/lib/owner-yaml.mjs +571 -0
- package/scripts/lib/package-manager.mjs +160 -0
- package/scripts/lib/path-utils.mjs +217 -0
- package/scripts/lib/peer-cards/merger.mjs +310 -0
- package/scripts/lib/peer-cards/reader.mjs +125 -0
- package/scripts/lib/peer-cards/schema.mjs +230 -0
- package/scripts/lib/peer-cards/staleness-banner.mjs +86 -0
- package/scripts/lib/peer-cards/writer.mjs +138 -0
- package/scripts/lib/peer-discovery.mjs +200 -0
- package/scripts/lib/persona-panel/catalog-loader.mjs +577 -0
- package/scripts/lib/persona-panel/consolidator.mjs +370 -0
- package/scripts/lib/persona-panel/persona-runner.mjs +375 -0
- package/scripts/lib/persona-panel/threshold.mjs +130 -0
- package/scripts/lib/pi-hook-bridge.mjs +328 -0
- package/scripts/lib/platform.mjs +266 -0
- package/scripts/lib/playwright-driver/runner.mjs +297 -0
- package/scripts/lib/plugin-root.mjs +210 -0
- package/scripts/lib/pre-dispatch-check.mjs +126 -0
- package/scripts/lib/product-repo-detect.mjs +121 -0
- package/scripts/lib/profiles/registry.mjs +176 -0
- package/scripts/lib/profiles/schema.mjs +209 -0
- package/scripts/lib/qg-command-drift-banner.mjs +88 -0
- package/scripts/lib/quality-gate/diagnostics.mjs +92 -0
- package/scripts/lib/quality-gate.mjs +536 -0
- package/scripts/lib/quality-gates-cache.mjs +228 -0
- package/scripts/lib/quality-gates-policy.mjs +95 -0
- package/scripts/lib/recommendations-v0.mjs +156 -0
- package/scripts/lib/reconcile/eligibility.mjs +203 -0
- package/scripts/lib/reconcile/emitter.mjs +244 -0
- package/scripts/lib/reconcile/engine.mjs +412 -0
- package/scripts/lib/reconcile/idempotency.mjs +239 -0
- package/scripts/lib/reconcile/renderer.mjs +211 -0
- package/scripts/lib/reconcile/writer.mjs +293 -0
- package/scripts/lib/reconcile-nudge-banner.mjs +284 -0
- package/scripts/lib/resource-probe/evaluate.mjs +190 -0
- package/scripts/lib/resource-probe/parsers.mjs +181 -0
- package/scripts/lib/resource-probe/probe-platform.mjs +300 -0
- package/scripts/lib/resource-probe.mjs +95 -0
- package/scripts/lib/rule-loader.mjs +552 -0
- package/scripts/lib/rules-sync.mjs +439 -0
- package/scripts/lib/scope-gate.mjs +496 -0
- package/scripts/lib/session-close-backfill.mjs +539 -0
- package/scripts/lib/session-discovery.mjs +256 -0
- package/scripts/lib/session-end/phase-skip.mjs +357 -0
- package/scripts/lib/session-end/worktree-cleanup.mjs +112 -0
- package/scripts/lib/session-id.mjs +362 -0
- package/scripts/lib/session-lock.mjs +703 -0
- package/scripts/lib/session-registry.mjs +355 -0
- package/scripts/lib/session-schema/aliases.mjs +71 -0
- package/scripts/lib/session-schema/constants.mjs +115 -0
- package/scripts/lib/session-schema/normalizer.mjs +66 -0
- package/scripts/lib/session-schema/timestamps.mjs +64 -0
- package/scripts/lib/session-schema/validator.mjs +453 -0
- package/scripts/lib/session-schema.mjs +71 -0
- package/scripts/lib/session-token-rollup.mjs +137 -0
- package/scripts/lib/sessions-staleness-banner.mjs +247 -0
- package/scripts/lib/skill-evolution/blast-radius-classifier.mjs +114 -0
- package/scripts/lib/skill-evolution/candidate-intake.mjs +270 -0
- package/scripts/lib/skill-evolution/config-validation-gate.mjs +279 -0
- package/scripts/lib/skill-evolution/engine.mjs +719 -0
- package/scripts/lib/skill-evolution/idempotency.mjs +279 -0
- package/scripts/lib/skill-evolution/mr-opener.mjs +507 -0
- package/scripts/lib/skill-health/join.mjs +181 -0
- package/scripts/lib/skill-health/score.mjs +123 -0
- package/scripts/lib/skill-invocations-schema.mjs +214 -0
- package/scripts/lib/skill-judge.mjs +348 -0
- package/scripts/lib/skill-judgments-schema.mjs +264 -0
- package/scripts/lib/slopcheck.mjs +501 -0
- package/scripts/lib/soul-resolve.mjs +118 -0
- package/scripts/lib/spiral-carryover.mjs +495 -0
- package/scripts/lib/state-md/body-sections.mjs +851 -0
- package/scripts/lib/state-md/frontmatter-mutators.mjs +453 -0
- package/scripts/lib/state-md/mission-status.mjs +247 -0
- package/scripts/lib/state-md/recommendations.mjs +57 -0
- package/scripts/lib/state-md/yaml-parser.mjs +234 -0
- package/scripts/lib/state-md-peer-guard.mjs +232 -0
- package/scripts/lib/state-md.mjs +53 -0
- package/scripts/lib/subagents-schema.mjs +309 -0
- package/scripts/lib/sunset/walker.mjs +1192 -0
- package/scripts/lib/test-runner/artifact-paths.mjs +94 -0
- package/scripts/lib/test-runner/fingerprint.mjs +33 -0
- package/scripts/lib/test-runner/issue-reconcile.mjs +770 -0
- package/scripts/lib/tmux-layout/layouts.mjs +224 -0
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +100 -0
- package/scripts/lib/tmux-layout/telemetry.mjs +88 -0
- package/scripts/lib/tmux-layout/tmux-shell.mjs +82 -0
- package/scripts/lib/tmux-layout/vcs-detector.mjs +88 -0
- package/scripts/lib/validate/check-agents.mjs +457 -0
- package/scripts/lib/validate/check-codex-plugin.mjs +37 -0
- package/scripts/lib/validate/check-commands.mjs +148 -0
- package/scripts/lib/validate/check-component-paths.mjs +112 -0
- package/scripts/lib/validate/check-dead-bridge.mjs +180 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +258 -0
- package/scripts/lib/validate/check-json-files.mjs +116 -0
- package/scripts/lib/validate/check-owner-leakage.mjs +1011 -0
- package/scripts/lib/validate/check-path-utils-canary.mjs +175 -0
- package/scripts/lib/validate/check-peekaboo-driver-canary.mjs +201 -0
- package/scripts/lib/validate/check-pi-package.mjs +110 -0
- package/scripts/lib/validate/check-pi-prompts.mjs +43 -0
- package/scripts/lib/validate/check-playwright-mcp-canary.mjs +154 -0
- package/scripts/lib/validate/check-plugin-json.mjs +96 -0
- package/scripts/lib/validate/check-plugin-monitors.mjs +206 -0
- package/scripts/lib/validate/check-plugin-schema.mjs +137 -0
- package/scripts/lib/validate/check-rules.mjs +143 -0
- package/scripts/lib/validate/check-session-plan-routing.mjs +154 -0
- package/scripts/lib/validate/check-test-fixture-shapes.mjs +280 -0
- package/scripts/lib/validate/check-unicode-safety.mjs +533 -0
- package/scripts/lib/validate/confidential-names.mjs +169 -0
- package/scripts/lib/validate/dead-bridge-corpus.mjs +141 -0
- package/scripts/lib/validate/dead-bridge-detectors.mjs +568 -0
- package/scripts/lib/validate/tier-inference.mjs +100 -0
- package/scripts/lib/validate-vendored-rules.mjs +519 -0
- package/scripts/lib/vault-archive.mjs +404 -0
- package/scripts/lib/vault-backfill/glab.mjs +164 -0
- package/scripts/lib/vault-backfill/manifest.mjs +75 -0
- package/scripts/lib/vault-backfill/template.mjs +130 -0
- package/scripts/lib/vault-consolidate-fs.mjs +331 -0
- package/scripts/lib/vault-migration-rules.mjs +155 -0
- package/scripts/lib/vault-mirror/auto-commit.mjs +203 -0
- package/scripts/lib/vault-mirror/namespace.mjs +152 -0
- package/scripts/lib/vault-mirror/process.mjs +567 -0
- package/scripts/lib/vault-mirror/pseudonym-map.mjs +164 -0
- package/scripts/lib/vault-mirror/render-learnings.mjs +201 -0
- package/scripts/lib/vault-mirror/render-sessions.mjs +367 -0
- package/scripts/lib/vault-mirror/render.mjs +8 -0
- package/scripts/lib/vault-mirror/utils.mjs +217 -0
- package/scripts/lib/vault-relocation-rules.mjs +555 -0
- package/scripts/lib/vault-repo-backfill.mjs +235 -0
- package/scripts/lib/vault-staleness-banner.mjs +142 -0
- package/scripts/lib/vault-status/board-writer.mjs +769 -0
- package/scripts/lib/vault-status/narrative-mirror.mjs +544 -0
- package/scripts/lib/vault-sync-baseline.mjs +152 -0
- package/scripts/lib/wave-context.mjs +29 -0
- package/scripts/lib/wave-executor/pool.mjs +248 -0
- package/scripts/lib/wave-resource-gate.mjs +204 -0
- package/scripts/lib/wave-sizing.mjs +75 -0
- package/scripts/lib/webhook-url.mjs +105 -0
- package/scripts/lib/workspace.mjs +198 -0
- package/scripts/lib/worktree/constants.mjs +35 -0
- package/scripts/lib/worktree/index.mjs +17 -0
- package/scripts/lib/worktree/lifecycle.mjs +287 -0
- package/scripts/lib/worktree/listing.mjs +118 -0
- package/scripts/lib/worktree/meta.mjs +64 -0
- package/scripts/lib/worktree-freshness.mjs +313 -0
- package/scripts/lib/worktree.mjs +15 -0
- package/scripts/lifecycle-sim-v6.mjs +347 -0
- package/scripts/lock-reaper.mjs +185 -0
- package/scripts/mcp-server.sh +241 -0
- package/scripts/measure-policy-cache-effectiveness.mjs +427 -0
- package/scripts/memory-propose.mjs +464 -0
- package/scripts/migrate-cold-start-seed.mjs +404 -0
- package/scripts/migrate-learnings-jsonl.mjs +189 -0
- package/scripts/migrate-legacy-learnings.sh +61 -0
- package/scripts/migrate-sessions-jsonl.mjs +448 -0
- package/scripts/migrate-subagents-jsonl.mjs +196 -0
- package/scripts/migrate-vault-paths.mjs +796 -0
- package/scripts/parse-config.mjs +149 -0
- package/scripts/pi-install.mjs +117 -0
- package/scripts/print-applicable-rules.mjs +247 -0
- package/scripts/promote-vault-strict.mjs +496 -0
- package/scripts/relocate-vault-corpus.mjs +1178 -0
- package/scripts/run-migrate-v2-cross-repo.mjs +385 -0
- package/scripts/run-quality-gate.mjs +216 -0
- package/scripts/spikes/h3-agent-teams/preflight.sh +53 -0
- package/scripts/spikes/h3-agent-teams/run-h3.sh +112 -0
- package/scripts/spikes/h3-agent-teams/setup.sh +137 -0
- package/scripts/spikes/h3-agent-teams/toggle.sh +38 -0
- package/scripts/sweep-expired-learnings.mjs +135 -0
- package/scripts/sync-vault-schema.mjs +376 -0
- package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +8 -0
- package/scripts/tmux-layout.mjs +245 -0
- package/scripts/token-audit.sh +191 -0
- package/scripts/typecheck.mjs +42 -0
- package/scripts/upload-social-preview.mjs +316 -0
- package/scripts/validate-config.mjs +46 -0
- package/scripts/validate-plugin-manifests.mjs +163 -0
- package/scripts/validate-plugin.mjs +264 -0
- package/scripts/validate-wave-scope.mjs +289 -0
- package/scripts/vault-backfill.mjs +404 -0
- package/scripts/vault-consolidate.mjs +596 -0
- package/scripts/vault-integration-watcher.mjs +394 -0
- package/scripts/vault-mirror.mjs +430 -0
- package/skills/_shared/bootstrap-gate.md +111 -0
- package/skills/_shared/config-reading.md +226 -0
- package/skills/_shared/instruction-file-resolution.md +79 -0
- package/skills/_shared/model-selection.md +64 -0
- package/skills/_shared/monitor-patterns.md +300 -0
- package/skills/_shared/parallel-aware-auq.md +121 -0
- package/skills/_shared/parallel-aware-preamble.md +185 -0
- package/skills/_shared/platform-tools.md +96 -0
- package/skills/_shared/state-ownership.md +221 -0
- package/skills/architecture/DEEPENING.md +37 -0
- package/skills/architecture/INTERFACE-DESIGN.md +44 -0
- package/skills/architecture/LANGUAGE.md +53 -0
- package/skills/architecture/SKILL.md +92 -0
- package/skills/autopilot/SKILL.md +419 -0
- package/skills/bootstrap/SKILL.md +592 -0
- package/skills/bootstrap/STATE.md.template +24 -0
- package/skills/bootstrap/_shared-template.md +243 -0
- package/skills/bootstrap/deep-template.md +659 -0
- package/skills/bootstrap/fast-template.md +251 -0
- package/skills/bootstrap/intensity-heuristic.md +80 -0
- package/skills/bootstrap/public-fallback.md +342 -0
- package/skills/bootstrap/standard-template.md +736 -0
- package/skills/bootstrap/templates/agents/project-code-review.md +18 -0
- package/skills/bootstrap/templates/agents/project-discovery.md +18 -0
- package/skills/bootstrap/templates/agents/project-quality-gate.md +18 -0
- package/skills/brainstorm/SKILL.md +268 -0
- package/skills/brainstorm/soul.md +49 -0
- package/skills/claude-md-drift-check/SKILL.md +186 -0
- package/skills/claude-md-drift-check/checker.mjs +1380 -0
- package/skills/claude-md-drift-check/checker.sh +37 -0
- package/skills/claude-md-drift-check/package.json +16 -0
- package/skills/convergence-monitoring/README.md +39 -0
- package/skills/convergence-monitoring/SIGNALS.md +246 -0
- package/skills/convergence-monitoring/SKILL.md +285 -0
- package/skills/daily/SKILL.md +222 -0
- package/skills/daily/generate.sh +92 -0
- package/skills/daily/templates/daily.md.tpl +36 -0
- package/skills/debug/SKILL.md +188 -0
- package/skills/debug/soul.md +35 -0
- package/skills/discovery/SKILL.md +567 -0
- package/skills/discovery/issue-templates.md +237 -0
- package/skills/discovery/probes/docs-staleness.mjs +195 -0
- package/skills/discovery/probes/frontend-slop.mjs +186 -0
- package/skills/discovery/probes/ssot-code-diff.mjs +310 -0
- package/skills/discovery/probes/supply-chain-slopcheck.mjs +440 -0
- package/skills/discovery/probes/vault-narrative-staleness.mjs +355 -0
- package/skills/discovery/probes/vault-staleness.mjs +272 -0
- package/skills/discovery/probes-arch.md +252 -0
- package/skills/discovery/probes-audit.md +95 -0
- package/skills/discovery/probes-code.md +329 -0
- package/skills/discovery/probes-docs.md +76 -0
- package/skills/discovery/probes-feature.md +150 -0
- package/skills/discovery/probes-infra.md +138 -0
- package/skills/discovery/probes-intro.md +25 -0
- package/skills/discovery/probes-session.md +495 -0
- package/skills/discovery/probes-supply-chain.md +94 -0
- package/skills/discovery/probes-ui.md +147 -0
- package/skills/discovery/probes-vault.md +64 -0
- package/skills/discovery/slop-patterns.md +115 -0
- package/skills/dispatcher/SKILL.md +173 -0
- package/skills/docs-orchestrator/SKILL.md +362 -0
- package/skills/docs-orchestrator/audience-mapping.md +140 -0
- package/skills/domain-model/ADR-FORMAT.md +47 -0
- package/skills/domain-model/CONTEXT-FORMAT.md +77 -0
- package/skills/domain-model/SKILL.md +85 -0
- package/skills/ecosystem-health/SKILL.md +119 -0
- package/skills/ecosystem-health/wizard.md +193 -0
- package/skills/eval/SKILL.md +293 -0
- package/skills/eval/rubric-v1.md +218 -0
- package/skills/evolve/SKILL.md +546 -0
- package/skills/frontmatter-guard/SKILL.md +126 -0
- package/skills/gitlab-ops/SKILL.md +368 -0
- package/skills/gitlab-portfolio/SKILL.md +196 -0
- package/skills/grill/SKILL.md +185 -0
- package/skills/grill/soul.md +55 -0
- package/skills/hook-development/SKILL.md +413 -0
- package/skills/mcp-builder/SKILL.md +260 -0
- package/skills/memory-cleanup/SKILL.md +310 -0
- package/skills/mode-selector/SKILL.md +226 -0
- package/skills/peekaboo-driver/SKILL.md +237 -0
- package/skills/peekaboo-driver/soul.md +32 -0
- package/skills/persona-panel/SKILL.md +365 -0
- package/skills/persona-panel/persona-format.md +205 -0
- package/skills/persona-panel/presets/designer-lens.md +87 -0
- package/skills/persona-panel/presets/engineer-lens.md +88 -0
- package/skills/persona-panel/presets/pm-lens.md +86 -0
- package/skills/plan/SKILL.md +496 -0
- package/skills/plan/mode-feature.md +141 -0
- package/skills/plan/mode-new.md +297 -0
- package/skills/plan/mode-retro.md +271 -0
- package/skills/plan/prd-feature-template.md +132 -0
- package/skills/plan/prd-full-template.md +151 -0
- package/skills/plan/prd-reviewer-prompt.md +103 -0
- package/skills/plan/retro-template.md +75 -0
- package/skills/plan/soul.md +62 -0
- package/skills/playwright-driver/SKILL.md +226 -0
- package/skills/playwright-driver/soul.md +30 -0
- package/skills/quality-gates/SKILL.md +212 -0
- package/skills/reconcile/SKILL.md +324 -0
- package/skills/repo-audit/SKILL.md +272 -0
- package/skills/session-end/SKILL.md +1044 -0
- package/skills/session-end/discovery-scan.md +37 -0
- package/skills/session-end/drift-operations.md +97 -0
- package/skills/session-end/learning-patterns.md +78 -0
- package/skills/session-end/metrics-collection.md +175 -0
- package/skills/session-end/phase-3-2-docs-verification.md +148 -0
- package/skills/session-end/phase-3-6-tail.md +344 -0
- package/skills/session-end/phase-3-7a-recommendations.md +86 -0
- package/skills/session-end/plan-verification.md +288 -0
- package/skills/session-end/session-metrics-write.md +223 -0
- package/skills/session-end/vault-operations.md +50 -0
- package/skills/session-end/verification-checklist.md +20 -0
- package/skills/session-plan/SKILL.md +554 -0
- package/skills/session-plan/wave-template.md +37 -0
- package/skills/session-start/SKILL.md +1043 -0
- package/skills/session-start/phase-2-5-docs-planning.md +119 -0
- package/skills/session-start/phase-4-5-resource-health.md +49 -0
- package/skills/session-start/phase-7-1-premise-check.md +47 -0
- package/skills/session-start/phase-7-5-mode-selector.md +237 -0
- package/skills/session-start/phase-8-5-express-path.md +61 -0
- package/skills/session-start/presentation-format.md +81 -0
- package/skills/session-start/soul.md +57 -0
- package/skills/skill-creator/SKILL.md +168 -0
- package/skills/spinout/SKILL.md +76 -0
- package/skills/sunset-review/SKILL.md +96 -0
- package/skills/test-runner/SKILL.md +362 -0
- package/skills/test-runner/rubric-v1.md +388 -0
- package/skills/test-runner/soul.md +46 -0
- package/skills/tmux-layout/SKILL.md +104 -0
- package/skills/ubiquitous-language/SKILL.md +97 -0
- package/skills/using-orchestrator/SKILL.md +144 -0
- package/skills/vault-mirror/SKILL.md +234 -0
- package/skills/vault-sync/SKILL.md +319 -0
- package/skills/vault-sync/package-lock.json +40 -0
- package/skills/vault-sync/package.json +11 -0
- package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +8 -0
- package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +8 -0
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +8 -0
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +8 -0
- package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +8 -0
- package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +10 -0
- package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +8 -0
- package/skills/vault-sync/tests/fixtures/clean-vault/README.md +3 -0
- package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +11 -0
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +9 -0
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +8 -0
- package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +7 -0
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +9 -0
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +11 -0
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +3 -0
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +3 -0
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +11 -0
- package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +11 -0
- package/skills/vault-sync/tests/schema-drift.test.mjs +133 -0
- package/skills/vault-sync/validator.mjs +658 -0
- package/skills/vault-sync/validator.sh +55 -0
- package/skills/wave-executor/SKILL.md +496 -0
- package/skills/wave-executor/circuit-breaker.md +169 -0
- package/skills/wave-executor/wave-loop.md +1043 -0
- package/skills/write-executable-plan/SKILL.md +237 -0
- package/skills/write-executable-plan/plan-template.md +154 -0
- package/templates/_minimal/CLAUDE.md.tmpl +41 -0
- package/templates/_minimal/README.md.tmpl +15 -0
- package/templates/_minimal/gitignore.tmpl +47 -0
- package/templates/_shared/harte-regeln.md +16 -0
- package/templates/_shared/loop.md +90 -0
- package/templates/_shared/rules/parallel-sessions.md +77 -0
- package/templates/nextjs-minimal/README.md +30 -0
- package/templates/nextjs-minimal/app/layout.tsx +18 -0
- package/templates/nextjs-minimal/app/page.tsx +7 -0
- package/templates/nextjs-minimal/eslint.config.mjs +16 -0
- package/templates/nextjs-minimal/next.config.mjs +4 -0
- package/templates/nextjs-minimal/package.json +27 -0
- package/templates/nextjs-minimal/tsconfig.json +23 -0
- package/templates/node-minimal/README.md +33 -0
- package/templates/node-minimal/eslint.config.mjs +10 -0
- package/templates/node-minimal/package.json +21 -0
- package/templates/node-minimal/src/index.ts +1 -0
- package/templates/node-minimal/tests/sanity.test.ts +5 -0
- package/templates/node-minimal/tsconfig.json +17 -0
- package/templates/personas/README.md +150 -0
- package/templates/personas/accounting-compliance.v1.md +120 -0
- package/templates/personas/accounting-tax-advisor.v1.md +116 -0
- package/templates/personas/buyer-p1-cto.v1.md +125 -0
- package/templates/personas/buyer-p2-kanzlei.v1.md +134 -0
- package/templates/personas/buyer-p3-build.v1.md +130 -0
- package/templates/personas/buyer-p4-tech-veto.v1.md +130 -0
- package/templates/personas/buyer-p5-solo.v1.md +132 -0
- package/templates/personas/buyer-p6-ld.v1.md +130 -0
- package/templates/personas/klima-ai-expert.v1.md +114 -0
- package/templates/personas/klima-physicist.v1.md +117 -0
- package/templates/python-uv/README.md +28 -0
- package/templates/python-uv/pyproject.toml +32 -0
- package/templates/python-uv/src/__PROJECT_NAME__/__init__.py +0 -0
- package/templates/python-uv/src/__PROJECT_NAME__/main.py +6 -0
- package/templates/python-uv/tests/test_sanity.py +2 -0
- package/templates/static-html/README.md +19 -0
- package/templates/static-html/index.html +15 -0
- package/templates/static-html/script.js +1 -0
- package/templates/static-html/styles.css +26 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* layouts.mjs — tmux layout renderers for the session-orchestrator tmux-layout skill.
|
|
3
|
+
*
|
|
4
|
+
* Exports:
|
|
5
|
+
* renderDefaultLayout({ sessionName, force, projectRoot, vcsConfig? })
|
|
6
|
+
* renderDebugLayout({ sessionName, force, projectRoot })
|
|
7
|
+
*
|
|
8
|
+
* Default layout pane map (user-facing numbering):
|
|
9
|
+
* Pane 1 (top-left) — scratch shell (NO command — default tmux shell, AUQ-001 compliance)
|
|
10
|
+
* Pane 2 (top-right) — tail -F <stateDir>/STATE.md
|
|
11
|
+
* Pane 3 (bottom-right) — vcs-aware CI watch (poll-loop from detectVcsCommand)
|
|
12
|
+
* Pane 4 (bottom-left) — tail -F .orchestrator/metrics/events.jsonl | jq select(wave|gate|spiral)
|
|
13
|
+
* Pane 5 (optional) — agent-status telemetry (#565), only when withStatusPane is true:
|
|
14
|
+
* poll-loop over .orchestrator/runtime/agent-status-current.json
|
|
15
|
+
*
|
|
16
|
+
* Debug layout pane map (user-facing numbering):
|
|
17
|
+
* Pane 1 (top-left) — scratch shell (NO command — default tmux shell, AUQ-001 compliance)
|
|
18
|
+
* Pane 2 (top-right) — hypothesis-test runner: npm test -- --watch
|
|
19
|
+
* Pane 3 (bottom-right) — debug-artifact tail: tail -F .orchestrator/debug/*.md
|
|
20
|
+
* Pane 4 (bottom-left) — diff-watch: watch -n 2 'git diff --stat | head -30'
|
|
21
|
+
*
|
|
22
|
+
* Issues #561, #562 — ADR-0007 tmux-visualization substrate.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
import { resolveStateDir } from '../platform.mjs';
|
|
27
|
+
import { detectVcsCommand } from './vcs-detector.mjs';
|
|
28
|
+
import { isSessionCollision } from './tmux-shell.mjs';
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Telemetry wrapper — defensive import (P2 parallel agent owns telemetry.mjs)
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/** @type {(layoutName: string, fn: Function) => Function} */
|
|
35
|
+
let withTelemetry;
|
|
36
|
+
try {
|
|
37
|
+
// P2 owns scripts/lib/tmux-layout/telemetry.mjs — import defensively so that
|
|
38
|
+
// layouts.mjs works (without telemetry) even when P2's file has not landed yet.
|
|
39
|
+
({ withTelemetry } = await import('./telemetry.mjs'));
|
|
40
|
+
} catch {
|
|
41
|
+
// Fallback: identity wrapper — emits no telemetry but preserves the layout API.
|
|
42
|
+
// This code path is exercised during development and test runs before P2 ships.
|
|
43
|
+
withTelemetry = (_layoutName, fn) => fn;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Internal helpers
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Single-quote a shell command string for use as a tmux send-keys argument.
|
|
52
|
+
* Escapes embedded single-quotes using the POSIX `'...' '\'' '...'` pattern.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} s
|
|
55
|
+
* @returns {string} e.g. 'tail -F /path/to/STATE.md'
|
|
56
|
+
*/
|
|
57
|
+
function shellQuote(s) {
|
|
58
|
+
return "'" + String(s).replace(/'/g, "'\\''") + "'";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// renderDefaultLayout
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Render the default 4-pane tmux layout.
|
|
67
|
+
*
|
|
68
|
+
* Produces a one-liner shell command that the user pastes into a SECOND terminal
|
|
69
|
+
* (not the coordinator terminal). The coordinator terminal remains untouched.
|
|
70
|
+
*
|
|
71
|
+
* Collision policy (PSA-003):
|
|
72
|
+
* - If session already exists and --force is false → refuse with an error.
|
|
73
|
+
* - If session already exists and --force is true → kill it first.
|
|
74
|
+
*
|
|
75
|
+
* @param {{ sessionName: string, force: boolean, projectRoot: string, vcsConfig?: object, withStatusPane?: boolean }} ctx
|
|
76
|
+
* @returns {Promise<{ ok: boolean, oneliner: string, panes: number, degraded: boolean, attachCommand: string, error?: string }>}
|
|
77
|
+
*/
|
|
78
|
+
async function _renderDefaultLayoutInner({ sessionName, force, projectRoot, vcsConfig, withStatusPane = false }) {
|
|
79
|
+
// 1. Resolve STATE.md path: resolveStateDir() returns '.claude' / '.codex' / '.cursor'
|
|
80
|
+
// We intentionally do NOT hard-code projectRoot into the STATE.md path inside the
|
|
81
|
+
// one-liner — the user pastes the command in THEIR second terminal from the same
|
|
82
|
+
// project dir, so relative-from-cwd paths work. But for the tail -F of events.jsonl
|
|
83
|
+
// (which is relative) and STATE.md (also relative) we keep them relative.
|
|
84
|
+
const stateDirName = resolveStateDir(); // returns '.claude' | '.codex' | '.cursor'
|
|
85
|
+
const stateMdPath = path.join(stateDirName, 'STATE.md');
|
|
86
|
+
|
|
87
|
+
// 2. Resolve vcs command (Pane 3)
|
|
88
|
+
const vcs = detectVcsCommand({ config: vcsConfig, projectRoot });
|
|
89
|
+
|
|
90
|
+
// 3. Build pane commands (Pane 1 = scratch shell per AUQ-001 — no command sent, tmux uses default shell)
|
|
91
|
+
const pane2Cmd = `tail -F ${stateMdPath}`;
|
|
92
|
+
const pane3Cmd = vcs.command;
|
|
93
|
+
const pane4Cmd = `tail -F .orchestrator/metrics/events.jsonl | jq --unbuffered 'select(.event | test("wave|gate|spiral"))'`;
|
|
94
|
+
// Pane 5 (optional, #565): poll the LWW agent-status map. The `|| echo` fallback
|
|
95
|
+
// (mirrors Pane 3 style) keeps a missing file / absent jq from erroring the pane.
|
|
96
|
+
const pane5Cmd = `while true; do clear; jq . .orchestrator/runtime/agent-status-current.json 2>/dev/null || echo 'no agent-status yet — set persistence:true + run a wave (see skills/wave-executor/wave-loop.md § 3a-bis)'; sleep 2; done`;
|
|
97
|
+
|
|
98
|
+
// 4. Session-collision check
|
|
99
|
+
const collision = isSessionCollision(sessionName);
|
|
100
|
+
if (collision.exists && !force) {
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
oneliner: '',
|
|
104
|
+
panes: 0,
|
|
105
|
+
degraded: true,
|
|
106
|
+
attachCommand: '',
|
|
107
|
+
error: `Session '${sessionName}' already exists. Use --force to replace, or --session-name <other> to coexist (PSA-003).`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 5. Build one-liner segments. Commands are joined with ' && ' so any
|
|
112
|
+
// failure aborts the chain early (fail-fast is safer than silent partial setup).
|
|
113
|
+
const segments = [];
|
|
114
|
+
|
|
115
|
+
// Kill existing session if --force
|
|
116
|
+
if (collision.exists && force) {
|
|
117
|
+
segments.push(`tmux kill-session -t ${sessionName} 2>/dev/null || true`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Create new detached session (Pane 0 = user-facing Pane 1, the scratch shell)
|
|
121
|
+
segments.push(`tmux new-session -d -s ${sessionName}`);
|
|
122
|
+
|
|
123
|
+
// Pane 1 (tmux index 0.0): scratch shell — send 'clear' to tidy it up, no further command
|
|
124
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.0 'clear' Enter`);
|
|
125
|
+
|
|
126
|
+
// Pane 2 (tmux index 0.1): split horizontal on the window, run STATE.md tail
|
|
127
|
+
segments.push(`tmux split-window -h -t ${sessionName}:0`);
|
|
128
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.1 ${shellQuote(pane2Cmd)} Enter`);
|
|
129
|
+
|
|
130
|
+
// Pane 3 (tmux index 0.2): split vertically on Pane 2 (right side), run CI watch
|
|
131
|
+
segments.push(`tmux split-window -v -t ${sessionName}:0.1`);
|
|
132
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.2 ${shellQuote(pane3Cmd)} Enter`);
|
|
133
|
+
|
|
134
|
+
// Pane 4 (tmux index 0.3): split vertically on Pane 1 (left side), run events tail
|
|
135
|
+
segments.push(`tmux split-window -v -t ${sessionName}:0.0`);
|
|
136
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.3 ${shellQuote(pane4Cmd)} Enter`);
|
|
137
|
+
|
|
138
|
+
// Pane 5 (tmux index 0.4, optional #565): split off Pane 4, run agent-status poll-loop
|
|
139
|
+
if (withStatusPane) {
|
|
140
|
+
segments.push(`tmux split-window -v -t ${sessionName}:0.3`);
|
|
141
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.4 ${shellQuote(pane5Cmd)} Enter`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Select Pane 1 (scratch shell) as the active pane, then attach
|
|
145
|
+
segments.push(`tmux select-pane -t ${sessionName}:0.0`);
|
|
146
|
+
segments.push(`tmux attach-session -t ${sessionName}`);
|
|
147
|
+
|
|
148
|
+
const oneliner = segments.join(' && ');
|
|
149
|
+
const attachCommand = `tmux attach-session -t ${sessionName}`;
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
ok: true,
|
|
153
|
+
oneliner,
|
|
154
|
+
panes: withStatusPane ? 5 : 4,
|
|
155
|
+
// degraded = true when no vcs tool available (Pane 3 shows a help message instead)
|
|
156
|
+
degraded: vcs.bin === null,
|
|
157
|
+
attachCommand,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// renderDebugLayout — STUB (#562, deferred to W3 P1)
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* STUB for GitLab #562 — W3 P1 will implement the debug layout variant.
|
|
167
|
+
* For now returns a degraded result indicating not-yet-implemented.
|
|
168
|
+
*
|
|
169
|
+
* Signature MUST match renderDefaultLayout for uniform consumption by I2.
|
|
170
|
+
*
|
|
171
|
+
* @param {{ sessionName: string, force: boolean, projectRoot: string }} ctx
|
|
172
|
+
* @returns {Promise<{ ok: boolean, oneliner: string, panes: number, degraded: boolean, attachCommand: string, error?: string }>}
|
|
173
|
+
*/
|
|
174
|
+
async function _renderDebugLayoutInner({ sessionName, force, projectRoot: _projectRoot }) {
|
|
175
|
+
// Debug layout (4 panes — #562):
|
|
176
|
+
// Pane 1: scratch shell (AUQ-001)
|
|
177
|
+
// Pane 2: npm test --watch (hypothesis-test runner)
|
|
178
|
+
// Pane 3: tail -F .orchestrator/debug/*.md (debug-artifact tail)
|
|
179
|
+
// Pane 4: watch -n 2 'git diff --stat | head -30' (diff-watch)
|
|
180
|
+
|
|
181
|
+
const pane2Cmd = `npm test -- --watch 2>&1 | head -200`;
|
|
182
|
+
const pane3Cmd = `tail -F .orchestrator/debug/*.md 2>/dev/null || echo 'no .orchestrator/debug/*.md yet — companion to /debug skill Phase 2'`;
|
|
183
|
+
const pane4Cmd = `watch -n 2 'git diff --stat | head -30'`;
|
|
184
|
+
|
|
185
|
+
// Session-collision check (same policy as default layout — PSA-003)
|
|
186
|
+
const collision = isSessionCollision(sessionName);
|
|
187
|
+
if (collision.exists && !force) {
|
|
188
|
+
return {
|
|
189
|
+
ok: false,
|
|
190
|
+
oneliner: '',
|
|
191
|
+
panes: 0,
|
|
192
|
+
degraded: true,
|
|
193
|
+
attachCommand: '',
|
|
194
|
+
error: `Session '${sessionName}' already exists. Use --force to replace, or --session-name <other> to coexist (PSA-003).`,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const segments = [];
|
|
199
|
+
if (collision.exists && force) {
|
|
200
|
+
segments.push(`tmux kill-session -t ${sessionName} 2>/dev/null || true`);
|
|
201
|
+
}
|
|
202
|
+
segments.push(`tmux new-session -d -s ${sessionName}`);
|
|
203
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.0 'clear' Enter`);
|
|
204
|
+
segments.push(`tmux split-window -h -t ${sessionName}:0`);
|
|
205
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.1 ${shellQuote(pane2Cmd)} Enter`);
|
|
206
|
+
segments.push(`tmux split-window -v -t ${sessionName}:0.1`);
|
|
207
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.2 ${shellQuote(pane3Cmd)} Enter`);
|
|
208
|
+
segments.push(`tmux split-window -v -t ${sessionName}:0.0`);
|
|
209
|
+
segments.push(`tmux send-keys -t ${sessionName}:0.3 ${shellQuote(pane4Cmd)} Enter`);
|
|
210
|
+
segments.push(`tmux select-pane -t ${sessionName}:0.0`);
|
|
211
|
+
segments.push(`tmux attach-session -t ${sessionName}`);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
ok: true,
|
|
215
|
+
oneliner: segments.join(' && '),
|
|
216
|
+
panes: 4,
|
|
217
|
+
degraded: false,
|
|
218
|
+
attachCommand: `tmux attach-session -t ${sessionName}`,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Public exports — wrapped with telemetry for promotion-gate criteria (#563)
|
|
223
|
+
export const renderDefaultLayout = withTelemetry('default', _renderDefaultLayoutInner);
|
|
224
|
+
export const renderDebugLayout = withTelemetry('debug', _renderDebugLayoutInner);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/lib/tmux-layout/telemetry-stats.mjs
|
|
3
|
+
*
|
|
4
|
+
* Aggregator stub for /tmux-layout telemetry promotion gate (#563).
|
|
5
|
+
* Reads .orchestrator/metrics/events.jsonl and computes:
|
|
6
|
+
* - invocation count (total + per layout)
|
|
7
|
+
* - completion rate (completed / invoked) — promotion gate threshold 80%
|
|
8
|
+
* - top-K degradation reasons
|
|
9
|
+
* - meetsPromotionGate boolean (#563 acceptance criterion)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* - Programmatic: `import { computeStats, readTmuxEvents } from './telemetry-stats.mjs'`
|
|
13
|
+
* - CLI: `node scripts/lib/tmux-layout/telemetry-stats.mjs` (emits JSON to stdout)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
17
|
+
|
|
18
|
+
const EVENTS_PATH = '.orchestrator/metrics/events.jsonl';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Read events.jsonl and return tmux-layout-related events.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} [eventsPath=.orchestrator/metrics/events.jsonl]
|
|
24
|
+
* @returns {Array<object>} parsed event records (filtered to tmux-layout.* events)
|
|
25
|
+
*/
|
|
26
|
+
export function readTmuxEvents(eventsPath = EVENTS_PATH) {
|
|
27
|
+
if (!existsSync(eventsPath)) return [];
|
|
28
|
+
const raw = readFileSync(eventsPath, 'utf-8');
|
|
29
|
+
const lines = raw.split('\n').filter((l) => l.trim().length > 0);
|
|
30
|
+
return lines
|
|
31
|
+
.map((l) => {
|
|
32
|
+
try { return JSON.parse(l); } catch { return null; }
|
|
33
|
+
})
|
|
34
|
+
.filter((rec) => rec && typeof rec.event === 'string' && rec.event.startsWith('tmux-layout.'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Compute promotion-gate stats from tmux-layout events.
|
|
39
|
+
*
|
|
40
|
+
* @param {Array<object>} events output of readTmuxEvents()
|
|
41
|
+
* @returns {{
|
|
42
|
+
* invocations: number,
|
|
43
|
+
* completions: number,
|
|
44
|
+
* degradations: number,
|
|
45
|
+
* completionRate: number | null,
|
|
46
|
+
* byLayout: Record<string, {invoked: number, completed: number, degraded: number}>,
|
|
47
|
+
* topDegradationReasons: Array<{reason: string, count: number}>,
|
|
48
|
+
* meetsPromotionGate: boolean
|
|
49
|
+
* }}
|
|
50
|
+
*/
|
|
51
|
+
export function computeStats(events) {
|
|
52
|
+
const invocations = events.filter((e) => e.event === 'tmux-layout.invoked');
|
|
53
|
+
const completions = events.filter((e) => e.event === 'tmux-layout.completed');
|
|
54
|
+
const degradations = events.filter((e) => e.event === 'tmux-layout.degraded');
|
|
55
|
+
|
|
56
|
+
const byLayout = {};
|
|
57
|
+
const bump = (e, key) => {
|
|
58
|
+
const layout = e.layout ?? 'unknown';
|
|
59
|
+
byLayout[layout] ??= { invoked: 0, completed: 0, degraded: 0 };
|
|
60
|
+
byLayout[layout][key]++;
|
|
61
|
+
};
|
|
62
|
+
for (const e of invocations) bump(e, 'invoked');
|
|
63
|
+
for (const e of completions) bump(e, 'completed');
|
|
64
|
+
for (const e of degradations) bump(e, 'degraded');
|
|
65
|
+
|
|
66
|
+
const completionRate = invocations.length > 0
|
|
67
|
+
? completions.length / invocations.length
|
|
68
|
+
: null;
|
|
69
|
+
|
|
70
|
+
const reasonCounts = {};
|
|
71
|
+
for (const e of degradations) {
|
|
72
|
+
const reason = e.reason ?? 'unknown';
|
|
73
|
+
reasonCounts[reason] = (reasonCounts[reason] ?? 0) + 1;
|
|
74
|
+
}
|
|
75
|
+
const topDegradationReasons = Object.entries(reasonCounts)
|
|
76
|
+
.map(([reason, count]) => ({ reason, count }))
|
|
77
|
+
.sort((a, b) => b.count - a.count)
|
|
78
|
+
.slice(0, 5);
|
|
79
|
+
|
|
80
|
+
// Promotion gate (#563): >= 5 invocations AND completion rate >= 0.80
|
|
81
|
+
const meetsPromotionGate =
|
|
82
|
+
invocations.length >= 5 && (completionRate ?? 0) >= 0.80;
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
invocations: invocations.length,
|
|
86
|
+
completions: completions.length,
|
|
87
|
+
degradations: degradations.length,
|
|
88
|
+
completionRate,
|
|
89
|
+
byLayout,
|
|
90
|
+
topDegradationReasons,
|
|
91
|
+
meetsPromotionGate,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// CLI entry-point — emit stats as JSON to stdout when run directly
|
|
96
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
97
|
+
const events = readTmuxEvents();
|
|
98
|
+
const stats = computeStats(events);
|
|
99
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
100
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/lib/tmux-layout/telemetry.mjs
|
|
3
|
+
*
|
|
4
|
+
* Telemetry for the /tmux-layout skill — emits structured events to
|
|
5
|
+
* .orchestrator/metrics/events.jsonl for the promotion-gate criteria
|
|
6
|
+
* defined in GitLab #563 and docs/adr/0007-tmux-visualization-substrate.md.
|
|
7
|
+
*
|
|
8
|
+
* Three event types:
|
|
9
|
+
* - tmux-layout.invoked — fires before layout function runs
|
|
10
|
+
* - tmux-layout.completed — fires after layout function returns ok
|
|
11
|
+
* - tmux-layout.degraded — fires when layout returns ok:false OR throws
|
|
12
|
+
*
|
|
13
|
+
* Promotion gate (#563): invocation count >= 5 across >= 3 distinct deep
|
|
14
|
+
* sessions over >= 2 calendar weeks, layout-completion rate >= 80%, zero
|
|
15
|
+
* AUQ-001 / PSA-003 regressions. See ADR-0007 § Follow-ups.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { appendFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
|
|
21
|
+
const EVENTS_PATH = '.orchestrator/metrics/events.jsonl';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Emit a single tmux-layout event to events.jsonl.
|
|
25
|
+
* Best-effort — never throws (telemetry must not block the layout itself).
|
|
26
|
+
*
|
|
27
|
+
* @param {string} eventType - 'tmux-layout.invoked' | 'tmux-layout.degraded' | 'tmux-layout.completed'
|
|
28
|
+
* @param {object} [payload] - additional fields (layout, duration_ms, reason, etc.)
|
|
29
|
+
*/
|
|
30
|
+
export function emit(eventType, payload = {}) {
|
|
31
|
+
try {
|
|
32
|
+
const dir = path.dirname(EVENTS_PATH);
|
|
33
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
34
|
+
const record = {
|
|
35
|
+
event: eventType,
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
...payload,
|
|
38
|
+
};
|
|
39
|
+
appendFileSync(EVENTS_PATH, JSON.stringify(record) + '\n');
|
|
40
|
+
} catch {
|
|
41
|
+
// Best-effort — swallow all errors. Telemetry must not block layout.
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Wrap a layout function with telemetry. Emits invoked → completed/degraded.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} layoutName - 'default' | 'debug'
|
|
49
|
+
* @param {Function} fn - async function returning { ok, oneliner, panes, degraded, attachCommand, error? }
|
|
50
|
+
* @returns {Function} wrapped function with same signature
|
|
51
|
+
* @throws {TypeError} synchronously when fn is not a function
|
|
52
|
+
*/
|
|
53
|
+
export function withTelemetry(layoutName, fn) {
|
|
54
|
+
if (typeof fn !== 'function') {
|
|
55
|
+
throw new TypeError(`withTelemetry: fn must be a function (got ${typeof fn})`);
|
|
56
|
+
}
|
|
57
|
+
return async function telemetryWrapped(...args) {
|
|
58
|
+
const startedAt = Date.now();
|
|
59
|
+
emit('tmux-layout.invoked', { layout: layoutName });
|
|
60
|
+
try {
|
|
61
|
+
const result = await fn(...args);
|
|
62
|
+
const durationMs = Date.now() - startedAt;
|
|
63
|
+
if (result && result.ok === true) {
|
|
64
|
+
emit('tmux-layout.completed', {
|
|
65
|
+
layout: layoutName,
|
|
66
|
+
duration_ms: durationMs,
|
|
67
|
+
panes: result.panes ?? null,
|
|
68
|
+
degraded: result.degraded === true,
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
emit('tmux-layout.degraded', {
|
|
72
|
+
layout: layoutName,
|
|
73
|
+
duration_ms: durationMs,
|
|
74
|
+
reason: result?.error ?? 'unknown',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
} catch (err) {
|
|
79
|
+
const durationMs = Date.now() - startedAt;
|
|
80
|
+
emit('tmux-layout.degraded', {
|
|
81
|
+
layout: layoutName,
|
|
82
|
+
duration_ms: durationMs,
|
|
83
|
+
reason: `exception: ${err?.message ?? String(err)}`,
|
|
84
|
+
});
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tmux-shell.mjs — tmux availability detection + session-collision helpers.
|
|
3
|
+
*
|
|
4
|
+
* Issue #561 — ADR-0007 tmux-visualization substrate.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
|
|
9
|
+
const MIN_MAJOR = 3;
|
|
10
|
+
const MIN_MINOR = 0;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Detect tmux availability + version.
|
|
14
|
+
*
|
|
15
|
+
* Supports standard version strings ("tmux 3.4", "tmux 3.4a") and the
|
|
16
|
+
* "next-" prefix used in development builds ("tmux next-3.5").
|
|
17
|
+
*
|
|
18
|
+
* @returns {{ available: boolean, version: string|null, satisfiesMin: boolean, major?: number, minor?: number }}
|
|
19
|
+
*/
|
|
20
|
+
export function detectTmuxVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const raw = execSync('tmux -V', {
|
|
23
|
+
encoding: 'utf-8',
|
|
24
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
25
|
+
}).trim();
|
|
26
|
+
|
|
27
|
+
// Supports both "tmux 3.4a" (stable) and "tmux next-3.5" (development builds)
|
|
28
|
+
const match = raw.match(/^tmux\s+(?:next-)?(\d+)\.(\d+)([a-z])?/i);
|
|
29
|
+
if (!match) {
|
|
30
|
+
return { available: true, version: raw, satisfiesMin: false };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const major = parseInt(match[1], 10);
|
|
34
|
+
const minor = parseInt(match[2], 10);
|
|
35
|
+
const satisfiesMin =
|
|
36
|
+
major > MIN_MAJOR || (major === MIN_MAJOR && minor >= MIN_MINOR);
|
|
37
|
+
|
|
38
|
+
return { available: true, version: raw, satisfiesMin, major, minor };
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err.code === 'ENOENT' || err.status === 127) {
|
|
41
|
+
return { available: false, version: null, satisfiesMin: false };
|
|
42
|
+
}
|
|
43
|
+
// Other spawn errors — re-classify as unavailable to be safe
|
|
44
|
+
return { available: false, version: null, satisfiesMin: false };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check whether a tmux session with the given name already exists.
|
|
50
|
+
*
|
|
51
|
+
* Runs `tmux has-session -t <name>`: exit 0 means session found, exit 1 means not found.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} sessionName
|
|
54
|
+
* @returns {{ exists: boolean, error?: string }}
|
|
55
|
+
*/
|
|
56
|
+
export function isSessionCollision(sessionName) {
|
|
57
|
+
if (!sessionName || typeof sessionName !== 'string') {
|
|
58
|
+
return { exists: false, error: 'sessionName must be a non-empty string' };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
execSync(`tmux has-session -t ${shellQuote(sessionName)}`, {
|
|
63
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
64
|
+
});
|
|
65
|
+
return { exists: true }; // exit 0 means session found
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (err.status === 1) return { exists: false }; // exit 1 means no such session
|
|
68
|
+
if (err.code === 'ENOENT') return { exists: false, error: 'tmux not installed' };
|
|
69
|
+
return { exists: false, error: `tmux has-session failed: ${err.message}` };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Shell-quote a string for safe interpolation into a shell command.
|
|
75
|
+
* Uses single-quote wrapping with embedded single-quote escaping.
|
|
76
|
+
*
|
|
77
|
+
* @param {string} s
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
function shellQuote(s) {
|
|
81
|
+
return "'" + String(s).replace(/'/g, "'\\''") + "'";
|
|
82
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vcs-detector.mjs — Resolve the CI-watch pane command for the tmux default layout.
|
|
3
|
+
*
|
|
4
|
+
* Reads the `vcs:` key from Session Config and returns a poll-loop shell command
|
|
5
|
+
* suitable for Pane 3 (bottom-right). Both glab and gh are poll-based (not live-tail),
|
|
6
|
+
* so all commands are wrapped in a `while true; sleep` loop per D5 findings.
|
|
7
|
+
*
|
|
8
|
+
* Issue #561 — ADR-0007 tmux-visualization substrate.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the CI-watch pane command based on Session Config vcs: key.
|
|
13
|
+
*
|
|
14
|
+
* @param {{ config?: object, projectRoot: string }} args
|
|
15
|
+
* @returns {{ bin: 'glab'|'gh'|null, command: string, fallback: string, blocking: boolean, platform: 'gitlab'|'github'|null }}
|
|
16
|
+
* - command: the shell command for Pane 3 (wrapped in poll-loop since glab/gh are poll-based, not live-tail)
|
|
17
|
+
* - fallback: shell command shown when bin is not available in PATH
|
|
18
|
+
*/
|
|
19
|
+
export function detectVcsCommand({ config, projectRoot: _projectRoot }) {
|
|
20
|
+
const vcs = config?.vcs; // 'gitlab' | 'github' | undefined
|
|
21
|
+
|
|
22
|
+
if (vcs === 'gitlab') {
|
|
23
|
+
return {
|
|
24
|
+
bin: 'glab',
|
|
25
|
+
platform: 'gitlab',
|
|
26
|
+
blocking: true,
|
|
27
|
+
command: [
|
|
28
|
+
'while true; do',
|
|
29
|
+
' clear;',
|
|
30
|
+
' date;',
|
|
31
|
+
" echo '--- glab ci status (refresh: 15s) ---';",
|
|
32
|
+
' glab ci status --pipeline-id LATEST --output json 2>&1',
|
|
33
|
+
" | jq -r '.[] | \"\\(.status) \\(.name)\"' 2>/dev/null",
|
|
34
|
+
" || echo 'glab not available or no pipeline';",
|
|
35
|
+
' sleep 15;',
|
|
36
|
+
'done',
|
|
37
|
+
].join(' '),
|
|
38
|
+
fallback: [
|
|
39
|
+
'while true; do',
|
|
40
|
+
' clear;',
|
|
41
|
+
" echo 'glab not installed — install: brew install glab (macOS) / apt install glab (Linux)';",
|
|
42
|
+
' sleep 60;',
|
|
43
|
+
'done',
|
|
44
|
+
].join(' '),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (vcs === 'github') {
|
|
49
|
+
return {
|
|
50
|
+
bin: 'gh',
|
|
51
|
+
platform: 'github',
|
|
52
|
+
blocking: true,
|
|
53
|
+
command: [
|
|
54
|
+
'while true; do',
|
|
55
|
+
' clear;',
|
|
56
|
+
' date;',
|
|
57
|
+
" echo '--- gh pr checks --watch (will exit on PR completion) ---';",
|
|
58
|
+
' gh pr checks --watch 2>&1',
|
|
59
|
+
" || echo 'no PR in current branch';",
|
|
60
|
+
' sleep 15;',
|
|
61
|
+
'done',
|
|
62
|
+
].join(' '),
|
|
63
|
+
fallback: [
|
|
64
|
+
'while true; do',
|
|
65
|
+
' clear;',
|
|
66
|
+
" echo 'gh CLI not installed — install: brew install gh (macOS) / apt install gh (Linux)';",
|
|
67
|
+
' sleep 60;',
|
|
68
|
+
'done',
|
|
69
|
+
].join(' '),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// vcs unset or other value — show a static informational message
|
|
74
|
+
return {
|
|
75
|
+
bin: null,
|
|
76
|
+
platform: null,
|
|
77
|
+
blocking: false,
|
|
78
|
+
command: [
|
|
79
|
+
'while true; do',
|
|
80
|
+
' clear;',
|
|
81
|
+
" echo 'vcs: not configured in Session Config (CLAUDE.md / AGENTS.md on Codex CLI).';",
|
|
82
|
+
" echo 'Set vcs: gitlab or vcs: github to enable CI-watch in this pane.';",
|
|
83
|
+
' sleep 60;',
|
|
84
|
+
'done',
|
|
85
|
+
].join(' '),
|
|
86
|
+
fallback: '',
|
|
87
|
+
};
|
|
88
|
+
}
|