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,99 @@
|
|
|
1
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* slopcheck.mjs — Parser for the top-level `slopcheck:` YAML block
|
|
5
|
+
* (PRD gsd Pattern Adoption Quick-Wins — Pattern 2 / issues #517, #520).
|
|
6
|
+
*
|
|
7
|
+
* Drives the opt-in package-legitimacy gate that defends against LLM-
|
|
8
|
+
* hallucinated npm/pip/cargo package names ("slopsquatting"). Plugged into
|
|
9
|
+
* /plan PRD generation and /discovery supply-chain probes.
|
|
10
|
+
*
|
|
11
|
+
* Returns `{ enabled, sources }`.
|
|
12
|
+
* Tolerant parser: malformed values silently fall back to defaults.
|
|
13
|
+
*
|
|
14
|
+
* Consumers:
|
|
15
|
+
* - `scripts/lib/slopcheck.mjs` (classifyPackages())
|
|
16
|
+
* - `skills/discovery/probes/supply-chain-slopcheck.mjs` (discovery probe)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const ALLOWED_SOURCES = new Set(['plan', 'discovery']);
|
|
20
|
+
const DEFAULT_SOURCES = ['plan', 'discovery'];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Parse the top-level `slopcheck:` YAML block from markdown content.
|
|
24
|
+
* Independent of the `## Session Config` section boundary.
|
|
25
|
+
*
|
|
26
|
+
* Defaults:
|
|
27
|
+
* enabled: false (opt-in)
|
|
28
|
+
* sources: ['plan', 'discovery']
|
|
29
|
+
*
|
|
30
|
+
* @param {string} content — full file contents
|
|
31
|
+
* @returns {{ enabled: boolean, sources: string[] }}
|
|
32
|
+
*/
|
|
33
|
+
export function _parseSlopcheck(content) {
|
|
34
|
+
const defaults = {
|
|
35
|
+
enabled: false,
|
|
36
|
+
sources: [...DEFAULT_SOURCES],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const lines = content.split(/\r?\n/);
|
|
40
|
+
let inBlock = false;
|
|
41
|
+
const blockLines = [];
|
|
42
|
+
|
|
43
|
+
for (const rawLine of lines) {
|
|
44
|
+
const line = rawLine.replace(/\r$/, '');
|
|
45
|
+
if (!inBlock) {
|
|
46
|
+
if (matchBlockHeader(line, 'slopcheck')) inBlock = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
50
|
+
blockLines.push(line);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (blockLines.length === 0) return defaults;
|
|
54
|
+
|
|
55
|
+
let scEnabled = false;
|
|
56
|
+
let scSources = [...DEFAULT_SOURCES];
|
|
57
|
+
|
|
58
|
+
for (const rawLine of blockLines) {
|
|
59
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
60
|
+
if (!clean.trim()) continue;
|
|
61
|
+
|
|
62
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
|
|
63
|
+
if (!kvMatch) continue;
|
|
64
|
+
|
|
65
|
+
const k = kvMatch[1];
|
|
66
|
+
let v = kvMatch[2].trim();
|
|
67
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
68
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
69
|
+
|
|
70
|
+
switch (k) {
|
|
71
|
+
case 'enabled':
|
|
72
|
+
// Default is false → only flip to true on explicit "true"
|
|
73
|
+
scEnabled = v.toLowerCase() === 'true';
|
|
74
|
+
break;
|
|
75
|
+
case 'sources': {
|
|
76
|
+
// Accept inline array notation: [] or [a, b, c]
|
|
77
|
+
const stripped = v.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
|
|
78
|
+
if (stripped === '') {
|
|
79
|
+
scSources = [];
|
|
80
|
+
} else {
|
|
81
|
+
const items = stripped
|
|
82
|
+
.split(',')
|
|
83
|
+
.map((s) => s.trim())
|
|
84
|
+
.filter((s) => s.length > 0)
|
|
85
|
+
.filter((s) => ALLOWED_SOURCES.has(s));
|
|
86
|
+
// Only override the default when the parsed list is non-empty after filtering;
|
|
87
|
+
// a malformed list silently falls back to defaults.
|
|
88
|
+
if (items.length > 0) scSources = items;
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
enabled: scEnabled,
|
|
97
|
+
sources: scSources,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* state-md-lock.mjs — Parser for the top-level `state-md-lock:` YAML block
|
|
5
|
+
* (PRD gsd Pattern Adoption Quick-Wins — Pattern 1 / issues #517, #518).
|
|
6
|
+
*
|
|
7
|
+
* Drives the mechanical STATE.md write lock that prevents race conditions
|
|
8
|
+
* between parallel worker sessions writing the same STATE.md.
|
|
9
|
+
*
|
|
10
|
+
* Returns `{ enabled, "timeout-ms" }`.
|
|
11
|
+
* Tolerant parser: malformed values silently fall back to defaults.
|
|
12
|
+
*
|
|
13
|
+
* Consumer: `scripts/lib/session-lock.mjs` (Agent A — adds withStateMdLock()).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parse the top-level `state-md-lock:` YAML block from markdown content.
|
|
18
|
+
* Independent of the `## Session Config` section boundary.
|
|
19
|
+
*
|
|
20
|
+
* Defaults:
|
|
21
|
+
* enabled: true
|
|
22
|
+
* timeout-ms: 10000 (integer ≥ 0)
|
|
23
|
+
*
|
|
24
|
+
* @param {string} content — full file contents
|
|
25
|
+
* @returns {{ enabled: boolean, "timeout-ms": number }}
|
|
26
|
+
*/
|
|
27
|
+
export function _parseStateMdLock(content) {
|
|
28
|
+
const defaults = {
|
|
29
|
+
enabled: true,
|
|
30
|
+
'timeout-ms': 10000,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const lines = content.split(/\r?\n/);
|
|
34
|
+
let inBlock = false;
|
|
35
|
+
const blockLines = [];
|
|
36
|
+
|
|
37
|
+
for (const rawLine of lines) {
|
|
38
|
+
const line = rawLine.replace(/\r$/, '');
|
|
39
|
+
if (!inBlock) {
|
|
40
|
+
if (matchBlockHeader(line, 'state-md-lock')) inBlock = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
44
|
+
blockLines.push(line);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (blockLines.length === 0) return defaults;
|
|
48
|
+
|
|
49
|
+
let smlEnabled = true;
|
|
50
|
+
let smlTimeoutMs = 10000;
|
|
51
|
+
|
|
52
|
+
for (const rawLine of blockLines) {
|
|
53
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
54
|
+
if (!clean.trim()) continue;
|
|
55
|
+
|
|
56
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
|
|
57
|
+
if (!kvMatch) continue;
|
|
58
|
+
|
|
59
|
+
const k = kvMatch[1];
|
|
60
|
+
let v = kvMatch[2].trim();
|
|
61
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
62
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
63
|
+
|
|
64
|
+
switch (k) {
|
|
65
|
+
case 'enabled':
|
|
66
|
+
// Default is true → only flip to false on explicit "false"
|
|
67
|
+
smlEnabled = v.toLowerCase() !== 'false';
|
|
68
|
+
break;
|
|
69
|
+
case 'timeout-ms': {
|
|
70
|
+
if (/^\d+$/.test(v)) {
|
|
71
|
+
const n = parseInt(v, 10);
|
|
72
|
+
if (n >= 0) smlTimeoutMs = n;
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
enabled: smlEnabled,
|
|
81
|
+
'timeout-ms': smlTimeoutMs,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* templates-first.mjs — Parser for the top-level `templates-first:` YAML block
|
|
5
|
+
* (PRD gsd Pattern Adoption Quick-Wins — Pattern 3 / issues #517, #519).
|
|
6
|
+
*
|
|
7
|
+
* Drives the pre-bash hook that blocks `gh|glab pr|mr|issue create` calls
|
|
8
|
+
* unless the matching repo template (.github/PULL_REQUEST_TEMPLATE,
|
|
9
|
+
* .gitlab/merge_request_templates/*, …) was Read in the current session.
|
|
10
|
+
*
|
|
11
|
+
* Returns `{ enabled, hosts }`.
|
|
12
|
+
* Tolerant parser: malformed values silently fall back to defaults.
|
|
13
|
+
*
|
|
14
|
+
* Consumer: `hooks/pre-bash-templates-first.mjs` (Wave 2).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const ALLOWED_HOSTS = new Set(['github', 'gitlab']);
|
|
18
|
+
const DEFAULT_HOSTS = ['github', 'gitlab'];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Parse the top-level `templates-first:` YAML block from markdown content.
|
|
22
|
+
* Independent of the `## Session Config` section boundary.
|
|
23
|
+
*
|
|
24
|
+
* Defaults:
|
|
25
|
+
* enabled: true
|
|
26
|
+
* hosts: ['github', 'gitlab']
|
|
27
|
+
*
|
|
28
|
+
* @param {string} content — full file contents
|
|
29
|
+
* @returns {{ enabled: boolean, hosts: string[] }}
|
|
30
|
+
*/
|
|
31
|
+
export function _parseTemplatesFirst(content) {
|
|
32
|
+
const defaults = {
|
|
33
|
+
enabled: true,
|
|
34
|
+
hosts: [...DEFAULT_HOSTS],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const lines = content.split(/\r?\n/);
|
|
38
|
+
let inBlock = false;
|
|
39
|
+
const blockLines = [];
|
|
40
|
+
|
|
41
|
+
for (const rawLine of lines) {
|
|
42
|
+
const line = rawLine.replace(/\r$/, '');
|
|
43
|
+
if (!inBlock) {
|
|
44
|
+
if (matchBlockHeader(line, 'templates-first')) inBlock = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
48
|
+
blockLines.push(line);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (blockLines.length === 0) return defaults;
|
|
52
|
+
|
|
53
|
+
let tfEnabled = true;
|
|
54
|
+
let tfHosts = [...DEFAULT_HOSTS];
|
|
55
|
+
|
|
56
|
+
for (const rawLine of blockLines) {
|
|
57
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
58
|
+
if (!clean.trim()) continue;
|
|
59
|
+
|
|
60
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
|
|
61
|
+
if (!kvMatch) continue;
|
|
62
|
+
|
|
63
|
+
const k = kvMatch[1];
|
|
64
|
+
let v = kvMatch[2].trim();
|
|
65
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
66
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
67
|
+
|
|
68
|
+
switch (k) {
|
|
69
|
+
case 'enabled':
|
|
70
|
+
// Default is true → only flip to false on explicit "false"
|
|
71
|
+
tfEnabled = v.toLowerCase() !== 'false';
|
|
72
|
+
break;
|
|
73
|
+
case 'hosts': {
|
|
74
|
+
const stripped = v.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
|
|
75
|
+
if (stripped === '') {
|
|
76
|
+
tfHosts = [];
|
|
77
|
+
} else {
|
|
78
|
+
const items = stripped
|
|
79
|
+
.split(',')
|
|
80
|
+
.map((s) => s.trim())
|
|
81
|
+
.filter((s) => s.length > 0)
|
|
82
|
+
.filter((s) => ALLOWED_HOSTS.has(s));
|
|
83
|
+
if (items.length > 0) tfHosts = items;
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
enabled: tfEnabled,
|
|
92
|
+
hosts: tfHosts,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test.mjs — Parser for the top-level `test:` YAML block.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the docs-orchestrator / events-rotation block-parser pattern.
|
|
5
|
+
* Promoted from the inline _parseTestBlock in scripts/parse-config.mjs
|
|
6
|
+
* as part of the /test epic (#378) Track B wiring.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { validatePathInsideProject } from '../path-utils.mjs';
|
|
10
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse the top-level `test:` YAML block from markdown content.
|
|
14
|
+
* Returns defaults when the block is absent.
|
|
15
|
+
* @param {string} content — full CLAUDE.md / AGENTS.md content
|
|
16
|
+
* @returns {{enabled: boolean, "default-profile": string, "profiles-path": string, mode: string, "retention-days": number}}
|
|
17
|
+
* `profiles-path` is stored as an absolute path (realpath-resolved when the target exists,
|
|
18
|
+
* lexically-resolved via `path.resolve(cwd, v)` when the target does not exist yet) —
|
|
19
|
+
* defeats post-validation symlink-swap TOCTOU (#405, deep-4 deep-5).
|
|
20
|
+
*/
|
|
21
|
+
export function _parseTest(content) {
|
|
22
|
+
const defaults = {
|
|
23
|
+
enabled: false,
|
|
24
|
+
'default-profile': 'smoke',
|
|
25
|
+
'profiles-path': '.orchestrator/policy/test-profiles.json',
|
|
26
|
+
mode: 'warn',
|
|
27
|
+
'retention-days': 30,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const lines = content.split(/\r?\n/);
|
|
31
|
+
let inBlock = false;
|
|
32
|
+
const blockLines = [];
|
|
33
|
+
|
|
34
|
+
for (const rawLine of lines) {
|
|
35
|
+
const line = rawLine.replace(/\r$/, '');
|
|
36
|
+
if (!inBlock) {
|
|
37
|
+
// Match top-level `test:` key (not indented, no inline value after colon)
|
|
38
|
+
if (matchBlockHeader(line, 'test')) {
|
|
39
|
+
inBlock = true;
|
|
40
|
+
}
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Any non-empty, non-indented line closes the block
|
|
44
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
45
|
+
blockLines.push(line);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (blockLines.length === 0) return defaults;
|
|
49
|
+
|
|
50
|
+
let tcEnabled = false;
|
|
51
|
+
let tcDefaultProfile = 'smoke';
|
|
52
|
+
let tcProfilesPath = '.orchestrator/policy/test-profiles.json';
|
|
53
|
+
let tcMode = 'warn';
|
|
54
|
+
let tcRetentionDays = 30;
|
|
55
|
+
|
|
56
|
+
const validModes = new Set(['warn', 'strict', 'off']);
|
|
57
|
+
|
|
58
|
+
for (const rawLine of blockLines) {
|
|
59
|
+
// Strip inline YAML comments and trailing whitespace
|
|
60
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
61
|
+
if (!clean.trim()) continue;
|
|
62
|
+
|
|
63
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
|
|
64
|
+
if (!kvMatch) continue;
|
|
65
|
+
|
|
66
|
+
const k = kvMatch[1];
|
|
67
|
+
let v = kvMatch[2].trim();
|
|
68
|
+
// Strip surrounding quotes
|
|
69
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
70
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
71
|
+
|
|
72
|
+
switch (k) {
|
|
73
|
+
case 'enabled':
|
|
74
|
+
tcEnabled = v.toLowerCase() === 'true';
|
|
75
|
+
break;
|
|
76
|
+
case 'default-profile':
|
|
77
|
+
if (v) tcDefaultProfile = v;
|
|
78
|
+
break;
|
|
79
|
+
case 'profiles-path':
|
|
80
|
+
if (v) {
|
|
81
|
+
// SEC-IR-LOW-2 + SEC-Q2-LOW-1 + #402 + #405:
|
|
82
|
+
// Delegate two-phase path-traversal + symlink-escape guard to the shared helper.
|
|
83
|
+
// Store the resolved path (not raw v) to defeat TOCTOU symlink-swap attacks (#405).
|
|
84
|
+
const projectRoot = process.cwd();
|
|
85
|
+
const result = validatePathInsideProject(v, projectRoot);
|
|
86
|
+
if (result.ok) {
|
|
87
|
+
// Store resolved path, not raw v, to defeat TOCTOU symlink-swap (#405)
|
|
88
|
+
tcProfilesPath = result.realPath || result.lexicalPath;
|
|
89
|
+
}
|
|
90
|
+
// Silent skip on failure — matches the lenient pattern of other case branches
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case 'mode':
|
|
94
|
+
if (validModes.has(v.toLowerCase())) tcMode = v.toLowerCase();
|
|
95
|
+
break;
|
|
96
|
+
case 'retention-days': {
|
|
97
|
+
if (/^\d+$/.test(v)) {
|
|
98
|
+
const n = parseInt(v, 10);
|
|
99
|
+
if (n >= 0) tcRetentionDays = n;
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
enabled: tcEnabled,
|
|
108
|
+
'default-profile': tcDefaultProfile,
|
|
109
|
+
'profiles-path': tcProfilesPath,
|
|
110
|
+
mode: tcMode,
|
|
111
|
+
'retention-days': tcRetentionDays,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vault-integration.mjs — Parsers for vault-integration and resource-thresholds
|
|
3
|
+
* sub-keys.
|
|
4
|
+
*
|
|
5
|
+
* `_parseVaultIntegration(content)` reads its block scoped from the raw markdown
|
|
6
|
+
* content (cold-start.mjs style), matching the pattern used by every other
|
|
7
|
+
* block-scoped parser in `scripts/lib/config/`. Pre-#593 this parser took a
|
|
8
|
+
* flat KV map shared with all other blocks — a name-collision time bomb
|
|
9
|
+
* because `enabled:` is also used by 15+ other blocks (`docs-orchestrator`,
|
|
10
|
+
* `vault-staleness`, `slopcheck`, etc.). The last `enabled:` line in the file
|
|
11
|
+
* silently overwrote `vault-integration.enabled: true`.
|
|
12
|
+
*
|
|
13
|
+
* `_parseResourceThresholds(kv)` is unchanged: its sub-keys
|
|
14
|
+
* (`ram-free-min-gb`, `ram-free-critical-gb`, `cpu-load-max-pct`,
|
|
15
|
+
* `concurrent-sessions-warn`, `ssh-no-docker`) are unique across all blocks,
|
|
16
|
+
* so a shared KV map has no collision risk.
|
|
17
|
+
*
|
|
18
|
+
* Issue #497 inline-object form is preserved on the content-based path —
|
|
19
|
+
* a `vault-integration: { ... }` line takes precedence over a same-named
|
|
20
|
+
* block form when both are present.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { _coerceBoolean, _coerceInteger } from './coercers.mjs';
|
|
24
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// vault-integration
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
const MODE_ALLOWED = ['warn', 'strict', 'off'];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse the top-level `vault-integration:` YAML block (or inline-object literal)
|
|
34
|
+
* from the markdown content. Independent of the `## Session Config` section
|
|
35
|
+
* boundary so a baseline using either CLAUDE.md / AGENTS.md baseline-list-item form
|
|
36
|
+
* (`- vault-integration: { ... }`) or block form is handled identically.
|
|
37
|
+
*
|
|
38
|
+
* Supports two source shapes:
|
|
39
|
+
* 1. Inline object literal on a single line (issue #497):
|
|
40
|
+
* `vault-integration: { enabled: true, vault-dir: ~/Projects/vault, mode: warn }`
|
|
41
|
+
* (with or without a leading `- ` list-item dash)
|
|
42
|
+
* 2. Block form with indented sub-keys (default):
|
|
43
|
+
* ```
|
|
44
|
+
* vault-integration:
|
|
45
|
+
* enabled: true
|
|
46
|
+
* vault-dir: ~/Projects/vault
|
|
47
|
+
* mode: warn
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* The inline form takes precedence when both are present.
|
|
51
|
+
*
|
|
52
|
+
* Accepted forms: the bold-bullet markdown rendering of either shape above —
|
|
53
|
+
* `- **vault-integration:** { ... }` or a `- **vault-integration:**` header
|
|
54
|
+
* followed by an indented block — is also accepted (#823). The optional `**`
|
|
55
|
+
* is stripped only immediately around the `key:` token at line start; the
|
|
56
|
+
* value portion (including any literal `**` inside it) is untouched.
|
|
57
|
+
*
|
|
58
|
+
* Defaults:
|
|
59
|
+
* enabled: false
|
|
60
|
+
* vault-dir: null
|
|
61
|
+
* mode: "warn" (invalid values silently fall back to "warn")
|
|
62
|
+
* vault-name: null (absent = downstream callers use deriveRepo() default)
|
|
63
|
+
*
|
|
64
|
+
* @param {string} content — full file contents
|
|
65
|
+
* @returns {{enabled: boolean, "vault-dir": string|null, mode: string, "vault-name": string|null}}
|
|
66
|
+
*/
|
|
67
|
+
export function _parseVaultIntegration(content) {
|
|
68
|
+
const defaults = { enabled: false, 'vault-dir': null, mode: 'warn', 'vault-name': null };
|
|
69
|
+
if (typeof content !== 'string' || content === '') return defaults;
|
|
70
|
+
|
|
71
|
+
const lines = content.split(/\r?\n/);
|
|
72
|
+
|
|
73
|
+
// Pass 1: inline-object form. Matches `vault-integration: { ... }` with or
|
|
74
|
+
// without a leading `- ` (baseline list-item form per #497).
|
|
75
|
+
for (const rawLine of lines) {
|
|
76
|
+
const line = rawLine.replace(/\r$/, '');
|
|
77
|
+
const inlineMatch = line.match(/^(?:-\s+)?(?:\*\*)?vault-integration:(?:\*\*)?\s*(\{[^}]*\})\s*(?:#.*)?$/);
|
|
78
|
+
if (inlineMatch) {
|
|
79
|
+
return _parseInlineObject(inlineMatch[1]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Pass 2: block form. Find `^vault-integration:\s*$` (header-only line) and
|
|
84
|
+
// accumulate indented continuation lines until a non-indented line breaks
|
|
85
|
+
// out of the block.
|
|
86
|
+
let inBlock = false;
|
|
87
|
+
const blockLines = [];
|
|
88
|
+
for (const rawLine of lines) {
|
|
89
|
+
const line = rawLine.replace(/\r$/, '');
|
|
90
|
+
if (!inBlock) {
|
|
91
|
+
if (matchBlockHeader(line, 'vault-integration')) inBlock = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
95
|
+
blockLines.push(line);
|
|
96
|
+
}
|
|
97
|
+
if (blockLines.length === 0) return defaults;
|
|
98
|
+
|
|
99
|
+
let enabled = false;
|
|
100
|
+
let vaultDir = null;
|
|
101
|
+
let mode = 'warn';
|
|
102
|
+
let vaultName = null;
|
|
103
|
+
|
|
104
|
+
for (const rawLine of blockLines) {
|
|
105
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
106
|
+
if (!clean.trim()) continue;
|
|
107
|
+
|
|
108
|
+
// Only first-level sub-keys (single indent). Skip deeper nested keys like
|
|
109
|
+
// `gitlab-groups:` list items (handled as a no-op — they aren't in this
|
|
110
|
+
// parser's return shape).
|
|
111
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)$/);
|
|
112
|
+
if (!kvMatch) continue;
|
|
113
|
+
|
|
114
|
+
const k = kvMatch[1];
|
|
115
|
+
let v = kvMatch[2].trim();
|
|
116
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
117
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
118
|
+
|
|
119
|
+
switch (k) {
|
|
120
|
+
case 'enabled':
|
|
121
|
+
// Strict booleans only. Anything other than "true"/"false" stays at default (false).
|
|
122
|
+
if (v.toLowerCase() === 'true') enabled = true;
|
|
123
|
+
else if (v.toLowerCase() === 'false') enabled = false;
|
|
124
|
+
break;
|
|
125
|
+
case 'vault-dir':
|
|
126
|
+
if (v === '' || v === 'none' || v === 'null') vaultDir = null;
|
|
127
|
+
else vaultDir = v;
|
|
128
|
+
break;
|
|
129
|
+
case 'mode':
|
|
130
|
+
if (MODE_ALLOWED.includes(v.toLowerCase())) mode = v.toLowerCase();
|
|
131
|
+
else mode = 'warn'; // silent fallback (parity with pre-#593 behaviour)
|
|
132
|
+
break;
|
|
133
|
+
case 'vault-name':
|
|
134
|
+
if (v === '' || v === 'none' || v === 'null') vaultName = null;
|
|
135
|
+
else vaultName = v;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return { enabled, 'vault-dir': vaultDir, mode, 'vault-name': vaultName };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Parse an inline YAML object literal `{ key: val, key: val }` into the
|
|
145
|
+
* vault-integration return shape. Supports unquoted values including `~/` paths.
|
|
146
|
+
*
|
|
147
|
+
* @param {string} raw — full literal including braces
|
|
148
|
+
* @returns {{enabled: boolean, "vault-dir": string|null, mode: string}}
|
|
149
|
+
*/
|
|
150
|
+
function _parseInlineObject(raw) {
|
|
151
|
+
const stripped = raw.replace(/^\s*\{/, '').replace(/\}\s*$/, '').trim();
|
|
152
|
+
const kv = new Map();
|
|
153
|
+
if (stripped !== '') {
|
|
154
|
+
for (const pair of stripped.split(',')) {
|
|
155
|
+
const colonIdx = pair.indexOf(':');
|
|
156
|
+
if (colonIdx === -1) continue;
|
|
157
|
+
const k = pair.slice(0, colonIdx).trim();
|
|
158
|
+
const v = pair.slice(colonIdx + 1).trim();
|
|
159
|
+
if (k) kv.set(k, v);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const enabledRaw = kv.get('enabled');
|
|
164
|
+
const enabled = enabledRaw === 'true' ? true : false;
|
|
165
|
+
const vaultDirRaw = kv.get('vault-dir');
|
|
166
|
+
const vaultDir =
|
|
167
|
+
vaultDirRaw === undefined || vaultDirRaw === '' || vaultDirRaw === 'none' || vaultDirRaw === 'null'
|
|
168
|
+
? null
|
|
169
|
+
: vaultDirRaw;
|
|
170
|
+
const modeRaw = kv.get('mode') ?? 'warn';
|
|
171
|
+
const mode = MODE_ALLOWED.includes(modeRaw.toLowerCase()) ? modeRaw.toLowerCase() : 'warn';
|
|
172
|
+
const vaultNameRaw = kv.get('vault-name');
|
|
173
|
+
const vaultName =
|
|
174
|
+
vaultNameRaw === undefined || vaultNameRaw === '' || vaultNameRaw === 'none' || vaultNameRaw === 'null'
|
|
175
|
+
? null
|
|
176
|
+
: vaultNameRaw;
|
|
177
|
+
return { enabled, 'vault-dir': vaultDir, mode, 'vault-name': vaultName };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
// resource-thresholds
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
|
|
184
|
+
// Sub-key names are deliberately unique across all blocks (no collision with
|
|
185
|
+
// vault-integration / vault-sync / others) because they are flattened into the
|
|
186
|
+
// same KV map by the Session Config parser. See the A5 note in parse-config.sh.
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Extract resource-thresholds sub-keys from the Session Config KV map.
|
|
190
|
+
* @param {Map<string, string>} kv
|
|
191
|
+
* @returns {{[key: string]: number|boolean}}
|
|
192
|
+
*/
|
|
193
|
+
export function _parseResourceThresholds(kv) {
|
|
194
|
+
return {
|
|
195
|
+
'ram-free-min-gb': _coerceInteger(kv, 'ram-free-min-gb', 4),
|
|
196
|
+
'ram-free-critical-gb': _coerceInteger(kv, 'ram-free-critical-gb', 2),
|
|
197
|
+
'cpu-load-max-pct': _coerceInteger(kv, 'cpu-load-max-pct', 80),
|
|
198
|
+
'concurrent-sessions-warn': _coerceInteger(kv, 'concurrent-sessions-warn', 5),
|
|
199
|
+
'ssh-no-docker': _coerceBoolean(kv, 'ssh-no-docker', true),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* vault-mirror-quality.mjs — Parser for the top-level `vault-mirror:` YAML block,
|
|
5
|
+
* extracting the nested `quality:` sub-block (PRD F1.2 / issue #504).
|
|
6
|
+
*
|
|
7
|
+
* Returns the consumer-facing shape `{ quality: { "min-narrative-chars": int, "min-confidence": float } }`.
|
|
8
|
+
* Tolerant parser: malformed values silently fall back to defaults.
|
|
9
|
+
*
|
|
10
|
+
* Consumer: `scripts/vault-mirror.mjs` (I4's code).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parse the top-level `vault-mirror:` YAML block from markdown content, extracting
|
|
15
|
+
* the nested `quality:` sub-block. Independent of the `## Session Config` section
|
|
16
|
+
* boundary (mirrors `_parseEventsRotation` / `_parseVaultStaleness` design).
|
|
17
|
+
*
|
|
18
|
+
* Defaults:
|
|
19
|
+
* quality.min-narrative-chars: 400 (integer ≥ 0)
|
|
20
|
+
* quality.min-confidence: 0.5 (float in [0.0, 1.0])
|
|
21
|
+
*
|
|
22
|
+
* @param {string} content — full file contents
|
|
23
|
+
* @returns {{ quality: { "min-narrative-chars": number, "min-confidence": number } }}
|
|
24
|
+
*/
|
|
25
|
+
export function _parseVaultMirrorQuality(content) {
|
|
26
|
+
const defaults = {
|
|
27
|
+
quality: {
|
|
28
|
+
'min-narrative-chars': 400,
|
|
29
|
+
'min-confidence': 0.5,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const lines = content.split(/\r?\n/);
|
|
34
|
+
let inBlock = false;
|
|
35
|
+
const blockLines = [];
|
|
36
|
+
|
|
37
|
+
for (const rawLine of lines) {
|
|
38
|
+
const line = rawLine.replace(/\r$/, '');
|
|
39
|
+
if (!inBlock) {
|
|
40
|
+
if (matchBlockHeader(line, 'vault-mirror')) inBlock = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Stop at next top-level (non-indented, non-empty) key
|
|
44
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
45
|
+
blockLines.push(line);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (blockLines.length === 0) return defaults;
|
|
49
|
+
|
|
50
|
+
let qMinChars = 400;
|
|
51
|
+
let qMinConfidence = 0.5;
|
|
52
|
+
let inQualityBlock = false;
|
|
53
|
+
|
|
54
|
+
for (const rawLine of blockLines) {
|
|
55
|
+
const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
|
|
56
|
+
if (!clean.trim()) continue;
|
|
57
|
+
|
|
58
|
+
// Deeper-indented key (4+ spaces) → quality sub-key
|
|
59
|
+
const deepMatch = clean.match(/^\s{4,}([a-zA-Z_-]+):\s*(.*)/);
|
|
60
|
+
if (deepMatch && inQualityBlock) {
|
|
61
|
+
const k = deepMatch[1];
|
|
62
|
+
let v = deepMatch[2].trim();
|
|
63
|
+
if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
|
|
64
|
+
else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
|
|
65
|
+
|
|
66
|
+
if (k === 'min-narrative-chars') {
|
|
67
|
+
if (/^\d+$/.test(v)) {
|
|
68
|
+
const n = parseInt(v, 10);
|
|
69
|
+
if (n >= 0) qMinChars = n;
|
|
70
|
+
}
|
|
71
|
+
} else if (k === 'min-confidence') {
|
|
72
|
+
if (/^\d+(\.\d+)?$/.test(v)) {
|
|
73
|
+
const f = parseFloat(v);
|
|
74
|
+
if (Number.isFinite(f) && f >= 0.0 && f <= 1.0) qMinConfidence = f;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Top-level key inside vault-mirror (2-space indent) — looking for `quality:`
|
|
81
|
+
const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
|
|
82
|
+
if (!kvMatch) continue;
|
|
83
|
+
|
|
84
|
+
inQualityBlock = false;
|
|
85
|
+
const k = kvMatch[1];
|
|
86
|
+
const v = kvMatch[2].trim();
|
|
87
|
+
|
|
88
|
+
if (k === 'quality' && v === '') {
|
|
89
|
+
inQualityBlock = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
quality: {
|
|
95
|
+
'min-narrative-chars': qMinChars,
|
|
96
|
+
'min-confidence': qMinConfidence,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|