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,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* pre-bash-memory-propose-audit.mjs — PreToolUse Bash hook
|
|
4
|
+
*
|
|
5
|
+
* Logs memory.propose() CLI invocations to .orchestrator/metrics/events.jsonl
|
|
6
|
+
* for auditability. Observe-only — never blocks the Bash call.
|
|
7
|
+
*
|
|
8
|
+
* Part of issue #501. Node 20+, ESM, no external deps beyond project libs.
|
|
9
|
+
*
|
|
10
|
+
* Decision flow (G1-G7 early-return ladder):
|
|
11
|
+
* G1 — Bash tool only (other tools → exit 0)
|
|
12
|
+
* G2 — non-empty command string (else → exit 0)
|
|
13
|
+
* G3 — regex match /\bnode\b.*\bmemory-propose\.mjs\b/i (no match → exit 0)
|
|
14
|
+
* G4 — resolve session_id (from stdin payload or .orchestrator/current-session.json)
|
|
15
|
+
* G5 — resolve wave (from the active wave-scope.json `wave` field, default 0)
|
|
16
|
+
* G6 — redact argv: strip --insight/--subject/--evidence/--content/--reason values
|
|
17
|
+
* G7 — append event JSON line to .orchestrator/metrics/events.jsonl
|
|
18
|
+
* Always: exit 0 (never block)
|
|
19
|
+
*
|
|
20
|
+
* Exit codes:
|
|
21
|
+
* 0 — always (audit hook is observe-only, never denies)
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { readStdin, emitAllow } from '../scripts/lib/io.mjs';
|
|
25
|
+
import { existsSync } from 'node:fs';
|
|
26
|
+
import { readFile } from 'node:fs/promises';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { emitEvent } from '../scripts/lib/events.mjs';
|
|
29
|
+
import { findScopeFile } from '../scripts/lib/hardening.mjs';
|
|
30
|
+
|
|
31
|
+
import { shouldRunHook } from './_lib/profile-gate.mjs';
|
|
32
|
+
// exit 0 immediately when this hook is disabled via profile/env
|
|
33
|
+
if (!shouldRunHook('pre-bash-memory-propose-audit')) process.exit(0);
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Constants
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Matches `node ... memory-propose.mjs ...` invocations in any form:
|
|
41
|
+
* node scripts/memory-propose.mjs ...
|
|
42
|
+
* node "$PLUGIN_ROOT/scripts/memory-propose.mjs" ...
|
|
43
|
+
* /usr/bin/node ./scripts/memory-propose.mjs ...
|
|
44
|
+
* Does NOT match:
|
|
45
|
+
* echo "memory-propose.mjs"
|
|
46
|
+
* cat scripts/memory-propose.mjs
|
|
47
|
+
*/
|
|
48
|
+
const MEMORY_PROPOSE_REGEX = /\bnode\b.*\bmemory-propose\.mjs\b/i;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Flags whose VALUES are privacy-sensitive and must be redacted from the log.
|
|
52
|
+
* The flag name itself is preserved; only the value is replaced with [REDACTED].
|
|
53
|
+
*
|
|
54
|
+
* Matches both forms:
|
|
55
|
+
* --insight=value → --insight=[REDACTED]
|
|
56
|
+
* --insight "quoted value" → --insight [REDACTED]
|
|
57
|
+
* --insight unquoted → --insight [REDACTED]
|
|
58
|
+
*/
|
|
59
|
+
// CAVEAT (#554 A3, low severity): The regex operates on the unparsed Bash
|
|
60
|
+
// tool_input.command string. Exotic shell forms bypass redaction by hiding
|
|
61
|
+
// the value behind shell expansion the regex cannot see:
|
|
62
|
+
// --insight=$VAR (env-var indirection)
|
|
63
|
+
// --insight=$(cat secret) (command substitution)
|
|
64
|
+
// --insight <<<heredoc (here-string)
|
|
65
|
+
// The literal token (e.g. `$VAR`) is logged, NOT the resolved value — so an
|
|
66
|
+
// audit-trail leak requires the resolved value to also appear literally
|
|
67
|
+
// elsewhere in the command. Acceptable per the project's local-trust model.
|
|
68
|
+
//
|
|
69
|
+
// Issue #546: `\S+` would match an opening quote `"` or `'` (non-whitespace),
|
|
70
|
+
// and on malformed inputs (e.g. unbalanced or shell-already-unescaped values)
|
|
71
|
+
// could partial-match the value, leaving the tail unredacted. The negative
|
|
72
|
+
// lookahead `(?!["'])` forces `\S+` to be tried only on values that do not
|
|
73
|
+
// start with a quote, preserving the quoted-alt as the sole path for quoted
|
|
74
|
+
// values and preventing tail-leaks on malformed inputs.
|
|
75
|
+
const SENSITIVE_FLAGS_REGEX = /--(?:insight|subject|evidence|content|reason)(?:=("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|(?!["'])\S+)|\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|(?!["'])\S+))/g;
|
|
76
|
+
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Helpers
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Redact values of privacy-sensitive flags from a command string.
|
|
83
|
+
* Preserves flag names; replaces values with [REDACTED].
|
|
84
|
+
*
|
|
85
|
+
* @param {string} command
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
function redactArgv(command) {
|
|
89
|
+
return command.replace(SENSITIVE_FLAGS_REGEX, (match, eqValue, spaceValue) => {
|
|
90
|
+
if (eqValue !== undefined) {
|
|
91
|
+
// --insight=value form: preserve up to and including '=', replace value
|
|
92
|
+
const eqIndex = match.indexOf('=');
|
|
93
|
+
return match.slice(0, eqIndex + 1) + '[REDACTED]';
|
|
94
|
+
}
|
|
95
|
+
if (spaceValue !== undefined) {
|
|
96
|
+
// --insight value form: preserve flag + whitespace, replace value
|
|
97
|
+
const valueIndex = match.lastIndexOf(spaceValue);
|
|
98
|
+
return match.slice(0, valueIndex) + '[REDACTED]';
|
|
99
|
+
}
|
|
100
|
+
// Fallback: keep flag name, drop value
|
|
101
|
+
const flagMatch = match.match(/^(--[\w-]+)/);
|
|
102
|
+
return flagMatch ? flagMatch[1] + ' [REDACTED]' : match;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve the session_id from the hook stdin payload, with fallback to the
|
|
108
|
+
* persisted file written by on-session-start.mjs. Returns null when neither
|
|
109
|
+
* source yields a string.
|
|
110
|
+
*
|
|
111
|
+
* @param {object|null} input
|
|
112
|
+
* @param {string} projectDir
|
|
113
|
+
* @returns {Promise<string|null>}
|
|
114
|
+
*/
|
|
115
|
+
async function resolveSessionId(input, projectDir) {
|
|
116
|
+
const fromStdin = input?.session_id ?? input?.sessionId ?? null;
|
|
117
|
+
if (typeof fromStdin === 'string' && fromStdin.length > 0) return fromStdin;
|
|
118
|
+
|
|
119
|
+
const persisted = path.join(projectDir, '.orchestrator', 'current-session.json');
|
|
120
|
+
if (!existsSync(persisted)) return null;
|
|
121
|
+
try {
|
|
122
|
+
const raw = await readFile(persisted, 'utf8');
|
|
123
|
+
const data = JSON.parse(raw);
|
|
124
|
+
if (data && typeof data === 'object') {
|
|
125
|
+
const sid = data.session_id ?? data.sessionId ?? null;
|
|
126
|
+
if (typeof sid === 'string' && sid.length > 0) return sid;
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
// ignore — null below
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Resolve the current wave number from the active wave-scope.json.
|
|
136
|
+
* Returns 0 when the file is absent or unparseable.
|
|
137
|
+
*
|
|
138
|
+
* @param {string} projectDir
|
|
139
|
+
* @returns {Promise<number>}
|
|
140
|
+
*/
|
|
141
|
+
async function resolveWave(projectDir) {
|
|
142
|
+
const waveFile = findScopeFile(projectDir);
|
|
143
|
+
if (!waveFile || !existsSync(waveFile)) return 0;
|
|
144
|
+
try {
|
|
145
|
+
const raw = await readFile(waveFile, 'utf8');
|
|
146
|
+
const data = JSON.parse(raw);
|
|
147
|
+
const wave = data?.wave;
|
|
148
|
+
return typeof wave === 'number' ? wave : 0;
|
|
149
|
+
} catch {
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// Main
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
async function main() {
|
|
159
|
+
const input = await readStdin();
|
|
160
|
+
if (!input) return emitAllow();
|
|
161
|
+
|
|
162
|
+
// G1 — only Bash tool is audited
|
|
163
|
+
if (input.tool_name !== 'Bash') return emitAllow();
|
|
164
|
+
|
|
165
|
+
// G2 — command must be a non-empty string
|
|
166
|
+
const command = input?.tool_input?.command;
|
|
167
|
+
if (typeof command !== 'string' || command.length === 0) return emitAllow();
|
|
168
|
+
|
|
169
|
+
// G3 — regex gate: only memory-propose.mjs invocations via node
|
|
170
|
+
if (!MEMORY_PROPOSE_REGEX.test(command)) return emitAllow();
|
|
171
|
+
|
|
172
|
+
// Matched — proceed with audit logging (G4-G7)
|
|
173
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR
|
|
174
|
+
?? process.env.CODEX_PROJECT_DIR
|
|
175
|
+
?? process.cwd();
|
|
176
|
+
|
|
177
|
+
// G4 — resolve session_id
|
|
178
|
+
const sessionId = await resolveSessionId(input, projectDir);
|
|
179
|
+
|
|
180
|
+
// G5 — resolve wave
|
|
181
|
+
const wave = await resolveWave(projectDir);
|
|
182
|
+
|
|
183
|
+
// G6 — redact argv: strip sensitive flag values, keep flag names
|
|
184
|
+
const argvRedacted = redactArgv(command);
|
|
185
|
+
|
|
186
|
+
// G7 — emit canonical event via emitEvent (single emission path: schema + webhook,
|
|
187
|
+
// replacing the local hand-rolled appendFileSync bypass).
|
|
188
|
+
await emitEvent('orchestrator.memory.propose_invoked', {
|
|
189
|
+
session_id: sessionId,
|
|
190
|
+
wave,
|
|
191
|
+
argv_truncated: argvRedacted.slice(0, 512),
|
|
192
|
+
cwd: process.cwd(),
|
|
193
|
+
exit_code: null,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Always allow — this is an observe-only audit hook
|
|
197
|
+
return emitAllow();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Top-level error handler — never let exit 1 leak
|
|
201
|
+
main().catch((e) => {
|
|
202
|
+
process.stderr.write(
|
|
203
|
+
`⚠ pre-bash-memory-propose-audit: internal error — ${e?.message || e}\n`,
|
|
204
|
+
);
|
|
205
|
+
process.exit(0); // fail-open on internal errors
|
|
206
|
+
});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* pre-bash-staging-fence.mjs — PreToolUse Bash hook
|
|
4
|
+
*
|
|
5
|
+
* PSA-004 sub-mode C — staging-fence intent log for cross-agent `git add` race
|
|
6
|
+
* detection (issue #552). Companion to hooks/wave-scope-commit-guard.mjs
|
|
7
|
+
* (sub-mode B). Together the two guards cover:
|
|
8
|
+
*
|
|
9
|
+
* sub-mode B — lint-staged sweep that re-stages files outside wave-scope
|
|
10
|
+
* (the existing guard, caught at pre-commit time).
|
|
11
|
+
* sub-mode C — concurrent `git add` from two wave-agents on the same repo
|
|
12
|
+
* (this hook records intent; the commit-guard reconciles at
|
|
13
|
+
* commit time).
|
|
14
|
+
*
|
|
15
|
+
* Fence file
|
|
16
|
+
* ----------
|
|
17
|
+
* Path: .orchestrator/staging-fence/<agent-id>.json
|
|
18
|
+
* Shape:
|
|
19
|
+
* {
|
|
20
|
+
* "agent_id": "string", // ${SO_WAVE_AGENT}-${pid}-${rnd}
|
|
21
|
+
* "pid": 12345,
|
|
22
|
+
* "host": "string",
|
|
23
|
+
* "started_at": "2026-05-23T21:30:00.000Z",
|
|
24
|
+
* "staged_paths": [
|
|
25
|
+
* { "command": "git add src/foo.ts", "timestamp": "2026-…" },
|
|
26
|
+
* ...
|
|
27
|
+
* ]
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* The hook does NOT parse the `git add` argv into paths — argv parsing is
|
|
31
|
+
* fragile (globs, pathspec magic, `-A`, `-u`, `--`). Instead it records the
|
|
32
|
+
* raw command string; the commit-guard reconciles staged paths via
|
|
33
|
+
* `git diff --cached --name-only` and cross-checks them against ALL sibling
|
|
34
|
+
* fence files at commit time (where the staged set is unambiguous).
|
|
35
|
+
*
|
|
36
|
+
* Decision flow (G1-G6 early-return ladder):
|
|
37
|
+
* G1 tool filter — Bash only
|
|
38
|
+
* G2 command must be a non-empty string
|
|
39
|
+
* G3 regex match /\bgit\s+add\b/ — only `git add` invocations
|
|
40
|
+
* G4 context gate — isWaveAgentContext(); exit 0 immediately for
|
|
41
|
+
* coordinator/manual commits (AC5 safe-default no-op)
|
|
42
|
+
* G5 derive agent_id, build fence dir + path
|
|
43
|
+
* G6 read-modify-write the fence file (append the staging-intent entry).
|
|
44
|
+
* Errors are warned + swallowed — the hook NEVER blocks the Bash call.
|
|
45
|
+
*
|
|
46
|
+
* Bypass / disable
|
|
47
|
+
* ----------------
|
|
48
|
+
* - SO_DISABLED_HOOKS=pre-bash-staging-fence → exits 0 immediately
|
|
49
|
+
* - SO_HOOK_PROFILE=minimal|off → exits 0 immediately
|
|
50
|
+
* - Coordinator-thread invocations → exits 0 immediately (G4)
|
|
51
|
+
* - `git commit --no-verify` → bypasses the commit-guard
|
|
52
|
+
* entirely; sub-mode C reconciliation never runs (PSA-001/PSA-003 risk
|
|
53
|
+
* remains; the operator is opting out by name).
|
|
54
|
+
*
|
|
55
|
+
* Fail-safe posture: never blocks the Bash call, even on internal errors.
|
|
56
|
+
* Worst case is a missed enforcement, not a wedged session.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
import { readStdin, emitAllow, writeJsonAtomicSync } from '../scripts/lib/io.mjs';
|
|
60
|
+
import { isWaveAgentContext } from '../scripts/lib/wave-context.mjs';
|
|
61
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
62
|
+
import path from 'node:path';
|
|
63
|
+
import os from 'node:os';
|
|
64
|
+
import crypto from 'node:crypto';
|
|
65
|
+
|
|
66
|
+
import { shouldRunHook } from './_lib/profile-gate.mjs';
|
|
67
|
+
if (!shouldRunHook('pre-bash-staging-fence')) process.exit(0);
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Constants
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Matches `git add ...` invocations with word boundaries on both sides so
|
|
75
|
+
* `gitadd` and `git addremote` (hypothetical) do not match. Anchored to the
|
|
76
|
+
* `git` token, so `echo "git add"` is not matched (echo ≠ verb position).
|
|
77
|
+
*
|
|
78
|
+
* We deliberately accept `git add` anywhere in the command string — operators
|
|
79
|
+
* sometimes prefix env-vars (`GIT_COMMITTER_NAME=foo git add ...`) or chain
|
|
80
|
+
* commands (`cd repo && git add ...`). False positives are tolerable here
|
|
81
|
+
* (the hook only writes a log line, never blocks).
|
|
82
|
+
*/
|
|
83
|
+
const GIT_ADD_REGEX = /\bgit\s+add\b/;
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Helpers
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Derive a per-agent identifier for the fence filename.
|
|
91
|
+
*
|
|
92
|
+
* Composition: `${SO_WAVE_AGENT}-${pid}-${rnd6hex}`.
|
|
93
|
+
* - SO_WAVE_AGENT is always "1" inside a wave-agent context (per
|
|
94
|
+
* wave-context.mjs strict-equality contract), so the prefix is fixed.
|
|
95
|
+
* - PID disambiguates concurrent agents on the same host.
|
|
96
|
+
* - 6 hex chars (24 bits) defends against PID reuse within a long-running
|
|
97
|
+
* session, even though that race is vanishingly rare.
|
|
98
|
+
*
|
|
99
|
+
* The same PID may invoke `git add` repeatedly in one wave; the hook reads
|
|
100
|
+
* the existing fence file (matched by composing the same agent_id), appends,
|
|
101
|
+
* and rewrites. The random suffix is therefore frozen per process via
|
|
102
|
+
* lazy-init: the first call computes it; subsequent calls reuse it.
|
|
103
|
+
*
|
|
104
|
+
* NOTE: Because each hook subprocess is a fresh Node process, the random
|
|
105
|
+
* suffix is unique per `git add` invocation — there is no in-process cache
|
|
106
|
+
* to reuse. We accept N fence files per agent (one per `git add` call) and
|
|
107
|
+
* the commit-guard scans ALL fence files at commit time.
|
|
108
|
+
*
|
|
109
|
+
* @returns {string}
|
|
110
|
+
*/
|
|
111
|
+
function deriveAgentId() {
|
|
112
|
+
const waveAgent = process.env.SO_WAVE_AGENT ?? '1';
|
|
113
|
+
const pid = process.pid;
|
|
114
|
+
const rnd = crypto.randomBytes(3).toString('hex');
|
|
115
|
+
return `${waveAgent}-${pid}-${rnd}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Resolve the project directory the hook should operate against. Mirrors
|
|
120
|
+
* pre-bash-memory-propose-audit.mjs resolution: prefer CLAUDE_PROJECT_DIR /
|
|
121
|
+
* CODEX_PROJECT_DIR env-vars, fall back to cwd.
|
|
122
|
+
*
|
|
123
|
+
* @returns {string}
|
|
124
|
+
*/
|
|
125
|
+
function resolveProjectDir() {
|
|
126
|
+
return process.env.CLAUDE_PROJECT_DIR
|
|
127
|
+
?? process.env.CODEX_PROJECT_DIR
|
|
128
|
+
?? process.cwd();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Append a staging-intent entry to the fence file. Reads the existing file
|
|
133
|
+
* (if any), appends the entry, and rewrites atomically via the shared
|
|
134
|
+
* {@link writeJsonAtomicSync} helper from scripts/lib/io.mjs (extracted in
|
|
135
|
+
* #558 M1). The first call for a given agent_id creates the file with a
|
|
136
|
+
* fresh body.
|
|
137
|
+
*
|
|
138
|
+
* @param {{ fenceFile: string, agentId: string, command: string }} args
|
|
139
|
+
* @returns {{ ok: true } | { ok: false, reason: 'fs-error', error: string }}
|
|
140
|
+
*/
|
|
141
|
+
function appendIntent({ fenceFile, agentId, command }) {
|
|
142
|
+
const timestamp = new Date().toISOString();
|
|
143
|
+
|
|
144
|
+
let body;
|
|
145
|
+
if (existsSync(fenceFile)) {
|
|
146
|
+
try {
|
|
147
|
+
const raw = readFileSync(fenceFile, 'utf8');
|
|
148
|
+
const parsed = JSON.parse(raw);
|
|
149
|
+
if (parsed && typeof parsed === 'object' && Array.isArray(parsed.staged_paths)) {
|
|
150
|
+
body = parsed;
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
// Malformed existing fence file — overwrite with a fresh one.
|
|
154
|
+
body = undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!body) {
|
|
159
|
+
body = {
|
|
160
|
+
agent_id: agentId,
|
|
161
|
+
pid: process.pid,
|
|
162
|
+
host: os.hostname(),
|
|
163
|
+
started_at: timestamp,
|
|
164
|
+
staged_paths: [],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
body.staged_paths.push({ command: command.slice(0, 512), timestamp });
|
|
169
|
+
|
|
170
|
+
return writeJsonAtomicSync(fenceFile, body, { tmpPrefix: '.fence.tmp' });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Main
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
async function main() {
|
|
178
|
+
const input = await readStdin();
|
|
179
|
+
if (!input) return emitAllow();
|
|
180
|
+
|
|
181
|
+
// G1 — only Bash is gated.
|
|
182
|
+
if (input.tool_name !== 'Bash') return emitAllow();
|
|
183
|
+
|
|
184
|
+
// G2 — command must be a non-empty string.
|
|
185
|
+
const command = input?.tool_input?.command;
|
|
186
|
+
if (typeof command !== 'string' || command.length === 0) return emitAllow();
|
|
187
|
+
|
|
188
|
+
// G3 — regex gate. Non-`git add` commands pass through unconditionally.
|
|
189
|
+
if (!GIT_ADD_REGEX.test(command)) return emitAllow();
|
|
190
|
+
|
|
191
|
+
// G4 — context gate. Coordinator/manual commits are not fenced.
|
|
192
|
+
if (!isWaveAgentContext()) return emitAllow();
|
|
193
|
+
|
|
194
|
+
// G5 — derive paths.
|
|
195
|
+
const projectDir = resolveProjectDir();
|
|
196
|
+
const agentId = deriveAgentId();
|
|
197
|
+
const fenceFile = path.join(
|
|
198
|
+
projectDir,
|
|
199
|
+
'.orchestrator',
|
|
200
|
+
'staging-fence',
|
|
201
|
+
`${agentId}.json`,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// G6 — append intent. Never blocks the Bash call on failure.
|
|
205
|
+
const result = appendIntent({ fenceFile, agentId, command });
|
|
206
|
+
if (!result.ok) {
|
|
207
|
+
process.stderr.write(
|
|
208
|
+
`⚠ pre-bash-staging-fence: failed to write fence file — ${result.error}\n`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return emitAllow();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Top-level error handler — never let exit 1 leak. Fail-open on internal
|
|
216
|
+
// errors to avoid blocking legitimate work (mirrors the destructive-guard
|
|
217
|
+
// posture).
|
|
218
|
+
main().catch((e) => {
|
|
219
|
+
process.stderr.write(
|
|
220
|
+
`⚠ pre-bash-staging-fence: internal error — ${e?.message || e}\n`,
|
|
221
|
+
);
|
|
222
|
+
process.exit(0);
|
|
223
|
+
});
|