session-orchestrator 3.24.0 → 4.0.1
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/.agents/skills/architecture/SKILL.md +18 -0
- package/.agents/skills/autopilot/SKILL.md +17 -0
- package/.agents/skills/bootstrap/SKILL.md +20 -0
- package/.agents/skills/brainstorm/SKILL.md +22 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +15 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +22 -0
- package/.agents/skills/debug/SKILL.md +22 -0
- package/.agents/skills/discovery/SKILL.md +20 -0
- package/.agents/skills/dispatcher/SKILL.md +15 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +18 -0
- package/.agents/skills/ecosystem-health/SKILL.md +20 -0
- package/.agents/skills/eli5/SKILL.md +20 -0
- package/.agents/skills/eval/SKILL.md +21 -0
- package/.agents/skills/evolve/SKILL.md +21 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +15 -0
- package/.agents/skills/gitlab-ops/SKILL.md +20 -0
- package/.agents/skills/gitlab-portfolio/SKILL.md +15 -0
- package/.agents/skills/grill/SKILL.md +22 -0
- package/.agents/skills/hook-development/SKILL.md +15 -0
- package/.agents/skills/mcp-builder/SKILL.md +15 -0
- package/.agents/skills/memory-cleanup/SKILL.md +21 -0
- package/.agents/skills/mode-selector/SKILL.md +17 -0
- package/.agents/skills/npm-publish/SKILL.md +16 -0
- package/.agents/skills/peekaboo-driver/SKILL.md +18 -0
- package/.agents/skills/persona-panel/SKILL.md +17 -0
- package/.agents/skills/plan/SKILL.md +20 -0
- package/.agents/skills/playwright-driver/SKILL.md +20 -0
- package/.agents/skills/quality-gates/SKILL.md +20 -0
- package/.agents/skills/reconcile/SKILL.md +21 -0
- package/.agents/skills/remote-offload/SKILL.md +20 -0
- package/.agents/skills/repo-audit/SKILL.md +16 -0
- package/.agents/skills/session-end/SKILL.md +20 -0
- package/.agents/skills/session-plan/SKILL.md +20 -0
- package/.agents/skills/session-start/SKILL.md +20 -0
- package/.agents/skills/spinout/SKILL.md +16 -0
- package/.agents/skills/sunset-review/SKILL.md +16 -0
- package/.agents/skills/test-runner/SKILL.md +20 -0
- package/.agents/skills/tmux-layout/SKILL.md +21 -0
- package/.agents/skills/using-orchestrator/SKILL.md +17 -0
- package/.agents/skills/vault-mirror/SKILL.md +15 -0
- package/.agents/skills/vault-sync/SKILL.md +15 -0
- package/.agents/skills/wave-executor/SKILL.md +20 -0
- package/.agents/skills/write-executable-plan/SKILL.md +22 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +3 -2
- package/.codex-plugin/skills/architecture/SKILL.md +20 -0
- package/.codex-plugin/skills/autopilot/SKILL.md +21 -0
- package/.codex-plugin/skills/autopilot/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/bootstrap/SKILL.md +22 -0
- package/.codex-plugin/skills/bootstrap/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/brainstorm/SKILL.md +22 -0
- package/.codex-plugin/skills/brainstorm/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +17 -0
- package/.codex-plugin/skills/close/SKILL.md +21 -0
- package/.codex-plugin/skills/close/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +24 -0
- package/.codex-plugin/skills/debug/SKILL.md +21 -0
- package/.codex-plugin/skills/debug/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/discovery/SKILL.md +21 -0
- package/.codex-plugin/skills/discovery/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/dispatcher/SKILL.md +21 -0
- package/.codex-plugin/skills/dispatcher/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/docs-orchestrator/SKILL.md +20 -0
- package/.codex-plugin/skills/ecosystem-health/SKILL.md +22 -0
- package/.codex-plugin/skills/eli5/SKILL.md +21 -0
- package/.codex-plugin/skills/eli5/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/eval/SKILL.md +21 -0
- package/.codex-plugin/skills/eval/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/evolve/SKILL.md +21 -0
- package/.codex-plugin/skills/evolve/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/frontmatter-guard/SKILL.md +17 -0
- package/.codex-plugin/skills/gitlab-ops/SKILL.md +22 -0
- package/.codex-plugin/skills/gitlab-portfolio/SKILL.md +17 -0
- package/.codex-plugin/skills/go/SKILL.md +22 -0
- package/.codex-plugin/skills/go/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/grill/SKILL.md +21 -0
- package/.codex-plugin/skills/grill/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/harness-audit/SKILL.md +19 -0
- package/.codex-plugin/skills/harness-audit/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/hook-development/SKILL.md +17 -0
- package/.codex-plugin/skills/mcp-builder/SKILL.md +17 -0
- package/.codex-plugin/skills/memory-cleanup/SKILL.md +21 -0
- package/.codex-plugin/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/mode-selector/SKILL.md +19 -0
- package/.codex-plugin/skills/npm-publish/SKILL.md +18 -0
- package/.codex-plugin/skills/peekaboo-driver/SKILL.md +20 -0
- package/.codex-plugin/skills/persona-panel/SKILL.md +22 -0
- package/.codex-plugin/skills/persona-panel/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/plan/SKILL.md +22 -0
- package/.codex-plugin/skills/plan/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/playwright-driver/SKILL.md +22 -0
- package/.codex-plugin/skills/portfolio/SKILL.md +21 -0
- package/.codex-plugin/skills/portfolio/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/quality-gates/SKILL.md +22 -0
- package/.codex-plugin/skills/reconcile/SKILL.md +21 -0
- package/.codex-plugin/skills/reconcile/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/release/SKILL.md +22 -0
- package/.codex-plugin/skills/release/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/remote-offload/SKILL.md +22 -0
- package/.codex-plugin/skills/repo-audit/SKILL.md +19 -0
- package/.codex-plugin/skills/repo-audit/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/session/SKILL.md +21 -0
- package/.codex-plugin/skills/session/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/session-end/SKILL.md +22 -0
- package/.codex-plugin/skills/session-plan/SKILL.md +22 -0
- package/.codex-plugin/skills/session-start/SKILL.md +22 -0
- package/.codex-plugin/skills/spinout/SKILL.md +21 -0
- package/.codex-plugin/skills/spinout/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/sunset-review/SKILL.md +21 -0
- package/.codex-plugin/skills/sunset-review/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/templates-ack/SKILL.md +21 -0
- package/.codex-plugin/skills/templates-ack/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/test/SKILL.md +21 -0
- package/.codex-plugin/skills/test/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/test-runner/SKILL.md +22 -0
- package/.codex-plugin/skills/tmux-layout/SKILL.md +23 -0
- package/.codex-plugin/skills/using-orchestrator/SKILL.md +19 -0
- package/.codex-plugin/skills/vault-mirror/SKILL.md +17 -0
- package/.codex-plugin/skills/vault-sync/SKILL.md +17 -0
- package/.codex-plugin/skills/wave-executor/SKILL.md +22 -0
- package/.codex-plugin/skills/write-executable-plan/SKILL.md +24 -0
- package/.cursor/commands/autopilot.md +2 -2
- package/.cursor/commands/bootstrap.md +1 -1
- package/.cursor/commands/brainstorm.md +1 -1
- package/.cursor/commands/debug.md +1 -1
- package/.cursor/commands/discovery.md +1 -1
- package/.cursor/commands/dispatcher.md +2 -2
- package/.cursor/commands/eli5.md +2 -2
- package/.cursor/commands/eval.md +2 -2
- package/.cursor/commands/evolve.md +1 -1
- package/.cursor/commands/go.md +1 -1
- package/.cursor/commands/grill.md +2 -2
- package/.cursor/commands/memory-cleanup.md +2 -2
- package/.cursor/commands/persona-panel.md +1 -1
- package/.cursor/commands/plan.md +1 -1
- package/.cursor/commands/portfolio.md +1 -1
- package/.cursor/commands/reconcile.md +2 -2
- package/.cursor/commands/release.md +2 -2
- package/.cursor/commands/session.md +2 -2
- package/.cursor/commands/spinout.md +2 -2
- package/.cursor/commands/sunset-review.md +2 -2
- package/.cursor/commands/templates-ack.md +2 -2
- package/.cursor/commands/test.md +2 -2
- package/.cursor/skills/brainstorm/SKILL.md +1 -1
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/quality-gates/SKILL.md +1 -1
- package/.cursor/skills/remote-offload/SKILL.md +1 -1
- package/.cursor-plugin/plugin.json +30 -0
- package/.orchestrator/policy/blocked-commands.json +121 -0
- package/.orchestrator/policy/ecosystem.schema.json +66 -0
- package/.orchestrator/policy/quality-gates.example.json +16 -0
- package/.orchestrator/policy/quality-gates.schema.json +38 -0
- package/.orchestrator/policy/templates-policy.json +27 -0
- package/.orchestrator/policy/test-profiles.json +47 -0
- package/AGENTS.md +225 -0
- package/CHANGELOG.md +1314 -2
- package/NOTICE +11 -6
- package/README.md +135 -94
- package/agents/eval-judge.md +1 -1
- package/agents/skill-applied-judge.md +1 -1
- package/assets/wave-lifecycle.svg +98 -0
- package/commands/release.md +6 -3
- package/commands/session.md +18 -3
- package/docs/README.md +4 -0
- package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
- package/docs/baseline.md +67 -0
- package/docs/ci-setup.md +108 -62
- package/docs/codex-setup.md +107 -29
- package/docs/components.md +38 -16
- package/docs/cursor-setup.md +6 -2
- package/docs/events-schema.md +9 -6
- package/docs/instruction-delivery.md +69 -0
- package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
- package/docs/migration-v4.md +365 -0
- package/docs/pi-setup.md +6 -1
- package/docs/plugin-architecture-v3.md +1 -1
- package/docs/rule-authoring.md +85 -19
- package/docs/scope-collision-guard.md +5 -5
- package/docs/session-config-reference.md +57 -56
- package/docs/session-config-template.md +6 -29
- package/docs/telemetry.md +157 -3
- package/docs/vault-docs-architecture.md +50 -11
- package/hooks/_lib/hook-import-set.json +1488 -0
- package/hooks/_lib/subagent-transcript.mjs +562 -0
- package/hooks/config-protection.mjs +2 -2
- package/hooks/cwd-change-restore.mjs +2 -2
- package/hooks/enforce-commands.mjs +69 -0
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +10 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/loop-guard.mjs +3 -3
- package/hooks/on-session-end.mjs +2 -2
- package/hooks/on-session-start.mjs +103 -2
- package/hooks/on-stop.mjs +60 -14
- package/hooks/operator-steer.mjs +2 -2
- package/hooks/post-bash-write-verify.mjs +85 -0
- package/hooks/post-edit-import-probe.mjs +344 -0
- package/hooks/post-subagent-discovery-validator.mjs +187 -431
- package/hooks/post-tool-batch-wave-signal.mjs +118 -4
- package/hooks/post-tool-failure-corrective-context.mjs +2 -2
- package/hooks/post-tooluse-frontend-slop.mjs +3 -3
- package/hooks/pre-bash-destructive-guard.mjs +39 -13
- package/hooks/skill-invocation-telemetry.mjs +17 -5
- package/hooks/subagent-telemetry.mjs +13 -4
- package/monitors/monitors.json +3 -3
- package/package.json +9 -1
- package/pi/prompts/session.md +2 -2
- package/scripts/backfill-abandoned-sessions.mjs +50 -4
- package/scripts/backfill-learnings-from-vault.mjs +9 -3
- package/scripts/dialectic-deriver.mjs +73 -8
- package/scripts/export-hw-learnings.mjs +113 -1
- package/scripts/generate-agents-skills.mjs +378 -0
- package/scripts/generate-codex-skills.mjs +246 -0
- package/scripts/generate-cursor-adapter.mjs +45 -8
- package/scripts/generate-hook-import-set.mjs +292 -0
- package/scripts/lib/agent-status.mjs +13 -2
- package/scripts/lib/auto-dream.mjs +38 -36
- package/scripts/lib/autonomy/suitability.mjs +6 -0
- package/scripts/lib/autopilot/loop.mjs +2 -2
- package/scripts/lib/ci-status-banner.mjs +220 -75
- package/scripts/lib/codex/plugin-contract.mjs +88 -6
- package/scripts/lib/config/auto-dream.mjs +2 -1
- package/scripts/lib/config/block-header.mjs +8 -0
- package/scripts/lib/config/block-preprocess.mjs +177 -0
- package/scripts/lib/config/broken-window.mjs +2 -1
- package/scripts/lib/config/cold-start.mjs +2 -1
- package/scripts/lib/config/config-protection.mjs +22 -2
- package/scripts/lib/config/context-coverage.mjs +2 -1
- package/scripts/lib/config/cross-repo.mjs +2 -1
- package/scripts/lib/config/custom-phases.mjs +2 -1
- package/scripts/lib/config/dialectic.mjs +2 -1
- package/scripts/lib/config/discovery-validator.mjs +2 -1
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
- package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
- package/scripts/lib/config/docs-orchestrator.mjs +2 -1
- package/scripts/lib/config/docs-staleness.mjs +2 -1
- package/scripts/lib/config/drift-check.mjs +2 -1
- package/scripts/lib/config/eval.mjs +2 -1
- package/scripts/lib/config/events-rotation.mjs +2 -1
- package/scripts/lib/config/evolve.mjs +8 -2
- package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
- package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
- package/scripts/lib/config/handover-gate.mjs +2 -1
- package/scripts/lib/config/health-endpoints.mjs +7 -2
- package/scripts/lib/config/host-paths.mjs +20 -4
- package/scripts/lib/config/issue-budget.mjs +2 -1
- package/scripts/lib/config/loop-guard.mjs +2 -1
- package/scripts/lib/config/memory.mjs +2 -1
- package/scripts/lib/config/moc-staleness.mjs +2 -1
- package/scripts/lib/config/persona-gate-wave.mjs +2 -1
- package/scripts/lib/config/private-config-dir.mjs +67 -0
- package/scripts/lib/config/reconcile.mjs +2 -1
- package/scripts/lib/config/remote-hosts.mjs +2 -1
- package/scripts/lib/config/section-extractor.mjs +7 -1
- package/scripts/lib/config/skill-evolution.mjs +2 -1
- package/scripts/lib/config/slopcheck.mjs +2 -1
- package/scripts/lib/config/state-md-lock.mjs +2 -1
- package/scripts/lib/config/templates-first.mjs +2 -1
- package/scripts/lib/config/test.mjs +2 -1
- package/scripts/lib/config/vault-integration.mjs +7 -1
- package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
- package/scripts/lib/config/vault-staleness.mjs +2 -1
- package/scripts/lib/config/vault-sync.mjs +2 -1
- package/scripts/lib/config/verification-auto-fix.mjs +2 -1
- package/scripts/lib/config/wave-reviewers.mjs +2 -1
- package/scripts/lib/config/worktree-orphans.mjs +2 -1
- package/scripts/lib/convergence-monitor.mjs +82 -16
- package/scripts/lib/dispatcher/rank.mjs +124 -48
- package/scripts/lib/ecosystem-health.mjs +16 -2
- package/scripts/lib/eval/engine.mjs +9 -1
- package/scripts/lib/eval/session-resolve.mjs +23 -4
- package/scripts/lib/events.mjs +22 -6
- package/scripts/lib/frontmatter-guard.mjs +131 -13
- package/scripts/lib/gates/gate-full.mjs +30 -0
- package/scripts/lib/gates/gate-helpers.mjs +76 -0
- package/scripts/lib/hardware-pattern-detector.mjs +18 -1
- package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
- package/scripts/lib/host-identity.mjs +50 -11
- package/scripts/lib/instruction-budget-guard.mjs +171 -5
- package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
- package/scripts/lib/learnings/io.mjs +60 -6
- package/scripts/lib/memory-proposals/store.mjs +30 -22
- package/scripts/lib/owner-config-banner.mjs +41 -6
- package/scripts/lib/owner-config-loader.mjs +21 -10
- package/scripts/lib/owner-interview.mjs +3 -3
- package/scripts/lib/owner-yaml.mjs +215 -15
- package/scripts/lib/platform.mjs +108 -15
- package/scripts/lib/plugin-update-banner.mjs +414 -0
- package/scripts/lib/project-hygiene.mjs +38 -2
- package/scripts/lib/qg-command-drift-banner.mjs +50 -12
- package/scripts/lib/quality-gate.mjs +133 -44
- package/scripts/lib/reconcile/emitter.mjs +68 -6
- package/scripts/lib/reconcile/engine.mjs +51 -11
- package/scripts/lib/reconcile/idempotency.mjs +37 -4
- package/scripts/lib/reconcile/writer.mjs +40 -18
- package/scripts/lib/session-close-backfill.mjs +67 -9
- package/scripts/lib/session-id.mjs +12 -23
- package/scripts/lib/session-identity/own-session.mjs +125 -10
- package/scripts/lib/session-lock-shape.mjs +43 -0
- package/scripts/lib/session-lock.mjs +5 -10
- package/scripts/lib/session-registry.mjs +25 -9
- package/scripts/lib/session-schema/constants.mjs +64 -3
- package/scripts/lib/session-schema/validator.mjs +38 -4
- package/scripts/lib/session-start-probes.mjs +30 -1
- package/scripts/lib/sessions-staleness-banner.mjs +18 -11
- package/scripts/lib/skill-health/join.mjs +17 -4
- package/scripts/lib/state-md.mjs +78 -0
- package/scripts/lib/sunset/walker.mjs +6 -0
- package/scripts/lib/telemetry/schema.mjs +202 -9
- package/scripts/lib/telemetry/sync.mjs +368 -12
- package/scripts/lib/telemetry-flush-health-banner.mjs +211 -0
- package/scripts/lib/validate/check-agents-skills.mjs +327 -0
- package/scripts/lib/validate/check-agents.mjs +3 -3
- package/scripts/lib/validate/check-codex-skills.mjs +191 -0
- package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
- package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
- package/scripts/lib/validate/check-owner-leakage.mjs +319 -22
- package/scripts/lib/validate/check-skill-links.mjs +193 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +47 -28
- package/scripts/lib/validate/check-test-git-config-target.mjs +192 -12
- package/scripts/lib/validate/check-unwired-features.mjs +163 -15
- package/scripts/lib/validate/check-validator-registration.mjs +10 -4
- package/scripts/lib/validate/confidential-names.mjs +95 -30
- package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
- package/scripts/lib/validate/repo-files.mjs +48 -14
- package/scripts/lib/vault-backfill/template.mjs +63 -6
- package/scripts/lib/vault-mirror/process.mjs +165 -42
- package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
- package/scripts/lib/vault-status/narrative-mirror.mjs +127 -18
- package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
- package/scripts/lib/wave-executor/remote-dispatch.mjs +5 -7
- package/scripts/lib/wave-resource-gate.mjs +8 -2
- package/scripts/lib/wave-sizing.mjs +4 -1
- package/scripts/lib/wave-transcript-tail.mjs +118 -4
- package/scripts/materialize-wave-scope.mjs +12 -5
- package/scripts/memory-propose.mjs +19 -5
- package/scripts/migrate-cold-start-seed.mjs +4 -1
- package/scripts/parse-config.mjs +60 -3
- package/scripts/release.mjs +430 -31
- package/scripts/repair-invalid-sessions.mjs +3 -3
- package/scripts/run-quality-gate.mjs +128 -11
- package/scripts/site-numbers.mjs +344 -8
- package/scripts/sweep-expired-learnings.mjs +90 -0
- package/scripts/sync-vault-schema.mjs +3 -1
- package/scripts/telemetry.mjs +2 -2
- package/scripts/validate-plugin.mjs +164 -0
- package/scripts/validate-wave-scope.mjs +28 -8
- package/scripts/wave-scope-binding.mjs +215 -0
- package/skills/_shared/instruction-file-resolution.md +10 -0
- package/skills/_shared/parallel-aware-preamble.md +1 -0
- package/skills/_shared/platform-tools.md +1 -1
- package/skills/_shared/state-ownership.md +1 -1
- package/skills/architecture/SKILL.md +7 -5
- package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
- package/skills/autopilot/SKILL.md +4 -18
- package/skills/claude-md-drift-check/SKILL.md +5 -1
- package/skills/claude-md-drift-check/checker.mjs +62 -2
- package/skills/convergence-monitoring/SIGNALS.md +55 -0
- package/skills/discovery/probes/vault-staleness.mjs +37 -13
- package/skills/discovery/probes-arch.md +20 -18
- package/skills/dispatcher/SKILL.md +3 -2
- package/skills/evolve/SKILL.md +65 -26
- package/skills/frontmatter-guard/SKILL.md +11 -5
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +33 -0
- package/skills/remote-offload/SKILL.md +1 -1
- package/skills/session-end/SKILL.md +18 -905
- package/skills/session-end/phase-3-6-tail.md +10 -3
- package/skills/session-end/plan-verification.md +221 -155
- package/skills/session-end/references/phase-2-quality-gate.md +93 -0
- package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
- package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
- package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
- package/skills/session-end/references/session-summary-template.md +62 -0
- package/skills/session-plan/SKILL.md +49 -0
- package/skills/session-start/SKILL.md +22 -904
- package/skills/session-start/phase-8-5-express-path.md +1 -1
- package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
- package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
- package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
- package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
- package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
- package/skills/session-start/references/phase-4-ssot-environment-check.md +160 -0
- package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
- package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
- package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
- package/skills/vault-sync/SKILL.md +10 -0
- package/skills/vault-sync/validator.mjs +21 -27
- package/skills/wave-executor/SKILL.md +15 -1
- package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
- package/skills/wave-executor/references/wave-loop-review.md +570 -0
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
- package/skills/wave-executor/wave-loop.md +14 -1309
- package/templates/_shared/journey-manifest.md +10 -6
- package/.cursor/commands/autopilot-multi.md +0 -14
- package/.cursor/commands/contract-version-bump.md +0 -14
- package/.cursor/commands/journey-audit.md +0 -14
- package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
- package/.cursor/skills/daily/SKILL.md +0 -12
- package/.cursor/skills/domain-model/SKILL.md +0 -13
- package/.cursor/skills/journey-audit/SKILL.md +0 -13
- package/.cursor/skills/skill-creator/SKILL.md +0 -13
- package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
- package/commands/autopilot-multi.md +0 -74
- package/commands/contract-version-bump.md +0 -28
- package/commands/journey-audit.md +0 -43
- package/pi/prompts/autopilot-multi.md +0 -12
- package/pi/prompts/contract-version-bump.md +0 -12
- package/pi/prompts/journey-audit.md +0 -12
- package/scripts/autopilot-multi.mjs +0 -885
- package/scripts/backfill-learnings-expires.mjs +0 -196
- package/scripts/backfill-learnings.mjs +0 -203
- package/scripts/fleet-instruction-scan.mjs +0 -141
- package/scripts/lib/autopilot/dep-graph.mjs +0 -417
- package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
- package/scripts/lib/webhook-url.mjs +0 -105
- package/scripts/lifecycle-sim-v6.mjs +0 -347
- package/scripts/migrate-learnings-jsonl.mjs +0 -189
- package/scripts/migrate-subagents-jsonl.mjs +0 -196
- package/scripts/upload-social-preview.mjs +0 -316
- package/skills/_shared/model-selection.md +0 -64
- package/skills/contract-version-bump/SKILL.md +0 -219
- package/skills/daily/SKILL.md +0 -222
- package/skills/daily/generate.sh +0 -92
- package/skills/daily/templates/daily.md.tpl +0 -36
- package/skills/journey-audit/SKILL.md +0 -270
- package/skills/skill-creator/SKILL.md +0 -168
- package/skills/ubiquitous-language/SKILL.md +0 -97
- package/skills/vault-sync/package-lock.json +0 -40
- /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
- /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* block-preprocess.mjs — THE line-preprocessing contract for the block parsers
|
|
3
|
+
* under `scripts/lib/config/` (#1162).
|
|
4
|
+
*
|
|
5
|
+
* Every block parser here begins with `content.split(/\r?\n/)`, then walks lines
|
|
6
|
+
* looking for its own header and the indented sub-keys under it. Two markdown
|
|
7
|
+
* shapes that are ordinary in a CLAUDE.md / AGENTS.md were invisible to that
|
|
8
|
+
* walk, and both failed in the dangerous direction:
|
|
9
|
+
*
|
|
10
|
+
* (a) A block commented OUT with a multi-line `<!-- … -->` was read as LIVE
|
|
11
|
+
* config. Commenting a key out is the most ordinary way to disable it; it
|
|
12
|
+
* must not arm it. (`_extractConfigSection` learned this in #1097 — the
|
|
13
|
+
* block parsers never did.)
|
|
14
|
+
* (b) The bold-bullet rendering of a SUB-key (`- **enabled:** true`) matched
|
|
15
|
+
* no sub-key regex, so the key was absent and its DEFAULT applied. For a
|
|
16
|
+
* boolean that default is `false`, which reads exactly like a deliberately
|
|
17
|
+
* disabled block — no error, in any log. #823 fixed this for the block
|
|
18
|
+
* HEADER only (see `block-header.mjs`); this fixes it for the body.
|
|
19
|
+
*
|
|
20
|
+
* ZERO IMPORTS beyond the sibling `section-extractor.mjs` skipper, stdlib only —
|
|
21
|
+
* `tests/lib/config/cycle-guard.test.mjs` forbids any `scripts/lib/config/*.mjs`
|
|
22
|
+
* from importing `../config.mjs`, and the RAW-PARITY constraint (block-header.mjs
|
|
23
|
+
* docblock) requires the normalisation to live in the helper each parser calls,
|
|
24
|
+
* never in a preprocessing step in `config.mjs`.
|
|
25
|
+
*
|
|
26
|
+
* DELIBERATE NON-GOAL — fenced code blocks. These parsers are fence-UNAWARE, and
|
|
27
|
+
* that is a pinned contract, not an oversight. Two tests, cited by NAME because
|
|
28
|
+
* line numbers rot: `tests/lib/config/frontend-slop-hook.test.mjs` — "parses a
|
|
29
|
+
* block wrapped in a fenced code block — the parser is fence-unaware", and
|
|
30
|
+
* `tests/lib/config/dispatcher-autonomy-capture.test.mjs` — "treats a header
|
|
31
|
+
* inside a fenced code block as PRESENT". Both assert that a ```-fenced block IS
|
|
32
|
+
* parsed. Teaching this module about
|
|
33
|
+
* fences would flip ~36 parsers at once and break those pins, so it does not.
|
|
34
|
+
* Revisit only as its own change, with those two tests as the blast radius.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { htmlCommentSkipper } from './section-extractor.mjs';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Drop every line that lies inside — or opens — a multi-line `<!-- … -->` HTML
|
|
41
|
+
* comment (#1162a).
|
|
42
|
+
*
|
|
43
|
+
* Wraps `htmlCommentSkipper()` from `section-extractor.mjs` rather than
|
|
44
|
+
* re-deriving the state machine, so the block parsers and the Session Config
|
|
45
|
+
* KV extractor share ONE definition of "this line is commented-out
|
|
46
|
+
* documentation" by construction. A fresh closure is built per call: the skipper
|
|
47
|
+
* carries per-document state, and a shared instance would leak an unterminated
|
|
48
|
+
* comment from one document into the next.
|
|
49
|
+
*
|
|
50
|
+
* Inherits the skipper's deliberate ceiling: the opener must be at the START of
|
|
51
|
+
* a line (`/^\s*<!--/`), so `waves: 5 <!-- note` does NOT swallow the following
|
|
52
|
+
* lines — the trailing single-line comment form this repo's own convention
|
|
53
|
+
* encourages keeps working.
|
|
54
|
+
*
|
|
55
|
+
* Never touches `- ` list markers, indentation, or line content.
|
|
56
|
+
*
|
|
57
|
+
* FAIL-CLOSED on an UNTERMINATED comment. A stray `<!--` with no `-->` after it
|
|
58
|
+
* puts the skipper in the swallowing state for the REST of the document, so
|
|
59
|
+
* every later block silently disappears and each parser falls back to its
|
|
60
|
+
* defaults — for `config-protection` that is `strict` → `warn`, i.e. a guard
|
|
61
|
+
* disarmed by a typo, with no error anywhere. When the skipper would still be
|
|
62
|
+
* inside a comment at EOF, this returns the INPUT lines unfiltered (the
|
|
63
|
+
* pre-#1162 behaviour: the opener is treated as literal text), so nothing can
|
|
64
|
+
* vanish. The condition is reported via `onUnterminated` and is separately
|
|
65
|
+
* observable through {@link findUnterminatedComment}.
|
|
66
|
+
*
|
|
67
|
+
* @param {string[]} lines
|
|
68
|
+
* @param {(lineNo: number) => void} [onUnterminated] — called with the 1-based
|
|
69
|
+
* line number of the unterminated opener when stripping is disabled.
|
|
70
|
+
* @returns {string[]} a new array; the input is not mutated.
|
|
71
|
+
*/
|
|
72
|
+
export function stripHtmlCommentBlocks(lines, onUnterminated) {
|
|
73
|
+
if (!Array.isArray(lines)) return [];
|
|
74
|
+
const unterminatedAt = findUnterminatedComment(lines);
|
|
75
|
+
if (unterminatedAt !== null) {
|
|
76
|
+
if (typeof onUnterminated === 'function') onUnterminated(unterminatedAt);
|
|
77
|
+
return lines.slice();
|
|
78
|
+
}
|
|
79
|
+
const skip = htmlCommentSkipper();
|
|
80
|
+
return lines.filter((line) => !skip(typeof line === 'string' ? line : ''));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The 1-based line number of an `<!--` that is never closed, or `null` when
|
|
85
|
+
* every comment in `lines` is terminated.
|
|
86
|
+
*
|
|
87
|
+
* Derived from the SAME `htmlCommentSkipper()` state machine rather than a
|
|
88
|
+
* second copy of it (the RAW-PARITY constraint): the skipper swallows the
|
|
89
|
+
* closing `-->` line too, so the document ends inside a comment exactly when
|
|
90
|
+
* the LAST swallowed line carries no `-->`. A swallowed line that follows a
|
|
91
|
+
* closing line (or the first one of all) is an opener, which is how the
|
|
92
|
+
* reported line number is obtained.
|
|
93
|
+
*
|
|
94
|
+
* @param {string[]} lines
|
|
95
|
+
* @returns {number|null}
|
|
96
|
+
*/
|
|
97
|
+
export function findUnterminatedComment(lines) {
|
|
98
|
+
if (!Array.isArray(lines)) return null;
|
|
99
|
+
const skip = htmlCommentSkipper();
|
|
100
|
+
let openerLine = null;
|
|
101
|
+
/** @type {string|null} */
|
|
102
|
+
let lastSwallowed = null;
|
|
103
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
104
|
+
const line = typeof lines[i] === 'string' ? lines[i] : '';
|
|
105
|
+
if (!skip(line)) continue;
|
|
106
|
+
if (lastSwallowed === null || lastSwallowed.includes('-->')) openerLine = i + 1;
|
|
107
|
+
lastSwallowed = line;
|
|
108
|
+
}
|
|
109
|
+
if (lastSwallowed === null || lastSwallowed.includes('-->')) return null;
|
|
110
|
+
return openerLine;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* `- **key:** value` / `- **key**: value` / `**key:** value` → `key: value`,
|
|
115
|
+
* preserving the leading indentation EXACTLY (#1162b).
|
|
116
|
+
*
|
|
117
|
+
* The indent is load-bearing: every block parser ends its block at the first
|
|
118
|
+
* non-empty non-indented line, so an indent-eating rewrite would truncate the
|
|
119
|
+
* block one line early. Only the `**` markers and the optional `- ` bullet
|
|
120
|
+
* immediately around the `key:` token at line start are removed; the value
|
|
121
|
+
* portion (including any literal `**` inside it) is untouched — same rule as the
|
|
122
|
+
* `_matchKVLine` Format-1 branch and the #823 header tolerance.
|
|
123
|
+
*
|
|
124
|
+
* A line that is not a bold key/value pair is returned byte-identical.
|
|
125
|
+
*
|
|
126
|
+
* @internal — exported for this module's own tests. Production callers use
|
|
127
|
+
* {@link preprocessBlockLines} / {@link preprocessBlockLinesNoDash}.
|
|
128
|
+
*
|
|
129
|
+
* NAMED RISK — dash-record blocks. In any block whose body uses `- ` as a RECORD
|
|
130
|
+
* boundary, de-dashing the first key of a record merges it into the PREVIOUS
|
|
131
|
+
* record, silently producing one record where two were written. Those parsers
|
|
132
|
+
* must use
|
|
133
|
+
* `preprocessBlockLinesNoDash` instead. `tests/lib/config/block-preprocess.test.mjs`
|
|
134
|
+
* demonstrates the merge so the next reader sees why the NoDash variant exists.
|
|
135
|
+
*
|
|
136
|
+
* @param {string[]} lines
|
|
137
|
+
* @returns {string[]} a new array; the input is not mutated.
|
|
138
|
+
*/
|
|
139
|
+
export function normalizeBoldSubkeys(lines) {
|
|
140
|
+
if (!Array.isArray(lines)) return [];
|
|
141
|
+
return lines.map((line) => {
|
|
142
|
+
if (typeof line !== 'string') return line;
|
|
143
|
+
// (1) indent (2) optional bullet (3) **key:** or **key**: (4) rest
|
|
144
|
+
const m = line.match(/^(\s*)(?:-\s+)?\*\*([^*:]+?)(?::\*\*|\*\*:)\s*(.*)$/);
|
|
145
|
+
if (!m) return line;
|
|
146
|
+
const value = m[3];
|
|
147
|
+
return value === '' ? `${m[1]}${m[2]}:` : `${m[1]}${m[2]}: ${value}`;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* THE drop-in replacement for `content.split(/\r?\n/)` in a flat or
|
|
153
|
+
* nested-OBJECT block parser: strip commented-out lines, then normalise bold
|
|
154
|
+
* sub-keys.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} content — full file contents
|
|
157
|
+
* @returns {string[]} preprocessed lines (empty array for non-string input)
|
|
158
|
+
*/
|
|
159
|
+
export function preprocessBlockLines(content) {
|
|
160
|
+
if (typeof content !== 'string') return [];
|
|
161
|
+
return normalizeBoldSubkeys(stripHtmlCommentBlocks(content.split(/\r?\n/)));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* THE drop-in for every dash-RECORD parser — any parser whose block body uses
|
|
166
|
+
* `- ` as a record boundary, so the dash must survive: HTML-comment stripping
|
|
167
|
+
* only, no bold-subkey normalisation. (Enumerating them here goes stale; the
|
|
168
|
+
* rule is the criterion. `grep -l preprocessBlockLinesNoDash scripts/lib/config/`
|
|
169
|
+
* lists the current set.)
|
|
170
|
+
*
|
|
171
|
+
* @param {string} content — full file contents
|
|
172
|
+
* @returns {string[]} preprocessed lines (empty array for non-string input)
|
|
173
|
+
*/
|
|
174
|
+
export function preprocessBlockLinesNoDash(content) {
|
|
175
|
+
if (typeof content !== 'string') return [];
|
|
176
|
+
return stripHtmlCommentBlocks(content.split(/\r?\n/));
|
|
177
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* broken-window.mjs — Parser for the top-level `broken-window-budget:` YAML block
|
|
@@ -48,7 +49,7 @@ export function _parseBrokenWindow(content) {
|
|
|
48
49
|
'due-days': 7,
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
const lines = String(content ?? '')
|
|
52
|
+
const lines = preprocessBlockLines(String(content ?? ''));
|
|
52
53
|
let inBlock = false;
|
|
53
54
|
const blockLines = [];
|
|
54
55
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* cold-start.mjs — Parser for the top-level `cold-start:` YAML block (PRD F1.3 /
|
|
@@ -30,7 +31,7 @@ export function _parseColdStart(content) {
|
|
|
30
31
|
'silence-after-sessions': 1,
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
const lines = content
|
|
34
|
+
const lines = preprocessBlockLines(content);
|
|
34
35
|
let inBlock = false;
|
|
35
36
|
const blockLines = [];
|
|
36
37
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { findUnterminatedComment, preprocessBlockLines, preprocessBlockLinesNoDash } from './block-preprocess.mjs';
|
|
2
3
|
import { isSessionConfigHeading } from './section-extractor.mjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -45,7 +46,7 @@ export function _parseConfigProtection(content) {
|
|
|
45
46
|
|
|
46
47
|
if (typeof content !== 'string' || content.length === 0) return defaults;
|
|
47
48
|
|
|
48
|
-
const lines = content
|
|
49
|
+
const lines = preprocessBlockLines(content);
|
|
49
50
|
let inBlock = false;
|
|
50
51
|
const blockLines = [];
|
|
51
52
|
|
|
@@ -107,7 +108,26 @@ export function _parseConfigProtection(content) {
|
|
|
107
108
|
export function _isConfigWeakeningAllowed(content) {
|
|
108
109
|
if (typeof content !== 'string' || content.length === 0) return false;
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
// HTML-comment stripping ONLY (`preprocessBlockLinesNoDash`), never the full
|
|
112
|
+
// `preprocessBlockLines`: bold-subkey normalisation would make
|
|
113
|
+
// `- **allow-config-weakening:** true` arm the bypass, and
|
|
114
|
+
// `tests/lib/config/config-protection.test.mjs` pins the opposite — only the
|
|
115
|
+
// plain form is the supported bypass. Fail-closed beats markdown tolerance there.
|
|
116
|
+
// The comment strip is the OTHER direction and is mandatory (W4/F1): with a raw
|
|
117
|
+
// `content.split(/\r?\n/)` a COMMENTED-OUT `<!--\nallow-config-weakening: true\n-->`
|
|
118
|
+
// inside `## Session Config` ARMED the bypass — commenting a key out is the most
|
|
119
|
+
// ordinary way to disable it and must never enable it (same class as #1162a).
|
|
120
|
+
//
|
|
121
|
+
// UNTERMINATED `<!--` — the fail-closed direction INVERTS for a bypass scan.
|
|
122
|
+
// `stripHtmlCommentBlocks` returns the lines UNFILTERED when a comment is never
|
|
123
|
+
// closed, which is right for a block PARSER (nothing may silently vanish) and
|
|
124
|
+
// wrong here: it hands the commented-out bypass line straight back and re-arms
|
|
125
|
+
// the guard's own off switch. For this scan "I cannot tell where the comments
|
|
126
|
+
// end" must mean NOT ARMED — the bypass is opt-in, so refusing to grant it is
|
|
127
|
+
// the safe reading in every ambiguous document.
|
|
128
|
+
if (findUnterminatedComment(content.split(/\r?\n/)) !== null) return false;
|
|
129
|
+
|
|
130
|
+
const lines = preprocessBlockLinesNoDash(content);
|
|
111
131
|
let inConfig = false;
|
|
112
132
|
for (const line of lines) {
|
|
113
133
|
if (isSessionConfigHeading(line)) { inConfig = true; continue; }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* context-coverage.mjs — Parser for the top-level `context-coverage:` YAML block.
|
|
@@ -37,7 +38,7 @@ import { matchBlockHeader } from './block-header.mjs';
|
|
|
37
38
|
export function _parseContextCoverage(content) {
|
|
38
39
|
const defaults = { enabled: false, mode: 'warn' };
|
|
39
40
|
|
|
40
|
-
const lines = content
|
|
41
|
+
const lines = preprocessBlockLines(content);
|
|
41
42
|
let inBlock = false;
|
|
42
43
|
const blockLines = [];
|
|
43
44
|
|
|
@@ -20,6 +20,7 @@ import { homedir } from 'node:os';
|
|
|
20
20
|
import { join } from 'node:path';
|
|
21
21
|
import { readConfigFile } from './io.mjs';
|
|
22
22
|
import { matchBlockHeader } from './block-header.mjs';
|
|
23
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Resolve the cross-repo confinement root. Defaults to ~/Projects.
|
|
@@ -47,7 +48,7 @@ const SAFE_PATH_RE = /^[A-Za-z0-9._~/-]+$/;
|
|
|
47
48
|
* @returns {string[]} list of project paths, or [] when absent/empty/none/null
|
|
48
49
|
*/
|
|
49
50
|
export function _parseCrossRepo(content) {
|
|
50
|
-
const lines = content
|
|
51
|
+
const lines = preprocessBlockLines(content);
|
|
51
52
|
let inBlock = false;
|
|
52
53
|
|
|
53
54
|
for (const rawLine of lines) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLinesNoDash } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* custom-phases.mjs — Parser for the `custom-phases:` Session Config block (#637).
|
|
@@ -65,7 +66,7 @@ const SAFE_PATH_RE = /^[A-Za-z0-9._~/-]+$/;
|
|
|
65
66
|
* @returns {Array<{name: string, when: string, command: string, mode: string, review: string|null}>}
|
|
66
67
|
*/
|
|
67
68
|
export function _parseCustomPhases(content) {
|
|
68
|
-
const lines = content
|
|
69
|
+
const lines = preprocessBlockLinesNoDash(content);
|
|
69
70
|
let inBlock = false;
|
|
70
71
|
const blockLines = [];
|
|
71
72
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* dialectic.mjs — Parser for top-level `dialectic:` YAML block (#506).
|
|
@@ -30,7 +31,7 @@ const ALLOWED_MODELS = new Set(['haiku', 'sonnet', 'opus']);
|
|
|
30
31
|
export function _parseDialectic(content) {
|
|
31
32
|
const defaults = { cadence: 5, model: 'haiku', 'budget-tokens': 8000 };
|
|
32
33
|
|
|
33
|
-
const lines = content
|
|
34
|
+
const lines = preprocessBlockLines(content);
|
|
34
35
|
let inBlock = false;
|
|
35
36
|
const blockLines = [];
|
|
36
37
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* discovery-validator.mjs — Parser for the top-level `discovery-validator:`
|
|
@@ -36,7 +37,7 @@ export function _parseDiscoveryValidator(content) {
|
|
|
36
37
|
enabled: false,
|
|
37
38
|
};
|
|
38
39
|
|
|
39
|
-
const lines = content
|
|
40
|
+
const lines = preprocessBlockLines(content);
|
|
40
41
|
let inBlock = false;
|
|
41
42
|
const blockLines = [];
|
|
42
43
|
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
40
40
|
|
|
41
41
|
import { hasBlockHeader } from './block-header.mjs';
|
|
42
|
+
import { preprocessBlockLinesNoDash } from './block-preprocess.mjs';
|
|
42
43
|
|
|
43
44
|
const ALLOWED_AUTONOMY = ['off', 'advisory', 'autonomous-gated'];
|
|
44
45
|
const DEFAULT_CONFIDENCE_FLOOR = 0.5;
|
|
@@ -113,6 +114,18 @@ export function getDispatcherAutonomyQuestion() {
|
|
|
113
114
|
* the shared `matchBlockHeader()` matcher (block-header.mjs). `hasBlockHeader()`
|
|
114
115
|
* splits on `/\r?\n/` and tests each line, so `\r` and trailing whitespace are
|
|
115
116
|
* eaten by the `\s*$` tail and the identical set of inputs matches.
|
|
117
|
+
*
|
|
118
|
+
* PARSER PARITY, both halves (#1222): the parser preprocesses its content with
|
|
119
|
+
* `preprocessBlockLines()` — it STRIPS `<!-- … -->` HTML comments and is
|
|
120
|
+
* fence-BLIND. This guard therefore preprocesses too, with
|
|
121
|
+
* `preprocessBlockLinesNoDash()` (comment-strip only; the full
|
|
122
|
+
* `preprocessBlockLines` additionally de-dashes bold sub-keys, which this
|
|
123
|
+
* whole-file presence scan has no use for), and stays fence-blind as well. Before
|
|
124
|
+
* that, a block commented OUT (`<!--\ndispatcher-autonomy:\n autonomy: off\n-->`)
|
|
125
|
+
* parsed to DEFAULTS while being reported PRESENT — so the one-time capture AUQ
|
|
126
|
+
* never fired and the operator was never asked. The two halves must move
|
|
127
|
+
* together: teach one about comments or fences and the other follows in
|
|
128
|
+
* lock-step, or the guard and the parser disagree again.
|
|
116
129
|
* Verified-equivalent edge cases:
|
|
117
130
|
* - CRLF line endings (`dispatcher-autonomy:\r\n`) → PRESENT (`\s*$` eats the `\r`).
|
|
118
131
|
* - Trailing spaces / tabs on the header line → PRESENT (`\s*$`).
|
|
@@ -130,6 +143,15 @@ export function getDispatcherAutonomyQuestion() {
|
|
|
130
143
|
* - Header present but BODY malformed (garbage non-yaml lines) → PRESENT. A
|
|
131
144
|
* malformed block is the operator's to fix, never a re-prompt trigger — the
|
|
132
145
|
* parser tolerantly falls back to defaults, and capture must not re-ask.
|
|
146
|
+
* - Header inside a `<!-- … -->` comment → ABSENT (#1222), matching the parser.
|
|
147
|
+
* - Header inside a comment that is never closed (a stray `<!--` with no
|
|
148
|
+
* `-->`) → PRESENT. `stripHtmlCommentBlocks()` returns the lines UNFILTERED
|
|
149
|
+
* in that case, so nothing silently vanishes, and the parser — which uses the
|
|
150
|
+
* same helper — sees the header too. Unlike `_isConfigWeakeningAllowed()` in
|
|
151
|
+
* config-protection.mjs, this scan does NOT invert that direction: there the
|
|
152
|
+
* scanned line ARMS a bypass, so ambiguity must mean "not armed"; here the
|
|
153
|
+
* only cost of a stray PRESENT is one un-asked question, while diverging from
|
|
154
|
+
* the parser would re-open exactly the bug this fix closes.
|
|
133
155
|
*
|
|
134
156
|
* No-throw: null / non-string / empty → false.
|
|
135
157
|
*
|
|
@@ -138,7 +160,8 @@ export function getDispatcherAutonomyQuestion() {
|
|
|
138
160
|
*/
|
|
139
161
|
export function isDispatcherAutonomyBlockPresent(claudeMdContent) {
|
|
140
162
|
if (typeof claudeMdContent !== 'string' || claudeMdContent.length === 0) return false;
|
|
141
|
-
|
|
163
|
+
const preprocessed = preprocessBlockLinesNoDash(claudeMdContent).join('\n');
|
|
164
|
+
return hasBlockHeader(preprocessed, 'dispatcher-autonomy');
|
|
142
165
|
}
|
|
143
166
|
|
|
144
167
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* dispatcher-autonomy.mjs — Parser + resolver for the top-level
|
|
@@ -40,7 +41,7 @@ export function _parseDispatcherAutonomy(content) {
|
|
|
40
41
|
'confidence-floor': 0.5,
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
const lines = content
|
|
44
|
+
const lines = preprocessBlockLines(content);
|
|
44
45
|
let inBlock = false;
|
|
45
46
|
const blockLines = [];
|
|
46
47
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* docs-orchestrator.mjs — Parser for the top-level `docs-orchestrator:` YAML block.
|
|
@@ -13,7 +14,7 @@ import { matchBlockHeader } from './block-header.mjs';
|
|
|
13
14
|
export function _parseDocsOrchestrator(content) {
|
|
14
15
|
const defaults = { enabled: false, audiences: ['user', 'dev', 'vault'], mode: 'warn' };
|
|
15
16
|
|
|
16
|
-
const lines = content
|
|
17
|
+
const lines = preprocessBlockLines(content);
|
|
17
18
|
let inBlock = false;
|
|
18
19
|
const blockLines = [];
|
|
19
20
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* docs-staleness.mjs — Parser for the top-level `docs-staleness:` YAML block.
|
|
@@ -29,7 +30,7 @@ export function _parseDocsStaleness(content) {
|
|
|
29
30
|
mode: 'warn',
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
const lines = content
|
|
33
|
+
const lines = preprocessBlockLines(content);
|
|
33
34
|
let inBlock = false;
|
|
34
35
|
const blockLines = [];
|
|
35
36
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* drift-check.mjs — Parser for the top-level `drift-check:` YAML block.
|
|
@@ -39,7 +40,7 @@ export function _parseDriftCheck(content) {
|
|
|
39
40
|
'check-docs-parity': true,
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
const lines = content
|
|
43
|
+
const lines = preprocessBlockLines(content);
|
|
43
44
|
let inBlock = false;
|
|
44
45
|
const blockLines = [];
|
|
45
46
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* eval.mjs — Parser for the top-level `eval:` YAML block (#809, Epic #803).
|
|
@@ -51,7 +52,7 @@ const ALLOWED_REPORT = new Set(['html', 'none']);
|
|
|
51
52
|
export function _parseEval(content) {
|
|
52
53
|
const defaults = { enabled: false, mode: 'warn', judge: 'off', report: 'html', handle: null };
|
|
53
54
|
|
|
54
|
-
const lines = content
|
|
55
|
+
const lines = preprocessBlockLines(content);
|
|
55
56
|
let inBlock = false;
|
|
56
57
|
const blockLines = [];
|
|
57
58
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* events-rotation.mjs — Parser for the top-level `events-rotation:` YAML block.
|
|
@@ -17,7 +18,7 @@ import { matchBlockHeader } from './block-header.mjs';
|
|
|
17
18
|
export function _parseEventsRotation(content) {
|
|
18
19
|
const defaults = { enabled: true, 'max-size-mb': 10, 'max-backups': 5 };
|
|
19
20
|
|
|
20
|
-
const lines = content
|
|
21
|
+
const lines = preprocessBlockLines(content);
|
|
21
22
|
let inBlock = false;
|
|
22
23
|
const blockLines = [];
|
|
23
24
|
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
import pathModule from 'node:path';
|
|
36
36
|
|
|
37
37
|
import { matchBlockHeader } from './block-header.mjs';
|
|
38
|
+
import { preprocessBlockLines, preprocessBlockLinesNoDash } from './block-preprocess.mjs';
|
|
38
39
|
|
|
39
40
|
/** Per-entry defaults (none beyond the required field-set; documented for symmetry). */
|
|
40
41
|
export const EVOLVE_EXTRA_SOURCE_DEFAULTS = Object.freeze({
|
|
@@ -67,7 +68,9 @@ const SAFE_PATH_RE = /^[A-Za-z0-9._~/-]+$/;
|
|
|
67
68
|
* @returns {Array<{path: string, kind: string, 'learning-type': string}>}
|
|
68
69
|
*/
|
|
69
70
|
export function _parseEvolve(content) {
|
|
70
|
-
|
|
71
|
+
// NoDash: `- ` is the RECORD boundary under `extra-sources:` — de-dashing the
|
|
72
|
+
// first key of a record would merge it into the previous one (#1162).
|
|
73
|
+
const lines = preprocessBlockLinesNoDash(content);
|
|
71
74
|
let inEvolve = false;
|
|
72
75
|
let inExtraSources = false;
|
|
73
76
|
const blockLines = [];
|
|
@@ -254,7 +257,10 @@ export function _parseEvolveDecay(content) {
|
|
|
254
257
|
'floor-factor': EVOLVE_DECAY_DEFAULTS['floor-factor'],
|
|
255
258
|
};
|
|
256
259
|
|
|
257
|
-
|
|
260
|
+
// Standard variant: this parser reads only FLAT `decay-*` sub-keys and builds
|
|
261
|
+
// no records, so bold-subkey normalisation is safe here even though the same
|
|
262
|
+
// `evolve:` block also carries the `extra-sources:` dash records (#1162).
|
|
263
|
+
const lines = preprocessBlockLines(content);
|
|
258
264
|
let inEvolve = false;
|
|
259
265
|
const blockLines = [];
|
|
260
266
|
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
import { promises as fs } from 'node:fs';
|
|
19
19
|
import path from 'node:path';
|
|
20
20
|
|
|
21
|
-
import {
|
|
21
|
+
import { getProjectDir } from '../platform.mjs';
|
|
22
22
|
import { matchBlockHeader } from './block-header.mjs';
|
|
23
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Parse the top-level `frontend-slop-hook:` YAML block from markdown content.
|
|
@@ -35,7 +36,7 @@ import { matchBlockHeader } from './block-header.mjs';
|
|
|
35
36
|
export function _parseFrontendSlopHook(content) {
|
|
36
37
|
const defaults = { enabled: false };
|
|
37
38
|
|
|
38
|
-
const lines = content
|
|
39
|
+
const lines = preprocessBlockLines(content);
|
|
39
40
|
let inBlock = false;
|
|
40
41
|
const blockLines = [];
|
|
41
42
|
|
|
@@ -86,7 +87,10 @@ export function _parseFrontendSlopHook(content) {
|
|
|
86
87
|
* @returns {Promise<{ enabled: boolean }>}
|
|
87
88
|
*/
|
|
88
89
|
export async function loadFrontendSlopHookConfig(opts = {}) {
|
|
89
|
-
|
|
90
|
+
// Called at USE time, never at module load: the deprecated `SO_PROJECT_DIR`
|
|
91
|
+
// named export is a live binding that stays `undefined` until some getter has
|
|
92
|
+
// run in the process, so a bare call resolved the root to undefined (#1153 P5).
|
|
93
|
+
const root = opts.repoRoot || getProjectDir();
|
|
90
94
|
const candidates = [
|
|
91
95
|
path.join(root, 'CLAUDE.md'),
|
|
92
96
|
path.join(root, 'AGENTS.md'),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* gitlab-portfolio.mjs — Parser for the top-level `gitlab-portfolio:` YAML block.
|
|
@@ -66,7 +67,7 @@ export function coerceGitlabPortfolio(raw) {
|
|
|
66
67
|
* @returns {{ enabled: boolean, mode: 'warn'|'strict'|'off', 'stale-days': number, 'critical-labels': string[] }}
|
|
67
68
|
*/
|
|
68
69
|
export function _parseGitlabPortfolio(content) {
|
|
69
|
-
const lines = content
|
|
70
|
+
const lines = preprocessBlockLines(content);
|
|
70
71
|
let inBlock = false;
|
|
71
72
|
const blockLines = [];
|
|
72
73
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* handover-gate.mjs — Parser for the top-level `handover-gate:` YAML block
|
|
@@ -43,7 +44,7 @@ export function _parseHandoverGate(content) {
|
|
|
43
44
|
'max-open-questions': 3,
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
const lines = content
|
|
47
|
+
const lines = preprocessBlockLines(content);
|
|
47
48
|
let inBlock = false;
|
|
48
49
|
const blockLines = [];
|
|
49
50
|
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
65
|
import { matchBlockHeader, matchBlockHeaderDetailed } from './block-header.mjs';
|
|
66
|
+
import { preprocessBlockLines, preprocessBlockLinesNoDash } from './block-preprocess.mjs';
|
|
66
67
|
import { _coerceBoolean } from './coercers.mjs';
|
|
67
68
|
|
|
68
69
|
/**
|
|
@@ -315,7 +316,9 @@ function assignKV(entry, text) {
|
|
|
315
316
|
export function _parseHealthEndpoints(content) {
|
|
316
317
|
if (typeof content !== 'string' || content === '') return null;
|
|
317
318
|
|
|
318
|
-
|
|
319
|
+
// NoDash: `- name:` / `- url:` / `- {name, url}` list items are RECORD
|
|
320
|
+
// boundaries here — de-dashing would merge two endpoints into one (#1162).
|
|
321
|
+
const lines = preprocessBlockLinesNoDash(content);
|
|
319
322
|
for (let i = 0; i < lines.length; i++) {
|
|
320
323
|
const line = lines[i].replace(/\r$/, '');
|
|
321
324
|
const m = matchBlockHeaderDetailed(line, 'health-endpoints');
|
|
@@ -353,7 +356,9 @@ export function _parseHealthEndpoints(content) {
|
|
|
353
356
|
export function _parseEcosystemHealthBlockEnabled(content) {
|
|
354
357
|
if (typeof content !== 'string' || content === '') return null;
|
|
355
358
|
|
|
356
|
-
|
|
359
|
+
// Standard variant: this parser reads only the flat `enabled:` sub-key and
|
|
360
|
+
// builds no records (#1162).
|
|
361
|
+
const lines = preprocessBlockLines(content);
|
|
357
362
|
let inBlock = false;
|
|
358
363
|
const blockLines = [];
|
|
359
364
|
for (const rawLine of lines) {
|
|
@@ -40,17 +40,33 @@ const ENV_KEYS = /** @type {const} */ ({
|
|
|
40
40
|
* merged with defaults, so a real owner.yaml without a `paths:` section yields
|
|
41
41
|
* `ownerConfig.paths === undefined`. Callers must read defensively.
|
|
42
42
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
43
|
+
* HEALTH PASSTHROUGH (#1251): the owner loader reports HOW its result came about
|
|
44
|
+
* (`source`, `reason`, `droppedSections`). Discarding those forced callers that
|
|
45
|
+
* need them — CP11 in check-owner-leakage.mjs is the live one — to load owner.yaml
|
|
46
|
+
* a SECOND time just to see the health of the load this function already did. They
|
|
47
|
+
* are passed through verbatim; `ownerConfig` and `env` keep their exact prior
|
|
48
|
+
* meaning, so callers reading only those two (scripts/lib/config.mjs,
|
|
49
|
+
* scripts/lib/vault-mirror/namespace.mjs) are unaffected. On a throwing loader all
|
|
50
|
+
* three health fields stay `undefined`, exactly like `ownerConfig`.
|
|
51
|
+
*
|
|
52
|
+
* @param {{ env?: Record<string, string|undefined>, ownerLoader?: () => { config: object, source?: string, reason?: string, droppedSections?: Array<{section: string, errors: string[]}> } }} [opts]
|
|
53
|
+
* @returns {{ ownerConfig: object|undefined, env: Record<string, string|undefined>, source: string|undefined, reason: string|undefined, droppedSections: Array<{section: string, errors: string[]}>|undefined }}
|
|
45
54
|
*/
|
|
46
55
|
export function loadHostPaths({ env = process.env, ownerLoader = loadOwnerConfig } = {}) {
|
|
47
56
|
let ownerConfig;
|
|
57
|
+
let source;
|
|
58
|
+
let reason;
|
|
59
|
+
let droppedSections;
|
|
48
60
|
try {
|
|
49
|
-
|
|
61
|
+
const loaded = ownerLoader();
|
|
62
|
+
ownerConfig = loaded?.config;
|
|
63
|
+
source = loaded?.source;
|
|
64
|
+
reason = loaded?.reason;
|
|
65
|
+
droppedSections = loaded?.droppedSections;
|
|
50
66
|
} catch {
|
|
51
67
|
ownerConfig = undefined;
|
|
52
68
|
}
|
|
53
|
-
return { ownerConfig, env };
|
|
69
|
+
return { ownerConfig, env, source, reason, droppedSections };
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchBlockHeader } from './block-header.mjs';
|
|
2
|
+
import { preprocessBlockLines } from './block-preprocess.mjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* issue-budget.mjs — Parser for the `issue-budget:` block-style Session Config key.
|
|
@@ -65,7 +66,7 @@ export function _parseIssueBudget(content) {
|
|
|
65
66
|
|
|
66
67
|
if (typeof content !== 'string' || content === '') return { ...defaults };
|
|
67
68
|
|
|
68
|
-
const lines = content
|
|
69
|
+
const lines = preprocessBlockLines(content);
|
|
69
70
|
let inBlock = false;
|
|
70
71
|
const blockLines = [];
|
|
71
72
|
|