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,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eval/session-resolve.mjs — deterministic session selection + time-window
|
|
3
|
+
* attribution helpers for the aiat-llm-eval engine (Epic #803, S3).
|
|
4
|
+
*
|
|
5
|
+
* The engine scores ONE completed orchestrator session. Two questions must be
|
|
6
|
+
* answered deterministically and honestly before any dimension is graded:
|
|
7
|
+
*
|
|
8
|
+
* 1. WHICH session? — resolveSession() implements the operator-approved
|
|
9
|
+
* cascade (Decision #2, revised #822): explicit id > newest record (source
|
|
10
|
+
* order) that is either status:'completed' or non-abandoned with completed
|
|
11
|
+
* work. Abandoned records are ALWAYS skipped.
|
|
12
|
+
*
|
|
13
|
+
* 2. WHOSE events? — quality_gate events in events.jsonl carry NO session_id,
|
|
14
|
+
* so they are attributed to a session by its wall-clock window
|
|
15
|
+
* [started_at, completed_at] (Decision #1: attribution = time-window).
|
|
16
|
+
* findPeerOverlap() detects when that window overlaps ANY other session's
|
|
17
|
+
* window — a contaminated window means gate-attribution is unsafe and the
|
|
18
|
+
* affected dimensions downgrade to `cannot-determine` (never guess).
|
|
19
|
+
*
|
|
20
|
+
* Pure module: no clock reads, no I/O — it operates on already-parsed record
|
|
21
|
+
* arrays. Determinism is load-bearing for the CLI `--verify` re-evaluation path.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Thrown by resolveSession when no eligible session can be selected. */
|
|
25
|
+
export class SessionResolutionError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'SessionResolutionError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isPlainObject(v) {
|
|
33
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the session to evaluate.
|
|
38
|
+
*
|
|
39
|
+
* @param {object[]} records — parsed sessions.jsonl records, in source order.
|
|
40
|
+
* @param {string} [sessionId] — explicit session_id; when absent the cascade runs.
|
|
41
|
+
* @returns {{ record: object, resolvedVia: 'explicit'|'cascade-completed'|'cascade-fallback' }}
|
|
42
|
+
* @throws {SessionResolutionError} when nothing eligible is found.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveSession(records, sessionId) {
|
|
45
|
+
if (!Array.isArray(records) || records.length === 0) {
|
|
46
|
+
throw new SessionResolutionError('no session records found in sessions.jsonl');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Explicit selection: the LAST record carrying this session_id (records may be
|
|
50
|
+
// rewritten/backfilled across a session's life; the latest is authoritative).
|
|
51
|
+
if (sessionId) {
|
|
52
|
+
let match = null;
|
|
53
|
+
for (const r of records) {
|
|
54
|
+
if (isPlainObject(r) && r.session_id === sessionId) match = r;
|
|
55
|
+
}
|
|
56
|
+
if (!match) {
|
|
57
|
+
throw new SessionResolutionError(`session not found: ${sessionId}`);
|
|
58
|
+
}
|
|
59
|
+
return { record: match, resolvedVia: 'explicit' };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Cascade (#822 — single backward scan, newest-wins): walk records from
|
|
63
|
+
// newest to oldest and return the FIRST one that qualifies via either tier,
|
|
64
|
+
// rather than exhausting tier (a) — status:'completed' — over the WHOLE
|
|
65
|
+
// array before ever considering tier (b). status:'completed' is a sparse
|
|
66
|
+
// legacy field (absent from every record written after 2026-07-04 by the
|
|
67
|
+
// current Phase-3.7 writer), so exhausting it first could select an
|
|
68
|
+
// arbitrarily old record and skip many newer valid ones. Both resolvedVia
|
|
69
|
+
// labels are preserved for downstream callers/tests.
|
|
70
|
+
for (let i = records.length - 1; i >= 0; i--) {
|
|
71
|
+
const r = records[i];
|
|
72
|
+
if (!isPlainObject(r)) continue;
|
|
73
|
+
if (r.status === 'abandoned') continue;
|
|
74
|
+
if (r.status === 'completed') {
|
|
75
|
+
return { record: r, resolvedVia: 'cascade-completed' };
|
|
76
|
+
}
|
|
77
|
+
// status may be absent (absent !== 'abandoned') — qualifies when it
|
|
78
|
+
// otherwise shows evidence of completed work.
|
|
79
|
+
if (!r.completed_at) continue;
|
|
80
|
+
const complete = isPlainObject(r.agent_summary) ? r.agent_summary.complete ?? 0 : 0;
|
|
81
|
+
const rate = isPlainObject(r.effectiveness) ? r.effectiveness.completion_rate : undefined;
|
|
82
|
+
if (complete > 0 || (rate !== undefined && rate !== null)) {
|
|
83
|
+
return { record: r, resolvedVia: 'cascade-fallback' };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
throw new SessionResolutionError(
|
|
88
|
+
'no completed session found (all records abandoned or without evidence of completed work)',
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Compute the wall-clock window [start, end] (epoch ms) for a session record.
|
|
94
|
+
* Returns null when either boundary is missing / unparseable — the caller then
|
|
95
|
+
* treats window-attributed dimensions as unmeasurable rather than guessing.
|
|
96
|
+
*
|
|
97
|
+
* @param {object} record
|
|
98
|
+
* @returns {{ start: number, end: number } | null}
|
|
99
|
+
*/
|
|
100
|
+
export function computeWindow(record) {
|
|
101
|
+
if (!isPlainObject(record)) return null;
|
|
102
|
+
const start = Date.parse(record.started_at);
|
|
103
|
+
const end = Date.parse(record.completed_at);
|
|
104
|
+
if (Number.isNaN(start) || Number.isNaN(end)) return null;
|
|
105
|
+
return { start, end };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Detect peer sessions whose window overlaps the resolved session's window.
|
|
110
|
+
*
|
|
111
|
+
* Overlap uses STRICT inequality (a.start < b.end && b.start < a.end) so two
|
|
112
|
+
* back-to-back sessions that merely touch at a shared boundary are NOT counted
|
|
113
|
+
* as overlapping. Records sharing the resolved session_id (duplicate/backfill
|
|
114
|
+
* rewrites of the SAME session) are excluded, as are records without a valid
|
|
115
|
+
* window.
|
|
116
|
+
*
|
|
117
|
+
* @param {object[]} records — all sessions.jsonl records.
|
|
118
|
+
* @param {object} resolved — the resolved session record.
|
|
119
|
+
* @returns {{ count: number, peers: string[] }} unique overlapping session_ids.
|
|
120
|
+
*/
|
|
121
|
+
export function findPeerOverlap(records, resolved) {
|
|
122
|
+
const win = computeWindow(resolved);
|
|
123
|
+
if (!win || !Array.isArray(records)) return { count: 0, peers: [] };
|
|
124
|
+
|
|
125
|
+
const peers = new Set();
|
|
126
|
+
for (const r of records) {
|
|
127
|
+
if (!isPlainObject(r)) continue;
|
|
128
|
+
if (r.session_id === resolved.session_id) continue;
|
|
129
|
+
const w = computeWindow(r);
|
|
130
|
+
if (!w) continue;
|
|
131
|
+
if (win.start < w.end && w.start < win.end) {
|
|
132
|
+
peers.add(typeof r.session_id === 'string' ? r.session_id : '(unknown)');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const list = [...peers];
|
|
136
|
+
return { count: list.length, peers: list };
|
|
137
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eval/sink.mjs — append-only sink + reader for the eval journal
|
|
3
|
+
* (.orchestrator/metrics/eval.jsonl), the Single Source of Truth for the
|
|
4
|
+
* aiat-llm-eval standard (Epic #803, S2). The HTML report is a derived view;
|
|
5
|
+
* this journal is authoritative.
|
|
6
|
+
*
|
|
7
|
+
* Design (mirrors scripts/harness-audit.mjs appendAuditRecord): a metrics append
|
|
8
|
+
* MUST NEVER break its caller. The session-end eval phase is advisory and must
|
|
9
|
+
* never block /close, so appendEvalRecord swallows BOTH validation and
|
|
10
|
+
* filesystem errors — it emits a stderr WARN and returns a result object, and
|
|
11
|
+
* NEVER throws. Callers that want hard validation call validateEvalRecord
|
|
12
|
+
* (from ./schema.mjs) directly.
|
|
13
|
+
*
|
|
14
|
+
* Read path reuses readJsonlFile from scripts/lib/io.mjs (missing file → [],
|
|
15
|
+
* malformed lines skipped) — never throws.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { mkdirSync, appendFileSync } from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { validateEvalRecord, normalizeEvalRecord } from './schema.mjs';
|
|
21
|
+
import { readJsonlFile } from '../io.mjs';
|
|
22
|
+
|
|
23
|
+
/** Default repo-relative path for the eval journal. */
|
|
24
|
+
export const DEFAULT_EVAL_JSONL_PATH = '.orchestrator/metrics/eval.jsonl';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Append a single session-eval record to the eval journal. NEVER throws.
|
|
28
|
+
*
|
|
29
|
+
* Steps:
|
|
30
|
+
* 1. validateEvalRecord — stamps schema_version, enforces the full contract
|
|
31
|
+
* (incl. the no-global-score rule). On failure: stderr WARN + return
|
|
32
|
+
* { ok:false, reason:'validation', error }. The malformed record is NOT written.
|
|
33
|
+
* 2. Serialize the validated record to JSON + newline.
|
|
34
|
+
* 3. mkdirSync(dirname, recursive) + appendFileSync (append-only). On FS
|
|
35
|
+
* failure: stderr WARN + return { ok:false, reason:'fs-error', error }.
|
|
36
|
+
*
|
|
37
|
+
* @param {object} record — candidate session-eval record.
|
|
38
|
+
* @param {{ path?: string }} [opts] — target path (absolute preferred); defaults
|
|
39
|
+
* to DEFAULT_EVAL_JSONL_PATH (repo-relative).
|
|
40
|
+
* @returns {{ ok: true, record: object, path: string }
|
|
41
|
+
* | { ok: false, reason: 'validation'|'fs-error', error: string }}
|
|
42
|
+
*/
|
|
43
|
+
export function appendEvalRecord(record, { path: filePath = DEFAULT_EVAL_JSONL_PATH } = {}) {
|
|
44
|
+
let validated;
|
|
45
|
+
try {
|
|
46
|
+
validated = validateEvalRecord(record);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
const msg = err?.message ?? String(err);
|
|
49
|
+
process.stderr.write(`[eval-sink] WARN: record failed validation, not written: ${msg}\n`);
|
|
50
|
+
return { ok: false, reason: 'validation', error: msg };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const line = JSON.stringify(validated) + '\n';
|
|
55
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
56
|
+
appendFileSync(filePath, line, 'utf8');
|
|
57
|
+
return { ok: true, record: validated, path: filePath };
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const msg = err?.message ?? String(err);
|
|
60
|
+
process.stderr.write(`[eval-sink] WARN: could not append to ${filePath}: ${msg}\n`);
|
|
61
|
+
return { ok: false, reason: 'fs-error', error: msg };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Read all session-eval records from the eval journal. Never throws — a missing
|
|
67
|
+
* file yields [] and malformed JSONL lines are skipped (readJsonlFile with
|
|
68
|
+
* skipInvalid). Each record is passed through normalizeEvalRecord so callers get
|
|
69
|
+
* a uniform shape (kpi nulls, judge-dim defaults, stamped versions).
|
|
70
|
+
*
|
|
71
|
+
* @param {string} [filePath] — absolute path to the eval journal.
|
|
72
|
+
* @returns {object[]} normalized session-eval records, in source order.
|
|
73
|
+
*/
|
|
74
|
+
export function readEvalRecords(filePath = DEFAULT_EVAL_JSONL_PATH) {
|
|
75
|
+
const rows = readJsonlFile(filePath, { skipInvalid: true });
|
|
76
|
+
return rows.map((r) => normalizeEvalRecord(r));
|
|
77
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* events-rotation.mjs — size-based rotation for .orchestrator/metrics/events.jsonl.
|
|
3
|
+
*
|
|
4
|
+
* Contract: called from the session-start hook. Returns a result object; never
|
|
5
|
+
* throws on fs errors (rotation failure must not break session-start). Uses
|
|
6
|
+
* synchronous fs calls (the hook is short-lived; async adds complexity).
|
|
7
|
+
*
|
|
8
|
+
* Issue #251 (CRITICAL). Rotation fires only at session-start, not per-append —
|
|
9
|
+
* per-append overhead is wasteful given ~6 KiB/day growth.
|
|
10
|
+
*
|
|
11
|
+
* Rename safety (POSIX): atomic rename is safe with in-flight writers. Old fds
|
|
12
|
+
* continue writing to the original inode (now `events.jsonl.1`); new writers
|
|
13
|
+
* will open the new file on next append.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { statSync, renameSync, unlinkSync, existsSync } from 'node:fs';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Rotate the events log if it exceeds `maxSizeMb`.
|
|
20
|
+
*
|
|
21
|
+
* Shift scheme: `.N-1` → `.N`, …, `.1` → `.2`, active `events.jsonl` → `.1`.
|
|
22
|
+
* The oldest backup (`events.jsonl.{maxBackups}`) is deleted before shifting.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} opts
|
|
25
|
+
* @param {string} opts.logPath — absolute path to `events.jsonl`
|
|
26
|
+
* @param {number} opts.maxSizeMb — integer 1..1024
|
|
27
|
+
* @param {number} opts.maxBackups — integer 1..20
|
|
28
|
+
* @param {boolean} opts.enabled — if false, returns early
|
|
29
|
+
* @returns {{rotated: boolean, reason?: string, archivedAs?: string, sizeBefore?: number, maxBackups?: number, error?: string}}
|
|
30
|
+
*/
|
|
31
|
+
export function maybeRotate({ logPath, maxSizeMb, maxBackups, enabled } = {}) {
|
|
32
|
+
// --- Input validation (throw — programmer error, not runtime fs failure) ---
|
|
33
|
+
if (typeof logPath !== 'string' || logPath.length === 0) {
|
|
34
|
+
throw new Error(`events-rotation: logPath must be a non-empty string, got ${typeof logPath}`);
|
|
35
|
+
}
|
|
36
|
+
if (!Number.isInteger(maxSizeMb) || maxSizeMb < 1 || maxSizeMb > 1024) {
|
|
37
|
+
throw new Error(`events-rotation: maxSizeMb must be integer 1..1024, got ${maxSizeMb}`);
|
|
38
|
+
}
|
|
39
|
+
if (!Number.isInteger(maxBackups) || maxBackups < 1 || maxBackups > 20) {
|
|
40
|
+
throw new Error(`events-rotation: maxBackups must be integer 1..20, got ${maxBackups}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (enabled === false) {
|
|
44
|
+
return { rotated: false, reason: 'disabled' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
if (!existsSync(logPath)) {
|
|
49
|
+
return { rotated: false, reason: 'no-file' };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const sizeBefore = statSync(logPath).size;
|
|
53
|
+
const threshold = maxSizeMb * 1024 * 1024;
|
|
54
|
+
if (sizeBefore < threshold) {
|
|
55
|
+
return { rotated: false, reason: 'under-threshold' };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Drop the oldest backup if it exists — this keeps the ring bounded.
|
|
59
|
+
const oldestPath = `${logPath}.${maxBackups}`;
|
|
60
|
+
if (existsSync(oldestPath)) {
|
|
61
|
+
unlinkSync(oldestPath);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Shift `.N-1` → `.N`, …, `.1` → `.2`.
|
|
65
|
+
for (let i = maxBackups - 1; i >= 1; i--) {
|
|
66
|
+
const src = `${logPath}.${i}`;
|
|
67
|
+
const dst = `${logPath}.${i + 1}`;
|
|
68
|
+
if (existsSync(src)) {
|
|
69
|
+
renameSync(src, dst);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Rotate active file to `.1`. POSIX atomic rename.
|
|
74
|
+
renameSync(logPath, `${logPath}.1`);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
rotated: true,
|
|
78
|
+
archivedAs: `${logPath}.1`,
|
|
79
|
+
sizeBefore,
|
|
80
|
+
maxBackups,
|
|
81
|
+
};
|
|
82
|
+
} catch (err) {
|
|
83
|
+
// Never throw — rotation failure must not break session-start.
|
|
84
|
+
return { rotated: false, reason: 'error', error: err?.message ?? String(err) };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* events-schema.mjs — canonical schema + naming-convention validator for
|
|
3
|
+
* `.orchestrator/metrics/events.jsonl` records.
|
|
4
|
+
*
|
|
5
|
+
* The orchestrator emits ONE event stream via `emitEvent()` (see events.mjs).
|
|
6
|
+
* Every record has the shape `{ timestamp, event, ...payload }`. Orchestrator-owned
|
|
7
|
+
* events follow the dotted namespace `orchestrator.<domain>.<verb>` (see
|
|
8
|
+
* docs/events-schema.md). Third-party / legacy event names (e.g. `tmux-layout.*`)
|
|
9
|
+
* are accepted as-is — this validator only enforces the convention on the
|
|
10
|
+
* `orchestrator.` namespace we own.
|
|
11
|
+
*
|
|
12
|
+
* Pure functions, no filesystem access — safe to import anywhere.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** ISO-8601 UTC timestamp with trailing Z (e.g. 2026-05-28T14:35:13.123Z). */
|
|
16
|
+
const ISO_8601_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/;
|
|
17
|
+
|
|
18
|
+
/** Prefix marking an orchestrator-owned event. */
|
|
19
|
+
export const ORCHESTRATOR_PREFIX = 'orchestrator.';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Dotted orchestrator-domain event name: `orchestrator.<domain>.<verb>[.<...>]`.
|
|
23
|
+
* Lowercase alphanumeric segments; underscores allowed WITHIN a segment
|
|
24
|
+
* (e.g. `quality_gate`, `propose_invoked`). Requires at least three segments
|
|
25
|
+
* (orchestrator + domain + verb).
|
|
26
|
+
*/
|
|
27
|
+
export const ORCHESTRATOR_EVENT_RE =
|
|
28
|
+
/^orchestrator\.[a-z0-9]+(?:_[a-z0-9]+)*(?:\.[a-z0-9]+(?:_[a-z0-9]+)*)+$/;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* True when `value` is an ISO-8601 UTC timestamp string that also parses to a
|
|
32
|
+
* real date.
|
|
33
|
+
* @param {unknown} value
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
export function isIso8601(value) {
|
|
37
|
+
return (
|
|
38
|
+
typeof value === 'string' &&
|
|
39
|
+
ISO_8601_RE.test(value) &&
|
|
40
|
+
!Number.isNaN(Date.parse(value))
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validate a single events.jsonl record against the canonical schema.
|
|
46
|
+
*
|
|
47
|
+
* Rules:
|
|
48
|
+
* - record must be a plain (non-array) object;
|
|
49
|
+
* - `timestamp` is required and must be an ISO-8601 UTC string;
|
|
50
|
+
* - `event` is required and must be a non-empty string;
|
|
51
|
+
* - events in the `orchestrator.` namespace MUST match
|
|
52
|
+
* `orchestrator.<domain>.<verb>` (lowercase, dotted);
|
|
53
|
+
* - non-orchestrator event names are accepted as-is (legacy / third-party).
|
|
54
|
+
*
|
|
55
|
+
* @param {unknown} record
|
|
56
|
+
* @returns {{ valid: boolean, errors: string[] }}
|
|
57
|
+
*/
|
|
58
|
+
export function validateEventRecord(record) {
|
|
59
|
+
if (record === null || typeof record !== 'object' || Array.isArray(record)) {
|
|
60
|
+
return { valid: false, errors: ['record must be a non-array object'] };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const errors = [];
|
|
64
|
+
|
|
65
|
+
if (!isIso8601(record.timestamp)) {
|
|
66
|
+
errors.push('timestamp must be an ISO-8601 UTC string ending in Z');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (typeof record.event !== 'string' || record.event.length === 0) {
|
|
70
|
+
errors.push('event must be a non-empty string');
|
|
71
|
+
} else if (
|
|
72
|
+
record.event.startsWith(ORCHESTRATOR_PREFIX) &&
|
|
73
|
+
!ORCHESTRATOR_EVENT_RE.test(record.event)
|
|
74
|
+
) {
|
|
75
|
+
errors.push(
|
|
76
|
+
`orchestrator-domain event "${record.event}" must match orchestrator.<domain>.<verb> (lowercase, dotted, ≥3 segments)`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { valid: errors.length === 0, errors };
|
|
81
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* events.mjs — JSONL event emission + optional webhook POST for session-orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Replaces scripts/lib/events.sh. Windows-safe (no hardcoded path separators).
|
|
5
|
+
* Uses native fetch (Node 20+) and fs.promises — no external dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Part of v3.0.0 migration (Epic #124, issue #133).
|
|
8
|
+
* Issue #228: removed hardcoded personal-domain default URL. Clank Event Bus URL
|
|
9
|
+
* must now be supplied explicitly via CLANK_EVENT_URL when CLANK_EVENT_SECRET is set.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { promises as fs } from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { SO_PROJECT_DIR, SO_SHARED_DIR } from './platform.mjs';
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Public API
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns the absolute path to .orchestrator/metrics/events.jsonl in the project root.
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export function eventsFilePath() {
|
|
25
|
+
return path.join(SO_PROJECT_DIR, SO_SHARED_DIR, 'metrics', 'events.jsonl');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Append a JSONL event record and optionally POST to the Clank Event Bus webhook.
|
|
30
|
+
*
|
|
31
|
+
* Writes `{ts, event, ...payload}` as a single JSON line to
|
|
32
|
+
* `.orchestrator/metrics/events.jsonl` (creates parent directory if needed).
|
|
33
|
+
* If both `CLANK_EVENT_SECRET` and `CLANK_EVENT_URL` are set, fires an async
|
|
34
|
+
* fire-and-forget POST to `CLANK_EVENT_URL` with a 3-second timeout. Network
|
|
35
|
+
* errors are swallowed. Write errors propagate to the caller. No personal-domain
|
|
36
|
+
* default URL exists — both vars must be set explicitly (#228).
|
|
37
|
+
*
|
|
38
|
+
* @param {string} type — event type (e.g. "orchestrator.session.started")
|
|
39
|
+
* @param {object} [payload={}] — additional fields shallow-merged into the record
|
|
40
|
+
* @param {object} [opts={}] — emission options.
|
|
41
|
+
* @param {string} [opts.filePath] — override the destination JSONL path. Defaults
|
|
42
|
+
* to `eventsFilePath()` (the project's `.orchestrator/metrics/events.jsonl`).
|
|
43
|
+
* Used by `scripts/emit-event.mjs --file` so shell callers (e.g.
|
|
44
|
+
* compute-grounding-injection.sh) can target a pre-resolved EVENTS_JSONL path
|
|
45
|
+
* without depending on platform.mjs CWD/env resolution (#611).
|
|
46
|
+
* @returns {Promise<void>}
|
|
47
|
+
*/
|
|
48
|
+
export async function emitEvent(type, payload = {}, opts = {}) {
|
|
49
|
+
// Build the JSONL record: ts + event come first, payload spreads last.
|
|
50
|
+
const record = { timestamp: new Date().toISOString(), event: type, ...payload };
|
|
51
|
+
const line = JSON.stringify(record) + '\n';
|
|
52
|
+
|
|
53
|
+
// Ensure the destination directory exists before appending. The default
|
|
54
|
+
// resolution is unchanged for 2-arg callers — only an explicit opts.filePath
|
|
55
|
+
// overrides it (#611, additive).
|
|
56
|
+
const filePath = opts.filePath ?? eventsFilePath();
|
|
57
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
58
|
+
await fs.appendFile(filePath, line, 'utf8');
|
|
59
|
+
|
|
60
|
+
// Fire-and-forget webhook POST — only when secret AND URL are configured.
|
|
61
|
+
// No personal-domain default: CLANK_EVENT_URL must be set explicitly (#228).
|
|
62
|
+
if (process.env.CLANK_EVENT_SECRET && process.env.CLANK_EVENT_URL) {
|
|
63
|
+
const url = process.env.CLANK_EVENT_URL;
|
|
64
|
+
const body = JSON.stringify({
|
|
65
|
+
event_type: type,
|
|
66
|
+
source: 'session-orchestrator',
|
|
67
|
+
payload,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
fetch(`${url}/api/webhooks/events`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
'Authorization': `Bearer ${process.env.CLANK_EVENT_SECRET}`,
|
|
75
|
+
},
|
|
76
|
+
body,
|
|
77
|
+
signal: AbortSignal.timeout(3000),
|
|
78
|
+
}).catch(() => {});
|
|
79
|
+
}
|
|
80
|
+
}
|