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,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* subagent-telemetry.mjs — SubagentStart + SubagentStop hook handler.
|
|
4
|
+
*
|
|
5
|
+
* Hook events: SubagentStart, SubagentStop (issue #342).
|
|
6
|
+
* Fires when a subagent lifecycle event occurs. Discriminates on
|
|
7
|
+
* `hook_event_name` to write either a 'start' or 'stop' record to
|
|
8
|
+
* `.orchestrator/metrics/subagents.jsonl`.
|
|
9
|
+
*
|
|
10
|
+
* Decision flow:
|
|
11
|
+
* 1. shouldRunHook gate — exit 0 immediately when the hook is disabled.
|
|
12
|
+
* 2. Read JSON payload from stdin: { hook_event_name, agent_id?, subagent_id?,
|
|
13
|
+
* agent_type?, subagent_type?, parent_session_id?, session_id?,
|
|
14
|
+
* duration_ms?, transcript_path? }.
|
|
15
|
+
* 3. Discriminate on hook_event_name → event: 'start' | 'stop'.
|
|
16
|
+
* 4. For stop events, parse the subagent transcript at `transcript_path` to
|
|
17
|
+
* recover token_input / token_output (#624). The harness does NOT send
|
|
18
|
+
* token_input / token_output on stdin — they must be extracted from the
|
|
19
|
+
* transcript's per-assistant-turn `message.usage` blocks, deduped by
|
|
20
|
+
* requestId (streaming snapshots repeat the same requestId ~4-5×).
|
|
21
|
+
* 5. Build canonical record and call appendSubagent().
|
|
22
|
+
* 6. Output: nothing on stdout. Diagnostic errors to stderr only.
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 always (informational, never blocking).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { shouldRunHook } from './_lib/profile-gate.mjs';
|
|
28
|
+
// Exit 0 immediately when disabled via SO_HOOK_PROFILE / SO_DISABLED_HOOKS.
|
|
29
|
+
if (!shouldRunHook('subagent-telemetry')) process.exit(0);
|
|
30
|
+
|
|
31
|
+
import fs from 'node:fs';
|
|
32
|
+
import path from 'node:path';
|
|
33
|
+
import { appendSubagent } from '../scripts/lib/subagents-schema.mjs';
|
|
34
|
+
import { SO_PROJECT_DIR } from '../scripts/lib/platform.mjs';
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Constants
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
const JSONL_PATH = path.join(SO_PROJECT_DIR, '.orchestrator', 'metrics', 'subagents.jsonl');
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Defense-in-depth byte ceiling for transcript reads (#624). The transcript path
|
|
44
|
+
* is harness-trusted, so this is not an exploitable vector — but the repo follows
|
|
45
|
+
* a bounded-read discipline: a pathologically large transcript is skipped (yields
|
|
46
|
+
* the empty/zero-usage result) rather than read whole into memory.
|
|
47
|
+
*/
|
|
48
|
+
const MAX_TRANSCRIPT_BYTES = 50 * 1024 * 1024; // ~50 MB
|
|
49
|
+
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Helpers
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Read stdin to EOF (best-effort). Returns parsed JSON or null on failure.
|
|
56
|
+
* Uses a 5 s timeout consistent with Claude Code hook contract.
|
|
57
|
+
*
|
|
58
|
+
* @returns {Promise<object|null>}
|
|
59
|
+
*/
|
|
60
|
+
function readStdinJson() {
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
if (process.stdin.readableEnded || process.stdin.closed) {
|
|
63
|
+
resolve(null);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const chunks = [];
|
|
67
|
+
const timer = setTimeout(() => { resolve(null); }, 5_000);
|
|
68
|
+
process.stdin.setEncoding('utf8');
|
|
69
|
+
process.stdin.on('data', (c) => chunks.push(c));
|
|
70
|
+
process.stdin.on('end', () => {
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
const raw = chunks.join('').trim();
|
|
73
|
+
if (!raw) { resolve(null); return; }
|
|
74
|
+
try { resolve(JSON.parse(raw)); } catch { resolve(null); }
|
|
75
|
+
});
|
|
76
|
+
process.stdin.on('error', () => { clearTimeout(timer); resolve(null); });
|
|
77
|
+
process.stdin.resume();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Extract deduped token totals from a subagent transcript JSONL file (#624).
|
|
83
|
+
*
|
|
84
|
+
* On SubagentStop the harness supplies `transcript_path`. Each
|
|
85
|
+
* `{"type":"assistant"}` line carries a `message.usage` block with
|
|
86
|
+
* `{ input_tokens, output_tokens, ... }`. Streaming snapshots repeat the SAME
|
|
87
|
+
* `requestId` across consecutive assistant lines, so a naive Σ over every line
|
|
88
|
+
* double-counts (observed ~4-5× on real transcripts). The correct recipe is to
|
|
89
|
+
* group by `requestId`, keep ONE usage block per id (the first), then sum.
|
|
90
|
+
*
|
|
91
|
+
* token_input is the raw `input_tokens` sum (NOT folded with cache_* fields) to
|
|
92
|
+
* match the existing OTel `gen_ai.usage.input_tokens` semantic.
|
|
93
|
+
*
|
|
94
|
+
* Per-turn clamping (#624): a single poisoned usage value (negative, NaN, or a
|
|
95
|
+
* non-integer such as 10.5) MUST NOT discard the otherwise-good turns. Each turn's
|
|
96
|
+
* contribution is added ONLY when it is a non-negative integer; an invalid value
|
|
97
|
+
* is skipped (its turn still counts toward `counted` so a transcript of mixed
|
|
98
|
+
* good/bad turns yields the sum of the GOOD turns, never null). Without per-turn
|
|
99
|
+
* clamping, a final `Number.isInteger(sum) && sum >= 0` aggregate check would
|
|
100
|
+
* nuke the whole input sum to null on one bad value.
|
|
101
|
+
*
|
|
102
|
+
* Dedup assumption (#624): the streaming harness always supplies a `requestId` on
|
|
103
|
+
* assistant turns, so dedup keys on it. A turn with NO requestId is counted
|
|
104
|
+
* individually (no dedup) — this is the documented forward-compat fallback, not a
|
|
105
|
+
* double-count, because the harness never omits requestId in practice.
|
|
106
|
+
*
|
|
107
|
+
* Partial-usage assumption (#624): a turn carrying `input_tokens` but no
|
|
108
|
+
* `output_tokens` (or vice-versa) contributes 0 to the absent side — NOT null —
|
|
109
|
+
* so the present side still sums and the aggregate stays valid.
|
|
110
|
+
*
|
|
111
|
+
* NEVER throws. Any failure (missing/unreadable path, 0 assistant turns, parse
|
|
112
|
+
* error) yields { tokenInput: null, tokenOutput: null } so the hook still exits 0.
|
|
113
|
+
*
|
|
114
|
+
* @param {string|undefined|null} transcriptPath — absolute path from stdin
|
|
115
|
+
* @returns {{ tokenInput: number|null, tokenOutput: number|null }}
|
|
116
|
+
*/
|
|
117
|
+
function extractTranscriptUsage(transcriptPath) {
|
|
118
|
+
const nullResult = { tokenInput: null, tokenOutput: null };
|
|
119
|
+
try {
|
|
120
|
+
if (typeof transcriptPath !== 'string' || !transcriptPath.trim()) return nullResult;
|
|
121
|
+
if (!fs.existsSync(transcriptPath)) return nullResult;
|
|
122
|
+
|
|
123
|
+
// Bounded-read guard (#624): skip an oversized transcript gracefully rather
|
|
124
|
+
// than read the whole file into memory. statSync failure (race/unreadable)
|
|
125
|
+
// falls through to the readFileSync attempt below — both stay inside the
|
|
126
|
+
// no-throw try/catch, so the worst case is still nullResult, never a throw.
|
|
127
|
+
const { size } = fs.statSync(transcriptPath);
|
|
128
|
+
if (size > MAX_TRANSCRIPT_BYTES) return nullResult;
|
|
129
|
+
|
|
130
|
+
const raw = fs.readFileSync(transcriptPath, 'utf8');
|
|
131
|
+
const lines = raw.split('\n');
|
|
132
|
+
|
|
133
|
+
const seen = new Set();
|
|
134
|
+
let tokenInput = 0;
|
|
135
|
+
let tokenOutput = 0;
|
|
136
|
+
let counted = 0;
|
|
137
|
+
|
|
138
|
+
for (const line of lines) {
|
|
139
|
+
const trimmed = line.trim();
|
|
140
|
+
if (!trimmed) continue;
|
|
141
|
+
let obj;
|
|
142
|
+
try {
|
|
143
|
+
obj = JSON.parse(trimmed);
|
|
144
|
+
} catch {
|
|
145
|
+
continue; // skip a single malformed line, keep parsing the rest
|
|
146
|
+
}
|
|
147
|
+
if (!obj || obj.type !== 'assistant') continue;
|
|
148
|
+
const usage = obj.message?.usage;
|
|
149
|
+
if (!usage || typeof usage !== 'object') continue;
|
|
150
|
+
|
|
151
|
+
// Dedup by requestId — keep the first usage block per id.
|
|
152
|
+
const requestId = obj.requestId;
|
|
153
|
+
if (typeof requestId === 'string' && requestId) {
|
|
154
|
+
if (seen.has(requestId)) continue;
|
|
155
|
+
seen.add(requestId);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Per-turn clamp (#624): add a turn's value ONLY when it is a non-negative
|
|
159
|
+
// integer. A poisoned value (negative, NaN, float like 10.5) is skipped so
|
|
160
|
+
// the good turns survive. An absent side contributes 0, not null.
|
|
161
|
+
const inTok = usage.input_tokens;
|
|
162
|
+
const outTok = usage.output_tokens;
|
|
163
|
+
if (Number.isInteger(inTok) && inTok >= 0) tokenInput += inTok;
|
|
164
|
+
if (Number.isInteger(outTok) && outTok >= 0) tokenOutput += outTok;
|
|
165
|
+
counted += 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// No assistant turns with usage → leave fields null (forward-compat).
|
|
169
|
+
if (counted === 0) return nullResult;
|
|
170
|
+
|
|
171
|
+
// The aggregate is guaranteed a non-negative integer by per-turn clamping
|
|
172
|
+
// above (Σ of non-negative integers), so emit it directly.
|
|
173
|
+
return {
|
|
174
|
+
tokenInput,
|
|
175
|
+
tokenOutput,
|
|
176
|
+
};
|
|
177
|
+
} catch {
|
|
178
|
+
return nullResult;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Main
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
async function main() {
|
|
187
|
+
const input = await readStdinJson();
|
|
188
|
+
if (!input) return;
|
|
189
|
+
|
|
190
|
+
const eventName = input.hook_event_name;
|
|
191
|
+
const event = eventName === 'SubagentStart' ? 'start' : 'stop';
|
|
192
|
+
|
|
193
|
+
// Pick the first non-empty trimmed string from the candidate keys, or the fallback.
|
|
194
|
+
const firstNonEmptyString = (keys, fallback) => {
|
|
195
|
+
for (const k of keys) {
|
|
196
|
+
const v = input[k];
|
|
197
|
+
if (typeof v === 'string' && v.trim()) return v;
|
|
198
|
+
}
|
|
199
|
+
return fallback;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Resolve identifiers from either naming convention the harness may use.
|
|
203
|
+
const agentId = firstNonEmptyString(['agent_id', 'subagent_id'], 'unknown');
|
|
204
|
+
const agentType = firstNonEmptyString(['agent_type', 'subagent_type'], null);
|
|
205
|
+
const parentSessionId = firstNonEmptyString(['parent_session_id', 'session_id'], null);
|
|
206
|
+
|
|
207
|
+
/** @type {object} */
|
|
208
|
+
const record = {
|
|
209
|
+
timestamp: new Date().toISOString(),
|
|
210
|
+
event,
|
|
211
|
+
agent_id: agentId,
|
|
212
|
+
schema_version: 1,
|
|
213
|
+
...(agentType !== null ? { agent_type: agentType } : {}),
|
|
214
|
+
...(parentSessionId !== null ? { parent_session_id: parentSessionId } : {}),
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
if (event === 'stop') {
|
|
218
|
+
// duration_ms is required for stop events; default to 0 if harness omits it.
|
|
219
|
+
record.duration_ms =
|
|
220
|
+
typeof input.duration_ms === 'number' && input.duration_ms >= 0
|
|
221
|
+
? Math.round(input.duration_ms)
|
|
222
|
+
: 0;
|
|
223
|
+
|
|
224
|
+
// Tokens are NOT sent on stdin (#624) — recover them from the transcript's
|
|
225
|
+
// per-assistant-turn usage blocks, deduped by requestId. Any failure → null.
|
|
226
|
+
const { tokenInput, tokenOutput } = extractTranscriptUsage(input.transcript_path);
|
|
227
|
+
if (tokenInput !== null) record.token_input = tokenInput;
|
|
228
|
+
if (tokenOutput !== null) record.token_output = tokenOutput;
|
|
229
|
+
|
|
230
|
+
// Cost is best-effort / forward-compat (#624): the native transcript does
|
|
231
|
+
// NOT expose total_cost_usd today, so this is null in practice. No rate
|
|
232
|
+
// table — use the native cost only, default null when absent.
|
|
233
|
+
const totalCostUsd =
|
|
234
|
+
typeof input.total_cost_usd === 'number' && Number.isFinite(input.total_cost_usd) && input.total_cost_usd >= 0
|
|
235
|
+
? input.total_cost_usd
|
|
236
|
+
: null;
|
|
237
|
+
record.total_cost_usd = totalCostUsd;
|
|
238
|
+
|
|
239
|
+
// OTel alias — #411 additive, schema_version=1 backwards-compat
|
|
240
|
+
record['gen_ai.usage.input_tokens'] = tokenInput;
|
|
241
|
+
record['gen_ai.usage.output_tokens'] = tokenOutput;
|
|
242
|
+
record['gen_ai.system'] = 'anthropic';
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
await appendSubagent(JSONL_PATH, record);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Exit 0 always — informational hook must never block Claude.
|
|
249
|
+
main().catch(() => {}).finally(() => process.exit(0));
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// hooks/wave-scope-commit-guard.mjs
|
|
3
|
+
//
|
|
4
|
+
// PSA-004 sub-mode B + sub-mode C guard: runs at pre-commit time and rejects
|
|
5
|
+
// the commit when staged paths violate either the active wave-scope.json
|
|
6
|
+
// allowedPaths (sub-mode B) or the cross-agent staging-fence (sub-mode C).
|
|
7
|
+
//
|
|
8
|
+
// Sub-mode B — lint-staged sweep
|
|
9
|
+
// lint-staged's eslint --fix / prettier --write step touches files matching
|
|
10
|
+
// its globs in package.json (not just the agent's staged set) and re-stages
|
|
11
|
+
// them via internal `git add`. PreToolUse Edit/Write gates never see these
|
|
12
|
+
// files. This guard catches them at the very last moment before the commit
|
|
13
|
+
// object is created.
|
|
14
|
+
//
|
|
15
|
+
// Sub-mode C — concurrent git-add race (issue #552)
|
|
16
|
+
// Two wave-agents in the same repo can both `git add` overlapping paths
|
|
17
|
+
// between each other's `git diff --cached` and `git commit`. Each individual
|
|
18
|
+
// `git add` is recorded by hooks/pre-bash-staging-fence.mjs in a per-agent
|
|
19
|
+
// fence file under .orchestrator/staging-fence/<agent-id>.json. At commit
|
|
20
|
+
// time this guard walks ALL fence files (under a withStagingFenceLock mutex)
|
|
21
|
+
// and rejects the commit when ANY staged path is also recorded in a SIBLING
|
|
22
|
+
// agent's fence — i.e. another agent's intent to stage that path.
|
|
23
|
+
//
|
|
24
|
+
// Behavior summary
|
|
25
|
+
// - No .orchestrator/wave-scope.json → exit 0 (no active wave; sub-mode B
|
|
26
|
+
// short-circuits). Sub-mode C still runs if a fence directory exists.
|
|
27
|
+
// - Allowed paths violation → exit 1 with restore hint.
|
|
28
|
+
// - Cross-agent fence overlap → exit 1 with "staging-fence: cross-agent
|
|
29
|
+
// overlap" stderr.
|
|
30
|
+
// - --no-verify bypass: this hook is invoked as a git pre-commit hook;
|
|
31
|
+
// `git commit --no-verify` skips it entirely (operator opts out by name).
|
|
32
|
+
|
|
33
|
+
import { execSync } from 'node:child_process';
|
|
34
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
35
|
+
import { join } from 'node:path';
|
|
36
|
+
|
|
37
|
+
// Re-use existing helpers from scripts/lib/hardening.mjs.
|
|
38
|
+
// IMPORTANT: import is resolved relative to THIS file's location (the hook
|
|
39
|
+
// ships with the session-orchestrator package), NOT relative to the git
|
|
40
|
+
// repo it is protecting. The two diverge when the hook is invoked from a
|
|
41
|
+
// consumer repo or a test tmp-dir.
|
|
42
|
+
import { pathMatchesPattern, findScopeFile } from '../scripts/lib/hardening.mjs';
|
|
43
|
+
import { withStagingFenceLock } from '../scripts/lib/session-lock.mjs';
|
|
44
|
+
|
|
45
|
+
const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
46
|
+
// #801: resolve wave-scope.json via the same precedence every other reader
|
|
47
|
+
// uses (.pi/.cursor/.codex/.claude — scope-gate.mjs findScopeFile). The prior
|
|
48
|
+
// hardcoded `.orchestrator/wave-scope.json` path was DEAD — the coordinator
|
|
49
|
+
// writes wave-scope.json to the state dir (.claude/ on Claude Code; see
|
|
50
|
+
// skills/wave-executor/wave-loop.md), so this guard never fired. findScopeFile
|
|
51
|
+
// returns null when no scope file exists at any precedence dir, preserving
|
|
52
|
+
// the "no active wave → exit 0" semantics below.
|
|
53
|
+
const scopePath = findScopeFile(repoRoot);
|
|
54
|
+
const fenceDir = join(repoRoot, '.orchestrator', 'staging-fence');
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Sub-mode B — allowedPaths check
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
const stagedOutput = execSync('git diff --cached --name-only', { encoding: 'utf8' });
|
|
61
|
+
const stagedFiles = stagedOutput.split('\n').filter(Boolean);
|
|
62
|
+
|
|
63
|
+
if (scopePath) {
|
|
64
|
+
let scope;
|
|
65
|
+
try {
|
|
66
|
+
scope = JSON.parse(readFileSync(scopePath, 'utf8'));
|
|
67
|
+
} catch (err) {
|
|
68
|
+
process.stderr.write(`wave-scope-commit-guard: failed to parse wave-scope.json: ${err.message}\n`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const allowedPaths = Array.isArray(scope.allowedPaths) ? scope.allowedPaths : [];
|
|
73
|
+
if (allowedPaths.length > 0) {
|
|
74
|
+
const violations = stagedFiles.filter(
|
|
75
|
+
(f) => !allowedPaths.some((pattern) => pathMatchesPattern(f, pattern)),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (violations.length > 0) {
|
|
79
|
+
process.stderr.write('✗ wave-scope-commit-guard: staged paths outside wave-scope.allowedPaths:\n');
|
|
80
|
+
for (const v of violations) process.stderr.write(` - ${v}\n`);
|
|
81
|
+
process.stderr.write('\nThese files were likely added by lint-staged eslint --fix / prettier --write.\n');
|
|
82
|
+
process.stderr.write('To proceed:\n');
|
|
83
|
+
process.stderr.write(' 1) git restore --staged <path> # for each foreign path\n');
|
|
84
|
+
process.stderr.write(' 2) git commit # retry\n');
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Sub-mode C — cross-agent staging-fence reconciliation (issue #552)
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
//
|
|
94
|
+
// Skip entirely when no fence dir exists OR no staged files. The fence dir
|
|
95
|
+
// only appears when a wave-agent invoked `git add` while SO_WAVE_AGENT=1.
|
|
96
|
+
// Manual / coordinator commits never write a fence file, so this branch
|
|
97
|
+
// short-circuits to exit 0 for them (AC5 safe-default).
|
|
98
|
+
if (!existsSync(fenceDir) || stagedFiles.length === 0) {
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Resolve the "current" agent id from SO_WAVE_AGENT_ID (when set by the
|
|
103
|
+
// caller) or fall back to a PID-derived marker. The fence files themselves
|
|
104
|
+
// embed the agent_id; the env-var is only used to skip THIS agent's own
|
|
105
|
+
// fence entries (we cross-check against SIBLINGS, not ourselves).
|
|
106
|
+
const ownAgentId = process.env.SO_WAVE_AGENT_ID ?? null;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Build a regex that finds a staged path inside a `git add` command string.
|
|
110
|
+
* Word-boundary on both sides so `src/foo.ts` does not match `src/foo.ts.bak`.
|
|
111
|
+
* The path is escaped so glob metacharacters (`*`, `?`) and shell metas
|
|
112
|
+
* cannot be reinterpreted.
|
|
113
|
+
*/
|
|
114
|
+
function pathRegex(p) {
|
|
115
|
+
const escaped = p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
116
|
+
return new RegExp(`(?:^|[\\s'"])${escaped}(?:$|[\\s'"])`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Walk a single sibling fence file and return the staged paths whose path
|
|
121
|
+
* pattern matches any of our staged files.
|
|
122
|
+
*/
|
|
123
|
+
function findOverlaps(fenceJsonPath, ourStaged) {
|
|
124
|
+
let body;
|
|
125
|
+
try {
|
|
126
|
+
body = JSON.parse(readFileSync(fenceJsonPath, 'utf8'));
|
|
127
|
+
} catch {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
if (!body || typeof body !== 'object') return [];
|
|
131
|
+
if (!Array.isArray(body.staged_paths)) return [];
|
|
132
|
+
if (ownAgentId && body.agent_id === ownAgentId) return []; // skip self
|
|
133
|
+
|
|
134
|
+
const matches = [];
|
|
135
|
+
for (const entry of body.staged_paths) {
|
|
136
|
+
const cmd = entry?.command;
|
|
137
|
+
if (typeof cmd !== 'string') continue;
|
|
138
|
+
for (const ours of ourStaged) {
|
|
139
|
+
if (pathRegex(ours).test(cmd)) {
|
|
140
|
+
matches.push({ ourPath: ours, siblingAgent: body.agent_id ?? '<unknown>', cmd });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return matches;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let overlaps = [];
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
await withStagingFenceLock(
|
|
151
|
+
repoRoot,
|
|
152
|
+
async () => {
|
|
153
|
+
let entries;
|
|
154
|
+
try {
|
|
155
|
+
entries = readdirSync(fenceDir);
|
|
156
|
+
} catch {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
for (const name of entries) {
|
|
160
|
+
if (!name.endsWith('.json')) continue;
|
|
161
|
+
if (name.startsWith('.')) continue; // skip .commit.lock, tmp files
|
|
162
|
+
const overlapsFromFile = findOverlaps(join(fenceDir, name), stagedFiles);
|
|
163
|
+
overlaps = overlaps.concat(overlapsFromFile);
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{ timeoutMs: 5000 },
|
|
167
|
+
);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
// Lock acquisition failed — emit a warning but do NOT block the commit.
|
|
170
|
+
// The race-detection layer is opportunistic; a lock-acquire timeout is
|
|
171
|
+
// strictly less severe than blocking a legitimate commit on flaky FS.
|
|
172
|
+
process.stderr.write(
|
|
173
|
+
`⚠ wave-scope-commit-guard: staging-fence lock failed — ${err?.message ?? err}\n`,
|
|
174
|
+
);
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (overlaps.length > 0) {
|
|
179
|
+
process.stderr.write('✗ wave-scope-commit-guard: staging-fence: cross-agent overlap detected:\n');
|
|
180
|
+
for (const o of overlaps) {
|
|
181
|
+
process.stderr.write(` - ${o.ourPath} (also staged by sibling agent ${o.siblingAgent})\n`);
|
|
182
|
+
}
|
|
183
|
+
process.stderr.write('\nAnother wave-agent recorded a `git add` for one or more of your staged paths.\n');
|
|
184
|
+
process.stderr.write('To proceed:\n');
|
|
185
|
+
process.stderr.write(' 1) Coordinate with the sibling agent OR\n');
|
|
186
|
+
process.stderr.write(' 2) git restore --staged <path> # for each conflicting path, then retry\n');
|
|
187
|
+
process.stderr.write(' 3) git commit --no-verify # bypass (PSA-001/PSA-003 risk — operator opt-out)\n');
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
process.exit(0);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "ecosystem-health",
|
|
4
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}\"/scripts/lib/ecosystem-health.mjs --watch",
|
|
5
|
+
"description": "Ecosystem repo health watcher (CI status, branch drift, stale baselines across vault-registered projects). Emits one NDJSON line per detected state change.",
|
|
6
|
+
"when": "on-skill-invoke:ecosystem-health"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "convergence-monitor",
|
|
10
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}\"/scripts/lib/convergence-monitor.mjs --tail",
|
|
11
|
+
"description": "Wave convergence telemetry monitor — tails .orchestrator/metrics/events.jsonl + sessions.jsonl, surfaces convergence signals (shrinking diff, pass-rate plateau, velocity).",
|
|
12
|
+
"when": "on-skill-invoke:wave-executor"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Finding Report Style
|
|
2
|
+
|
|
3
|
+
Use this format for discovery probes and code analysis findings.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
### Finding Header
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
### [{severity}] {title}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Severity levels: `critical`, `high`, `medium`, `low`, `info`
|
|
14
|
+
|
|
15
|
+
### Finding Body
|
|
16
|
+
|
|
17
|
+
| Field | Value |
|
|
18
|
+
|-------|-------|
|
|
19
|
+
| Severity | `{level}` |
|
|
20
|
+
| Confidence | `{high\|medium\|low}` |
|
|
21
|
+
| File | `{path}:{line}` |
|
|
22
|
+
| Issue | GL#{n} (if applicable) |
|
|
23
|
+
|
|
24
|
+
### Description
|
|
25
|
+
|
|
26
|
+
One paragraph maximum. What was found and why it matters.
|
|
27
|
+
|
|
28
|
+
### Evidence
|
|
29
|
+
|
|
30
|
+
Code snippet with file reference:
|
|
31
|
+
|
|
32
|
+
```{lang}
|
|
33
|
+
// path/to/file.ts:42
|
|
34
|
+
<relevant code>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Recommendation
|
|
38
|
+
|
|
39
|
+
One-line fix suggestion. Link to docs or patterns if applicable.
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
- Severity + confidence always visible — drives prioritization
|
|
44
|
+
- One finding per block — never combine multiple issues
|
|
45
|
+
- Evidence is mandatory — no findings without code references
|
|
46
|
+
- Recommendations are actionable — "rename X to Y" not "consider renaming"
|
|
47
|
+
- Sort by severity descending within a report
|
|
48
|
+
- Keep description under 3 sentences
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Session Report Style
|
|
2
|
+
|
|
3
|
+
Use this format for session-start presentations and session-end summaries.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
### Session Overview Table
|
|
8
|
+
|
|
9
|
+
| Field | Value |
|
|
10
|
+
|-------|-------|
|
|
11
|
+
| Type | `{housekeeping\|feature\|deep}` |
|
|
12
|
+
| Repo | `{name}` on `{branch}` |
|
|
13
|
+
| Git | {uncommitted} uncommitted, {unpushed} unpushed, {branches} branches |
|
|
14
|
+
| GitLab | {open} open issues ({high} high), {mrs} open MRs |
|
|
15
|
+
| Health | Tests: {status} \| Validator: {status} \| CI: {status} |
|
|
16
|
+
|
|
17
|
+
### Findings Section
|
|
18
|
+
|
|
19
|
+
Use bullet points with status icons:
|
|
20
|
+
- Items requiring action
|
|
21
|
+
- Observations and context
|
|
22
|
+
|
|
23
|
+
Status icons: `pass` / `fail` / `warn` / `info` / `skip`
|
|
24
|
+
|
|
25
|
+
### Recommendations
|
|
26
|
+
|
|
27
|
+
Present as numbered options with clear rationale:
|
|
28
|
+
|
|
29
|
+
1. **Option A (recommended):** Description — why this is best
|
|
30
|
+
2. **Option B:** Description — trade-offs
|
|
31
|
+
|
|
32
|
+
### Scope Table (session-end)
|
|
33
|
+
|
|
34
|
+
| Issue | Status | Summary |
|
|
35
|
+
|-------|--------|---------|
|
|
36
|
+
| GL#{n} | done/partial/deferred | One-line description |
|
|
37
|
+
|
|
38
|
+
### Metrics (session-end)
|
|
39
|
+
|
|
40
|
+
| Metric | Value |
|
|
41
|
+
|--------|-------|
|
|
42
|
+
| Files changed | {n} |
|
|
43
|
+
| Tests | {n} passing |
|
|
44
|
+
| Commits | {n} pushed |
|
|
45
|
+
| Duration | {estimate} |
|
|
46
|
+
|
|
47
|
+
## Rules
|
|
48
|
+
|
|
49
|
+
- Tables over prose — scannable beats readable
|
|
50
|
+
- One line per finding — no multi-paragraph explanations
|
|
51
|
+
- Link issues as `GL#{n}` — clickable in GitLab context
|
|
52
|
+
- Quantify everything — "3 issues" not "several issues"
|
|
53
|
+
- Lead with status — good news first, then blockers
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Wave Summary Style
|
|
2
|
+
|
|
3
|
+
Use this format for wave completion reports between waves.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
### Header
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
## Wave {N}/{total} Complete
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Agent Status Table
|
|
14
|
+
|
|
15
|
+
| Agent | Task | Status | Files |
|
|
16
|
+
|-------|------|--------|-------|
|
|
17
|
+
| {agent-name} | {1-line task} | done/partial/failed | {file list} |
|
|
18
|
+
|
|
19
|
+
### Quality Gate Results
|
|
20
|
+
|
|
21
|
+
- Tests: {n} passing, {n} failing
|
|
22
|
+
- Validator: {n}/{n} checks
|
|
23
|
+
- TypeScript: {n} errors (if applicable)
|
|
24
|
+
|
|
25
|
+
### Adaptations
|
|
26
|
+
|
|
27
|
+
Only include if the plan changed:
|
|
28
|
+
- What changed and why
|
|
29
|
+
- Impact on remaining waves
|
|
30
|
+
|
|
31
|
+
## Rules
|
|
32
|
+
|
|
33
|
+
- One table row per agent — no nested details
|
|
34
|
+
- Status is exactly one of: `done`, `partial`, `failed`
|
|
35
|
+
- File lists use short relative paths (e.g., `hooks/on-stop.sh`)
|
|
36
|
+
- Quality gates are pass/fail — no ambiguity
|
|
37
|
+
- Adaptations only when deviating from plan — omit if on track
|
|
38
|
+
- Keep under 20 lines total
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "session-orchestrator",
|
|
3
|
+
"version": "3.16.0",
|
|
4
|
+
"description": "Loop engineering for AI coding agents — turn ad-hoc sessions into a repeatable research → plan → wave-execute → close loop with verification gates. Runs on Claude Code, Codex CLI, Cursor, and Pi.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"homepage": "https://session-orchestrator.com",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pi-package",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"codex",
|
|
11
|
+
"cursor",
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"orchestration"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=24.0.0"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
".mcp.json",
|
|
20
|
+
"CHANGELOG.md",
|
|
21
|
+
"pi/",
|
|
22
|
+
"skills/",
|
|
23
|
+
"agents/",
|
|
24
|
+
"commands/",
|
|
25
|
+
"hooks/",
|
|
26
|
+
"scripts/",
|
|
27
|
+
"rules/",
|
|
28
|
+
"templates/",
|
|
29
|
+
"output-styles/",
|
|
30
|
+
"monitors/",
|
|
31
|
+
"assets/",
|
|
32
|
+
".claude-plugin/",
|
|
33
|
+
".codex-plugin/",
|
|
34
|
+
".cursor/",
|
|
35
|
+
"docs/*.md",
|
|
36
|
+
"NOTICE",
|
|
37
|
+
"SECURITY.md",
|
|
38
|
+
"!**/node_modules/**",
|
|
39
|
+
"!**/.DS_Store"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "node scripts/check-package-manager.mjs && vitest --run",
|
|
43
|
+
"test:coverage": "node scripts/check-package-manager.mjs && vitest --run --coverage",
|
|
44
|
+
"test:watch": "node scripts/check-package-manager.mjs && vitest",
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"lint:fix": "eslint . --fix",
|
|
47
|
+
"typecheck": "node scripts/typecheck.mjs",
|
|
48
|
+
"format": "prettier --write .",
|
|
49
|
+
"format:check": "prettier --check .",
|
|
50
|
+
"share:hw-learnings": "node scripts/export-hw-learnings.mjs",
|
|
51
|
+
"vault-watcher": "node scripts/vault-integration-watcher.mjs",
|
|
52
|
+
"prepare": "husky"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@babel/parser": "^7.26.0",
|
|
56
|
+
"ajv": "^8.17.1",
|
|
57
|
+
"js-yaml": "^4.2.0",
|
|
58
|
+
"mdast-util-to-string": "^4.0.0",
|
|
59
|
+
"remark": "^15.0.0",
|
|
60
|
+
"remark-parse": "^11.0.0",
|
|
61
|
+
"unified": "^11.0.0",
|
|
62
|
+
"zx": "^8.1.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@commitlint/cli": "^19.6.0",
|
|
66
|
+
"@commitlint/config-conventional": "^19.6.0",
|
|
67
|
+
"@eslint/js": "^10.0.1",
|
|
68
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
69
|
+
"eslint": "^10.2.1",
|
|
70
|
+
"husky": "^9.1.7",
|
|
71
|
+
"lint-staged": "^15.2.10",
|
|
72
|
+
"prettier": "^3.0.0",
|
|
73
|
+
"vitest": "^4.1.5"
|
|
74
|
+
},
|
|
75
|
+
"overrides": {
|
|
76
|
+
"vite": "^8.0.16"
|
|
77
|
+
},
|
|
78
|
+
"license": "MIT",
|
|
79
|
+
"repository": {
|
|
80
|
+
"type": "git",
|
|
81
|
+
"url": "git+https://github.com/Kanevry/session-orchestrator.git"
|
|
82
|
+
},
|
|
83
|
+
"pi": {
|
|
84
|
+
"extensions": [
|
|
85
|
+
"./pi/extensions/session-orchestrator.ts"
|
|
86
|
+
],
|
|
87
|
+
"skills": [
|
|
88
|
+
"./skills"
|
|
89
|
+
],
|
|
90
|
+
"prompts": [
|
|
91
|
+
"./pi/prompts/*.md"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|