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,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worktree-sweep.mjs — Stale auto-promoted worktree detection helpers.
|
|
3
|
+
*
|
|
4
|
+
* Implements Phase 4.5 of skills/memory-cleanup/SKILL.md (#575 P3.2):
|
|
5
|
+
* - listAutoPromotedWorktrees(repoRoot, mainCheckoutRoot)
|
|
6
|
+
* - isWorktreeStale(wtPath, staleBranchDays)
|
|
7
|
+
*
|
|
8
|
+
* Public API:
|
|
9
|
+
* - listAutoPromotedWorktrees(repoRoot, mainCheckoutRoot): Array<{wtPath, sessionId, branch}>
|
|
10
|
+
* - isWorktreeStale(wtPath, staleBranchDays): boolean
|
|
11
|
+
*
|
|
12
|
+
* PRD: "Parallel-aware sessions" (#568; archived in the private Meta-Vault) §3 P3 Gherkin row 4 + §3.A P3
|
|
13
|
+
* Closes #575 P3.2
|
|
14
|
+
*
|
|
15
|
+
* DI seam (#580-DI-001): this module uses a SYNCHRONOUS `opts.execFileFn`
|
|
16
|
+
* (default `execFileSync`) because the memory-cleanup Phase 4.5 sweep runs in a
|
|
17
|
+
* synchronous coordinator step. Its sibling helper
|
|
18
|
+
* `scripts/lib/session-end/worktree-cleanup.mjs` shares the same sync
|
|
19
|
+
* `execFileFn` seam; the autopilot worktree driver
|
|
20
|
+
* (`scripts/lib/autopilot/worktree-pipeline.mjs`) deliberately uses an ASYNC
|
|
21
|
+
* `opts.$` (zx) seam instead because `enterWorktree()` is async. The seams are
|
|
22
|
+
* kept divergent on purpose — unifying them would break the sync/async boundary.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { execFileSync } from 'node:child_process';
|
|
26
|
+
import { statSync } from 'node:fs';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { parseSessionId } from '../session-id.mjs';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* List all auto-promoted sibling worktrees for a given main checkout root.
|
|
32
|
+
*
|
|
33
|
+
* Auto-promoted worktrees follow the layout `<parentDir>/<repoName>-<sessionId>/`,
|
|
34
|
+
* where `<sessionId>` is a semantic session-id (per `parseSessionId()` from
|
|
35
|
+
* `scripts/lib/session-id.mjs`). Random-suffix worktrees (UUID-format) are NOT
|
|
36
|
+
* auto-promoted and are excluded.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} repoRoot - Current working directory (used as context; not directly
|
|
39
|
+
* passed to git — mainCheckoutRoot is used for git worktree list).
|
|
40
|
+
* @param {string} mainCheckoutRoot - Absolute path to the main checkout (the primary
|
|
41
|
+
* worktree). This is the anchor from which sibling worktrees are resolved.
|
|
42
|
+
* @param {object} [opts] - Optional dependency injection for testing.
|
|
43
|
+
* @param {Function} [opts.execFileFn] - Override for execFileSync (default: node:child_process execFileSync).
|
|
44
|
+
* Signature: (file: string, args: string[], options) => string.
|
|
45
|
+
* @returns {Array<{wtPath: string, sessionId: string, branch: string}>}
|
|
46
|
+
* Array of matching auto-promoted worktrees. Empty array on error or no candidates.
|
|
47
|
+
*/
|
|
48
|
+
export function listAutoPromotedWorktrees(repoRoot, mainCheckoutRoot, opts = {}) {
|
|
49
|
+
// #577 HARDEN-001: execFileSync + args ARRAY (no shell) — mainCheckoutRoot cannot inject.
|
|
50
|
+
const execFileFn = opts.execFileFn ?? execFileSync;
|
|
51
|
+
const repoName = path.basename(mainCheckoutRoot);
|
|
52
|
+
const candidates = [];
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const out = execFileFn('git', ['-C', mainCheckoutRoot, 'worktree', 'list', '--porcelain'], {
|
|
56
|
+
encoding: 'utf8',
|
|
57
|
+
});
|
|
58
|
+
const entries = out.split('\n\n').filter(Boolean);
|
|
59
|
+
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
const wtMatch = entry.match(/^worktree (.+)$/m);
|
|
62
|
+
if (!wtMatch) continue;
|
|
63
|
+
const wtPath = wtMatch[1];
|
|
64
|
+
|
|
65
|
+
// Skip the main checkout itself
|
|
66
|
+
if (wtPath === mainCheckoutRoot) continue;
|
|
67
|
+
|
|
68
|
+
// Match auto-promoted layout: <parentDir>/<repoName>-<sessionId>
|
|
69
|
+
const basename = path.basename(wtPath);
|
|
70
|
+
if (!basename.startsWith(`${repoName}-`)) continue;
|
|
71
|
+
const sessionIdCandidate = basename.slice(repoName.length + 1);
|
|
72
|
+
|
|
73
|
+
// Verify it's a semantic session-id (not a random suffix or UUID)
|
|
74
|
+
const parsed = parseSessionId(sessionIdCandidate);
|
|
75
|
+
if (!parsed || parsed.format !== 'semantic') continue;
|
|
76
|
+
|
|
77
|
+
candidates.push({ wtPath, sessionId: sessionIdCandidate, branch: parsed.branch });
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// git failure or any other error → return no candidates (conservative no-op)
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return candidates;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Determine whether a worktree directory is stale based on its mtime.
|
|
89
|
+
*
|
|
90
|
+
* A worktree is stale iff `mtime(wtPath) < now - staleBranchDays × 86400 × 1000`.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} wtPath - Absolute path to the worktree directory.
|
|
93
|
+
* @param {number} staleBranchDays - Staleness threshold in days (from Session Config,
|
|
94
|
+
* default 7). A worktree older than this many days is considered stale.
|
|
95
|
+
* @returns {boolean} `true` if the worktree exists and its mtime is older than the
|
|
96
|
+
* threshold; `false` if the path does not exist, is unreadable, or is within the
|
|
97
|
+
* threshold. Conservative no-op: missing paths return `false`.
|
|
98
|
+
*/
|
|
99
|
+
export function isWorktreeStale(wtPath, staleBranchDays) {
|
|
100
|
+
try {
|
|
101
|
+
const stat = statSync(wtPath);
|
|
102
|
+
const ageMs = Date.now() - stat.mtimeMs;
|
|
103
|
+
return ageMs > staleBranchDays * 24 * 60 * 60 * 1000;
|
|
104
|
+
} catch {
|
|
105
|
+
// Missing or unreadable → conservative no-op
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-cleanup-stamp.mjs — Pure helper: stamp `memory_cleanup_at` on a
|
|
3
|
+
* session record when `/memory-cleanup` ran this session.
|
|
4
|
+
*
|
|
5
|
+
* Issue #699 fix: a healthy no-op run of `/memory-cleanup` previously left
|
|
6
|
+
* `memory_cleanup_at` unstamped, so `auto-dream.mjs` `readDreamSignals`
|
|
7
|
+
* never advanced `lastCleanupAt` and `shouldDispatchAutoDream` kept firing a
|
|
8
|
+
* false nudge. This helper stamps the field unconditionally whenever the
|
|
9
|
+
* cleanup ran — including a healthy no-op where no memory files were mutated.
|
|
10
|
+
*
|
|
11
|
+
* Design constraints:
|
|
12
|
+
* - Pure function — no I/O, no side-effects.
|
|
13
|
+
* - No-throw — invalid inputs return the record unchanged (defensive).
|
|
14
|
+
* - Testable seam — the Quality wave (Q2) unit-tests this function directly.
|
|
15
|
+
* - No external deps — Node 20+ stdlib only (none needed here).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Stamp `memory_cleanup_at` on a session record when `/memory-cleanup` ran.
|
|
20
|
+
*
|
|
21
|
+
* A cleanup run includes ALL outcomes: dry-run, apply-pending, AND healthy
|
|
22
|
+
* no-op (MEMORY.md already healthy — no files mutated). The cadence marker
|
|
23
|
+
* MUST advance even on a no-op so `shouldDispatchAutoDream` does not fire a
|
|
24
|
+
* false nudge on the next session.
|
|
25
|
+
*
|
|
26
|
+
* @param {object} record The in-memory session record object (not mutated).
|
|
27
|
+
* @param {object} opts
|
|
28
|
+
* @param {boolean} opts.ranCleanup True when `/memory-cleanup` ran this session
|
|
29
|
+
* in any mode (dry-run, apply-pending, or interactive/healthy no-op).
|
|
30
|
+
* False or absent → return record unchanged.
|
|
31
|
+
* @param {string} opts.completedAt ISO-8601 UTC timestamp to write as
|
|
32
|
+
* `memory_cleanup_at`. Typically the session's `completed_at` value.
|
|
33
|
+
* Required when `ranCleanup === true`; if missing, returns record unchanged
|
|
34
|
+
* (defensive — never throws).
|
|
35
|
+
* @returns {object} Shallow-cloned record with `memory_cleanup_at` set, OR
|
|
36
|
+
* the original record object when no stamp is applied.
|
|
37
|
+
*/
|
|
38
|
+
export function stampMemoryCleanup(record, { ranCleanup, completedAt } = {}) {
|
|
39
|
+
// Guard: only stamp when the cleanup actually ran.
|
|
40
|
+
if (ranCleanup !== true) {
|
|
41
|
+
return record;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Guard: completedAt is required to stamp; if missing, skip defensively.
|
|
45
|
+
if (typeof completedAt !== 'string' || completedAt.length === 0) {
|
|
46
|
+
return record;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Guard: record must be a plain object; anything else is returned unchanged.
|
|
50
|
+
if (record === null || typeof record !== 'object' || Array.isArray(record)) {
|
|
51
|
+
return record;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Return a shallow clone with the stamp applied — never mutate the input.
|
|
55
|
+
return { ...record, memory_cleanup_at: completedAt };
|
|
56
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-paths.mjs — Memory-directory path resolution (Issue #512).
|
|
3
|
+
*
|
|
4
|
+
* Single-source helper for resolving the Claude Code memory directory layout.
|
|
5
|
+
* Extracted from `scripts/lib/auto-dream.mjs` so memory-banner.mjs (and any
|
|
6
|
+
* future consumer) can import the path helper without pulling in the entire
|
|
7
|
+
* auto-dream surface (dream signals, sidecar I/O, decision logic).
|
|
8
|
+
*
|
|
9
|
+
* No external deps — Node 20+ stdlib only.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import os from 'node:os';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the project-specific memory directory used by the Claude Code harness.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors the harness convention: `~/.claude/projects/<encoded-cwd>/memory/`
|
|
19
|
+
* where `<encoded-cwd>` is the cwd with BOTH `/` AND `.` replaced by `-`. The
|
|
20
|
+
* dot replacement matters for users with a trailing-`.` in their home dir
|
|
21
|
+
* (e.g. `/Users/<owner>.`) — without it the resolved path diverges from
|
|
22
|
+
* what the harness actually wrote.
|
|
23
|
+
*
|
|
24
|
+
* Verified empirically against `~/.claude/projects/` directory naming.
|
|
25
|
+
*
|
|
26
|
+
* @returns {string} Absolute path to the memory directory (not guaranteed to exist).
|
|
27
|
+
*/
|
|
28
|
+
export function resolveMemoryDir() {
|
|
29
|
+
const encoded = process.cwd().replaceAll('/', '-').replaceAll('.', '-');
|
|
30
|
+
return path.join(os.homedir(), '.claude', 'projects', encoded, 'memory');
|
|
31
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-proposals/collector.mjs — Read-only aggregator for the memory-proposal queue.
|
|
3
|
+
*
|
|
4
|
+
* Reads proposals.jsonl + all per-wave summary JSONs at session-end and
|
|
5
|
+
* aggregates them into a structured payload the coordinator uses to drive
|
|
6
|
+
* AUQ rendering (Phase 3.6.3).
|
|
7
|
+
*
|
|
8
|
+
* Design principles (issue #501, PRD F2.1):
|
|
9
|
+
* - Read-only — never writes any file.
|
|
10
|
+
* - Never throws — fs/parse errors are translated to empty/zero results.
|
|
11
|
+
* - FIFO ordering — proposals are sorted by created_at ASC (no confidence re-sort).
|
|
12
|
+
* - Malformed JSONL lines are silently skipped (counted in stats.parse_errors).
|
|
13
|
+
* - Missing files → empty queue + all-zero stats (graceful degradation).
|
|
14
|
+
*
|
|
15
|
+
* No external deps — Node 20+ stdlib only.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
19
|
+
import { existsSync } from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Path helpers
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the path to proposals.jsonl within the repo's metrics directory.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} repoRoot
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function proposalsJsonlPath(repoRoot) {
|
|
33
|
+
return path.join(repoRoot, '.orchestrator', 'metrics', 'proposals.jsonl');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the metrics directory where per-wave summary JSONs are stored.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} repoRoot
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
function metricsDir(repoRoot) {
|
|
43
|
+
return path.join(repoRoot, '.orchestrator', 'metrics');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Zero-value helpers
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Return a stats object with all counters set to zero.
|
|
52
|
+
*
|
|
53
|
+
* @returns {object}
|
|
54
|
+
*/
|
|
55
|
+
function zeroStats() {
|
|
56
|
+
return {
|
|
57
|
+
queued: 0,
|
|
58
|
+
dropped: 0,
|
|
59
|
+
below_floor: 0,
|
|
60
|
+
fs_error: 0,
|
|
61
|
+
parse_errors: 0,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// JSONL reader (exported for unit testing / direct use)
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Read proposals.jsonl and return records sorted FIFO by created_at.
|
|
71
|
+
*
|
|
72
|
+
* Malformed lines are skipped silently (a debug-level log is emitted so
|
|
73
|
+
* callers can observe them without failing). The caller receives an array
|
|
74
|
+
* of plain parsed objects — no schema validation is applied here; that is
|
|
75
|
+
* the store layer's responsibility.
|
|
76
|
+
*
|
|
77
|
+
* Uses `deserializeProposal` from schema.mjs when available; falls back to
|
|
78
|
+
* raw `JSON.parse` so the module can operate independently during testing or
|
|
79
|
+
* when I1 (schema.mjs) ships in the same wave.
|
|
80
|
+
*
|
|
81
|
+
* @param {object} args
|
|
82
|
+
* @param {string} args.repoRoot Absolute path to the repo root.
|
|
83
|
+
* @returns {Promise<import('./schema.mjs').ProposalRecord[]>}
|
|
84
|
+
*/
|
|
85
|
+
export async function readProposalsJsonl({ repoRoot }) {
|
|
86
|
+
const filePath = proposalsJsonlPath(repoRoot);
|
|
87
|
+
if (!existsSync(filePath)) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let raw;
|
|
92
|
+
try {
|
|
93
|
+
raw = await readFile(filePath, 'utf8');
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error(`[memory-proposals/collector] WARN: could not read proposals.jsonl: ${err.message}`);
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Attempt to load deserializeProposal from schema.mjs (may not exist yet).
|
|
100
|
+
let deserialize = null;
|
|
101
|
+
try {
|
|
102
|
+
const schema = await import('./schema.mjs');
|
|
103
|
+
if (typeof schema.deserializeProposal === 'function') {
|
|
104
|
+
deserialize = schema.deserializeProposal;
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
// schema.mjs not yet available — fall back to raw JSON.parse.
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const lines = raw.split('\n').filter((l) => l.length > 0);
|
|
111
|
+
const records = [];
|
|
112
|
+
|
|
113
|
+
for (const line of lines) {
|
|
114
|
+
try {
|
|
115
|
+
// deserializeProposal from schema.mjs expects the raw JSONL line (it
|
|
116
|
+
// does JSON.parse internally). Passing a pre-parsed object trips its
|
|
117
|
+
// `typeof line !== 'string'` guard and returns null for every record.
|
|
118
|
+
// Fall back to raw JSON.parse only when schema.mjs is unavailable.
|
|
119
|
+
const record = deserialize ? deserialize(line) : JSON.parse(line);
|
|
120
|
+
if (record !== null && record !== undefined) {
|
|
121
|
+
records.push(record);
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
// Malformed line — skip silently per spec.
|
|
125
|
+
console.debug(`[memory-proposals/collector] DEBUG: skipped malformed JSONL line`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// FIFO: sort by created_at ascending (lexicographic ISO 8601 is safe for this).
|
|
130
|
+
records.sort((a, b) => {
|
|
131
|
+
const aTs = typeof a.created_at === 'string' ? a.created_at : '';
|
|
132
|
+
const bTs = typeof b.created_at === 'string' ? b.created_at : '';
|
|
133
|
+
if (aTs < bTs) return -1;
|
|
134
|
+
if (aTs > bTs) return 1;
|
|
135
|
+
return 0;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return records;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Per-wave summary reader
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Read all `proposals-summary-*.json` files from the metrics directory.
|
|
147
|
+
*
|
|
148
|
+
* Returns a map of wave_id → parsed summary object. Files that cannot be
|
|
149
|
+
* parsed are skipped (fs_error is counted separately in collectProposals).
|
|
150
|
+
*
|
|
151
|
+
* @param {string} repoRoot
|
|
152
|
+
* @returns {Promise<Record<string, object>>}
|
|
153
|
+
*/
|
|
154
|
+
async function readPerWaveSummaries(repoRoot) {
|
|
155
|
+
const dir = metricsDir(repoRoot);
|
|
156
|
+
const summaries = {};
|
|
157
|
+
|
|
158
|
+
if (!existsSync(dir)) {
|
|
159
|
+
return summaries;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let names;
|
|
163
|
+
try {
|
|
164
|
+
names = await readdir(dir);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error(`[memory-proposals/collector] WARN: could not read metrics dir: ${err.message}`);
|
|
167
|
+
return summaries;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const summaryFiles = names.filter(
|
|
171
|
+
(n) => n.startsWith('proposals-summary-') && n.endsWith('.json')
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
for (const filename of summaryFiles) {
|
|
175
|
+
const filePath = path.join(dir, filename);
|
|
176
|
+
try {
|
|
177
|
+
const raw = await readFile(filePath, 'utf8');
|
|
178
|
+
const parsed = JSON.parse(raw);
|
|
179
|
+
// Derive the wave_id from the filename: proposals-summary-W1.json → W1
|
|
180
|
+
const waveId = filename
|
|
181
|
+
.replace(/^proposals-summary-/, '')
|
|
182
|
+
.replace(/\.json$/, '');
|
|
183
|
+
summaries[waveId] = parsed;
|
|
184
|
+
} catch (err) {
|
|
185
|
+
console.error(
|
|
186
|
+
`[memory-proposals/collector] WARN: could not parse ${filename}: ${err.message}`
|
|
187
|
+
);
|
|
188
|
+
// Silently skip — the caller gets the fs_error count from collectProposals.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return summaries;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
// Stats accumulator
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Accumulate stats from all per-wave summary objects into a single stats record.
|
|
201
|
+
*
|
|
202
|
+
* Recognised summary fields (store.mjs convention):
|
|
203
|
+
* queued, dropped, below_floor, fs_error
|
|
204
|
+
* (wrong-context rejections exit at CLI before reaching store; not tracked here per Q1 W4 finding.)
|
|
205
|
+
*
|
|
206
|
+
* Unknown fields in summaries are ignored.
|
|
207
|
+
*
|
|
208
|
+
* @param {Record<string, object>} summaries
|
|
209
|
+
* @returns {object} accumulated stats (without parse_errors — caller fills that)
|
|
210
|
+
*/
|
|
211
|
+
function accumulateSummaryStats(summaries) {
|
|
212
|
+
const stats = zeroStats();
|
|
213
|
+
const KNOWN_FIELDS = ['queued', 'dropped', 'below_floor', 'fs_error'];
|
|
214
|
+
|
|
215
|
+
for (const summary of Object.values(summaries)) {
|
|
216
|
+
if (!summary || typeof summary !== 'object') continue;
|
|
217
|
+
for (const field of KNOWN_FIELDS) {
|
|
218
|
+
if (typeof summary[field] === 'number' && Number.isFinite(summary[field])) {
|
|
219
|
+
stats[field] += summary[field];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return stats;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Main export
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Collect all memory proposals at session-end: read proposals.jsonl + all
|
|
233
|
+
* per-wave summary JSONs, aggregate into a structured payload.
|
|
234
|
+
*
|
|
235
|
+
* @param {object} args
|
|
236
|
+
* @param {string} args.repoRoot Absolute path to the repo root.
|
|
237
|
+
* @param {number|null} [args.minConfidence=null]
|
|
238
|
+
* Optional collect-emit confidence floor (issue #566). When a finite number
|
|
239
|
+
* is supplied, records with `record.confidence < minConfidence` are dropped
|
|
240
|
+
* from the returned `queue` BEFORE the function returns. When `null`,
|
|
241
|
+
* `undefined`, or non-numeric, no filtering is applied (back-compat).
|
|
242
|
+
*
|
|
243
|
+
* This is a SECOND gate above the write-time
|
|
244
|
+
* `memory.proposals.confidence-floor` enforced by
|
|
245
|
+
* `scripts/memory-propose.mjs` — the per-record write-floor runs first,
|
|
246
|
+
* then the collect-emit floor here filters what surfaces to the operator's
|
|
247
|
+
* AUQ at session-end Phase 3.6.3. `stats` reflect the full intake (not
|
|
248
|
+
* post-filter) because they are accumulated from the per-wave summaries,
|
|
249
|
+
* not from the returned queue.
|
|
250
|
+
* @returns {Promise<{
|
|
251
|
+
* queue: object[],
|
|
252
|
+
* stats: {
|
|
253
|
+
* queued: number,
|
|
254
|
+
* dropped: number,
|
|
255
|
+
* below_floor: number,
|
|
256
|
+
* fs_error: number,
|
|
257
|
+
* parse_errors: number,
|
|
258
|
+
* },
|
|
259
|
+
* perWaveSummaries: Record<string, object>,
|
|
260
|
+
* }>}
|
|
261
|
+
*/
|
|
262
|
+
export async function collectProposals({ repoRoot, minConfidence = null }) {
|
|
263
|
+
// Short-circuit: if proposals.jsonl doesn't exist, nothing was ever queued.
|
|
264
|
+
const jsonlPath = proposalsJsonlPath(repoRoot);
|
|
265
|
+
if (!existsSync(jsonlPath)) {
|
|
266
|
+
return {
|
|
267
|
+
queue: [],
|
|
268
|
+
stats: zeroStats(),
|
|
269
|
+
perWaveSummaries: {},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Run JSONL read and per-wave summary read concurrently.
|
|
274
|
+
const [queueResult, perWaveSummaries] = await Promise.allSettled([
|
|
275
|
+
readProposalsJsonl({ repoRoot }),
|
|
276
|
+
readPerWaveSummaries(repoRoot),
|
|
277
|
+
]);
|
|
278
|
+
|
|
279
|
+
// Extract results, treating rejections as empty/no-op (should not happen
|
|
280
|
+
// since both functions catch internally, but guard defensively).
|
|
281
|
+
let queue = queueResult.status === 'fulfilled' ? queueResult.value : [];
|
|
282
|
+
const summaries =
|
|
283
|
+
perWaveSummaries.status === 'fulfilled' ? perWaveSummaries.value : {};
|
|
284
|
+
|
|
285
|
+
if (queueResult.status === 'rejected') {
|
|
286
|
+
console.error(
|
|
287
|
+
`[memory-proposals/collector] WARN: readProposalsJsonl rejected unexpectedly: ${queueResult.reason}`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
if (perWaveSummaries.status === 'rejected') {
|
|
291
|
+
console.error(
|
|
292
|
+
`[memory-proposals/collector] WARN: readPerWaveSummaries rejected unexpectedly: ${perWaveSummaries.reason}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Accumulate stats from per-wave summaries.
|
|
297
|
+
const stats = accumulateSummaryStats(summaries);
|
|
298
|
+
|
|
299
|
+
// Count parse_errors: lines in the JSONL that were NOT successfully parsed.
|
|
300
|
+
// We approximate this by reading the raw line count vs the queue length.
|
|
301
|
+
// This requires a second read-pass on the raw file — use the already-read
|
|
302
|
+
// content by re-counting; since readProposalsJsonl does the heavy lifting,
|
|
303
|
+
// we derive parse_errors from the difference between raw non-empty lines
|
|
304
|
+
// and successfully parsed records.
|
|
305
|
+
let parseErrors = 0;
|
|
306
|
+
try {
|
|
307
|
+
const raw = await readFile(jsonlPath, 'utf8');
|
|
308
|
+
const rawLineCount = raw.split('\n').filter((l) => l.length > 0).length;
|
|
309
|
+
parseErrors = Math.max(0, rawLineCount - queue.length);
|
|
310
|
+
} catch {
|
|
311
|
+
// File became unreadable between the two reads — treat as 0 parse errors.
|
|
312
|
+
}
|
|
313
|
+
stats.parse_errors = parseErrors;
|
|
314
|
+
|
|
315
|
+
// Collect-emit confidence filter (issue #566). Applies AFTER parse_errors
|
|
316
|
+
// is computed against the raw-line count, so parse_errors stays anchored to
|
|
317
|
+
// what the file actually contains. The filter only affects what the
|
|
318
|
+
// coordinator surfaces to the operator AUQ; stats reflect the full intake.
|
|
319
|
+
if (typeof minConfidence === 'number' && Number.isFinite(minConfidence)) {
|
|
320
|
+
queue = queue.filter((record) => {
|
|
321
|
+
const c = record && typeof record.confidence === 'number' ? record.confidence : null;
|
|
322
|
+
// Records with no confidence field (or NaN) are kept — the gate only
|
|
323
|
+
// drops records that actively report a confidence below the floor.
|
|
324
|
+
if (c === null || !Number.isFinite(c)) return true;
|
|
325
|
+
return c >= minConfidence;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
queue,
|
|
331
|
+
stats,
|
|
332
|
+
perWaveSummaries: summaries,
|
|
333
|
+
};
|
|
334
|
+
}
|