session-orchestrator 3.24.0 → 4.0.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/.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 +1 -1
- 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/.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 +1125 -2
- package/NOTICE +11 -6
- package/README.md +127 -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 +65 -21
- package/docs/components.md +36 -15
- package/docs/cursor-setup.md +6 -2
- package/docs/events-schema.md +9 -6
- package/docs/instruction-delivery.md +62 -0
- package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
- package/docs/migration-v4.md +341 -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 +1487 -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 +36 -11
- 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/plugin.json +27 -0
- 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-cursor-adapter.mjs +45 -8
- package/scripts/generate-hook-import-set.mjs +249 -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 +82 -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/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 +26 -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 +43 -6
- package/scripts/lib/owner-config-loader.mjs +21 -10
- package/scripts/lib/owner-interview.mjs +3 -3
- package/scripts/lib/owner-yaml.mjs +207 -14
- package/scripts/lib/platform.mjs +108 -15
- package/scripts/lib/plugin-update-banner.mjs +406 -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 +13 -4
- 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 +36 -2
- package/scripts/lib/session-schema/validator.mjs +38 -4
- package/scripts/lib/session-start-probes.mjs +18 -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 +181 -9
- package/scripts/lib/telemetry/sync.mjs +368 -12
- package/scripts/lib/validate/check-agents-skills.mjs +327 -0
- package/scripts/lib/validate/check-agents.mjs +3 -3
- 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 +281 -20
- package/scripts/lib/validate/check-skill-links.mjs +163 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +47 -28
- package/scripts/lib/validate/check-unwired-features.mjs +0 -2
- package/scripts/lib/validate/check-validator-registration.mjs +10 -4
- package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
- 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 +337 -29
- package/scripts/repair-invalid-sessions.mjs +3 -3
- package/scripts/run-quality-gate.mjs +128 -11
- 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 +161 -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 +155 -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/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
|
@@ -38,26 +38,148 @@
|
|
|
38
38
|
*
|
|
39
39
|
* ── Exports ───────────────────────────────────────────────────────────────────
|
|
40
40
|
*
|
|
41
|
-
*
|
|
41
|
+
* resolvePrivateConfigDir({env}?) — THE host-private config dir resolver (#1223)
|
|
42
|
+
* resolveOwnerYamlPath(env?) — owner.yaml path, resolved at CALL time (#1223)
|
|
42
43
|
* validateOwnerSections(obj) — pure validation, no I/O; bucketed per section (#820)
|
|
43
44
|
* validateOwnerConfig(obj) — pure validation, no I/O; thin wrapper over validateOwnerSections
|
|
44
45
|
* loadOwnerConfig({path?}) — reads file; per-section tolerance for OPTIONAL
|
|
45
46
|
* sections (paths/dispatcher/vaults/baselines) — #820
|
|
46
47
|
* writeOwnerConfig(config, {path?}) — validates, writes YAML, creates dir
|
|
47
48
|
* getDefaults() — returns sensible default config object
|
|
49
|
+
*
|
|
50
|
+
* ── Zero bare-specifier imports (GH#62/#63, GitLab #1230) ────────────────────
|
|
51
|
+
*
|
|
52
|
+
* `js-yaml` is resolved LAZILY inside {@link loadOwnerConfig} / {@link
|
|
53
|
+
* writeOwnerConfig} (see {@link getYaml}), never at module load. Importing this
|
|
54
|
+
* module therefore costs `node:fs` + `node:path` + `node:module` and nothing
|
|
55
|
+
* else, which is what keeps it safe on the hook import graph: before this
|
|
56
|
+
* change, `import yaml from 'js-yaml'` at the top of this file crashed FOUR
|
|
57
|
+
* hooks with `ERR_MODULE_NOT_FOUND` for anyone whose `node_modules` was absent
|
|
58
|
+
* (on-session-start, on-session-end, post-edit-validate,
|
|
59
|
+
* skill-invocation-telemetry — measured 2026-09-06 over a `hooks/` + `scripts/`
|
|
60
|
+
* copy with no `node_modules`, 4 of 27 hooks rc=1).
|
|
61
|
+
*
|
|
62
|
+
* When the package cannot be resolved both entry points DEGRADE rather than
|
|
63
|
+
* throw: they return their normal shape plus `reason: 'yaml-parser-missing'`
|
|
64
|
+
* (`source: 'defaults'` / `written: false`) and emit ONE rate-limited stderr
|
|
65
|
+
* WARN naming `npm install` as the fix.
|
|
48
66
|
*/
|
|
49
67
|
|
|
50
68
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
51
69
|
import { join, dirname } from 'node:path';
|
|
52
|
-
import {
|
|
53
|
-
import
|
|
70
|
+
import { createRequire } from 'node:module';
|
|
71
|
+
import { resolvePrivateConfigDir } from './config/private-config-dir.mjs';
|
|
54
72
|
|
|
55
73
|
// ---------------------------------------------------------------------------
|
|
56
74
|
// Constants
|
|
57
75
|
// ---------------------------------------------------------------------------
|
|
58
76
|
|
|
59
|
-
/**
|
|
60
|
-
|
|
77
|
+
/** Basename of the owner persona config file. */
|
|
78
|
+
const OWNER_YAML_FILE = 'owner.yaml';
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Lazy js-yaml resolution (GH#62/#63, GitLab #1230)
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Memoised `js-yaml` module, or `false` once resolution has failed.
|
|
86
|
+
* `null` = not yet attempted.
|
|
87
|
+
* @type {null | false | { load: Function, dump: Function }}
|
|
88
|
+
*/
|
|
89
|
+
let _yaml = null;
|
|
90
|
+
|
|
91
|
+
/** Guards the one-per-process stderr WARN below. */
|
|
92
|
+
let _yamlWarned = false;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Resolve `js-yaml` at CALL time instead of at import time (GH#62/#63).
|
|
96
|
+
*
|
|
97
|
+
* WHY `createRequire` and not `await import('js-yaml')`: every caller of
|
|
98
|
+
* {@link loadOwnerConfig} consumes it SYNCHRONOUSLY. Measured 2026-09-06 with
|
|
99
|
+
* `rg -n --glob '!tests/**' 'loadOwnerConfig\(' scripts hooks skills` (minus
|
|
100
|
+
* this file and the unrelated async homonym in `owner-config-loader.mjs`):
|
|
101
|
+
* 9 call sites — 8 in code, 1 in `skills/session-start/SKILL.md:1113` — and
|
|
102
|
+
* `rg 'await\s+loadOwnerConfig'` over the same scope returns ZERO. Eight read
|
|
103
|
+
* `loadOwnerConfig().config` (`hooks/on-session-start.mjs:639`,
|
|
104
|
+
* `hooks/skill-invocation-telemetry.mjs:155`, `scripts/telemetry.mjs:81,130`,
|
|
105
|
+
* `scripts/vault-mirror.mjs:444`, `scripts/lib/telemetry/sync.mjs:202,269`,
|
|
106
|
+
* and the SKILL.md snippet); the ninth destructures the same sync return
|
|
107
|
+
* (`scripts/lib/soul-resolve.mjs:123`). `writeOwnerConfig` is likewise sync at
|
|
108
|
+
* its single call site, `scripts/lib/owner-interview.mjs:228`.
|
|
109
|
+
*
|
|
110
|
+
* Making either loader async would be a breaking change to all of them; a lazy
|
|
111
|
+
* `require()` keeps the sync contract and only fails at CALL time — where the
|
|
112
|
+
* failure is catchable — instead of at module load, where it is not.
|
|
113
|
+
*
|
|
114
|
+
* Same shape as the `getPicomatch()` pattern in `scripts/lib/rule-loader.mjs`
|
|
115
|
+
* and `scripts/lib/validate-vendored-rules.mjs`.
|
|
116
|
+
*
|
|
117
|
+
* @returns {{ load: Function, dump: Function } | null} the module, or `null`
|
|
118
|
+
* when `node_modules` is absent / the package cannot be resolved.
|
|
119
|
+
*/
|
|
120
|
+
function getYaml() {
|
|
121
|
+
if (_yaml !== null) return _yaml === false ? null : _yaml;
|
|
122
|
+
try {
|
|
123
|
+
_yaml = createRequire(import.meta.url)('js-yaml');
|
|
124
|
+
} catch {
|
|
125
|
+
_yaml = false;
|
|
126
|
+
}
|
|
127
|
+
return _yaml === false ? null : _yaml;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Emit the one-per-process actionable WARN for a missing `js-yaml`. Kept to a
|
|
132
|
+
* SINGLE line and rate-limited to once per process, mirroring the GH#63
|
|
133
|
+
* degradation contract `hooks/on-stop.mjs` already satisfies: a missing package
|
|
134
|
+
* must never be louder than the fix it asks for.
|
|
135
|
+
*/
|
|
136
|
+
function warnYamlMissing() {
|
|
137
|
+
if (_yamlWarned) return;
|
|
138
|
+
_yamlWarned = true;
|
|
139
|
+
console.warn(
|
|
140
|
+
"WARN owner-yaml: 'js-yaml' is not installed — owner.yaml cannot be parsed or written; " +
|
|
141
|
+
"using defaults. Run 'npm install' in the plugin directory to restore it.",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Re-export of the single host-private-config-dir resolver (#1223).
|
|
147
|
+
*
|
|
148
|
+
* The implementation lives in the ZERO-IMPORT leaf
|
|
149
|
+
* `scripts/lib/config/private-config-dir.mjs`, NOT here: `host-identity.mjs`
|
|
150
|
+
* sits on `hooks/on-stop.mjs`'s import subgraph (via `session-lock.mjs`), and
|
|
151
|
+
* this module statically imports `js-yaml`. While the resolver lived here,
|
|
152
|
+
* importing it from `host-identity.mjs` dragged `js-yaml` onto THAT subgraph and
|
|
153
|
+
* broke the GH#63 "degrade gracefully without node_modules" contract
|
|
154
|
+
* (`ERR_MODULE_NOT_FOUND` in `tests/hooks/on-stop.test.mjs`).
|
|
155
|
+
*
|
|
156
|
+
* As of GitLab #1230 (2026-09-06) THIS module is no longer a bare-specifier node
|
|
157
|
+
* on that graph either: the `js-yaml` import it used to carry statically is now
|
|
158
|
+
* lazy (see {@link getYaml}), so the four hooks that reach this file —
|
|
159
|
+
* on-session-start, on-session-end, post-edit-validate,
|
|
160
|
+
* skill-invocation-telemetry — load without `node_modules` instead of dying with
|
|
161
|
+
* ERR_MODULE_NOT_FOUND. Keep it that way: any NEW static bare import added here
|
|
162
|
+
* re-breaks all four at once, in a file whose own unit tests would never notice
|
|
163
|
+
* (the repo always has `node_modules`).
|
|
164
|
+
*
|
|
165
|
+
* NOTE for `tests/husky/pre-commit-owner-leakage.test.mjs`: that test copies
|
|
166
|
+
* the CP11 import chain FILE BY FILE into a tmp repo, so the leaf below is on
|
|
167
|
+
* its copied-file list. Any FURTHER repo-local import added here needs the same
|
|
168
|
+
* treatment.
|
|
169
|
+
*/
|
|
170
|
+
export { resolvePrivateConfigDir };
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Resolve the owner.yaml path at CALL time via the single private-config-dir
|
|
174
|
+
* resolver {@link resolvePrivateConfigDir} (#1223). Honours
|
|
175
|
+
* `SO_CONFIG_HOME` > `XDG_CONFIG_HOME` > homedir, each trimmed.
|
|
176
|
+
*
|
|
177
|
+
* @param {Record<string, string|undefined>} [env] — env source (default `process.env`)
|
|
178
|
+
* @returns {string} absolute path to owner.yaml
|
|
179
|
+
*/
|
|
180
|
+
export function resolveOwnerYamlPath(env = process.env) {
|
|
181
|
+
return join(resolvePrivateConfigDir({ env }), OWNER_YAML_FILE);
|
|
182
|
+
}
|
|
61
183
|
|
|
62
184
|
const VALID_LANGUAGES = /** @type {const} */ (['de', 'en']);
|
|
63
185
|
const VALID_TONE_STYLES = /** @type {const} */ (['direct', 'neutral', 'friendly']);
|
|
@@ -418,19 +540,43 @@ export function validateOwnerConfig(obj) {
|
|
|
418
540
|
* surfaced only via `sectionWarnings` (never dropped, never counted towards
|
|
419
541
|
* `'partial'`).
|
|
420
542
|
*
|
|
543
|
+
* MERGE RULE for the whole-file discard (GitLab #1244). The discard returns
|
|
544
|
+
* `getDefaults()` — but a VALID optional object section is merged back on top
|
|
545
|
+
* of its default (`{...defaults[name], ...parsed[name]}`), key by key. `source`
|
|
546
|
+
* stays `'defaults'` and `errors` still carries every required-section error,
|
|
547
|
+
* so no existing caller's branch changes; what changes is that a host-local
|
|
548
|
+
* path the operator DID declare correctly is no longer thrown away because an
|
|
549
|
+
* unrelated section (e.g. `tone:`) is malformed. That silent loss was a
|
|
550
|
+
* fail-OPEN path for the owner-leakage scanner's CP11 rule: a partial
|
|
551
|
+
* owner.yaml carrying only `owner:` + `paths.confidential-names-file:` made the
|
|
552
|
+
* scanner report PASS while matching nothing. An INVALID optional section is
|
|
553
|
+
* still replaced by its default and is now reported via `droppedSections` on
|
|
554
|
+
* this branch too (previously only on the required-valid branch), so a consumer
|
|
555
|
+
* can tell "not configured" from "configured but unusable".
|
|
556
|
+
*
|
|
421
557
|
* Defensive — never throws.
|
|
422
558
|
*
|
|
559
|
+
* When `js-yaml` cannot be resolved (no `node_modules`), returns defaults with
|
|
560
|
+
* `source: 'defaults'`, `reason: 'yaml-parser-missing'` and one explanatory
|
|
561
|
+
* entry in `errors` — never throws, never crashes the importing hook (GH#62/#63).
|
|
562
|
+
* When the file exists but cannot be turned into an object at all (unreadable,
|
|
563
|
+
* YAML syntax error, non-mapping top level) the same shape is returned with
|
|
564
|
+
* `reason: 'unparseable'`: in that state NOTHING about the file's contents is
|
|
565
|
+
* knowable, which is the distinction CP11 needs in order to fail CLOSED rather
|
|
566
|
+
* than assume "nothing configured".
|
|
567
|
+
*
|
|
423
568
|
* @param {{ path?: string }} [opts]
|
|
424
569
|
* @returns {{
|
|
425
570
|
* config: object,
|
|
426
571
|
* source: 'file'|'defaults'|'partial',
|
|
427
572
|
* errors: string[],
|
|
573
|
+
* reason?: 'yaml-parser-missing'|'unparseable',
|
|
428
574
|
* droppedSections?: Array<{ section: string, errors: string[] }>,
|
|
429
575
|
* sectionWarnings?: Array<{ section: string, errors: string[] }>,
|
|
430
576
|
* }}
|
|
431
577
|
*/
|
|
432
578
|
export function loadOwnerConfig(opts = {}) {
|
|
433
|
-
const filePath = opts.path ??
|
|
579
|
+
const filePath = opts.path ?? resolveOwnerYamlPath();
|
|
434
580
|
|
|
435
581
|
if (!existsSync(filePath)) {
|
|
436
582
|
return { config: getDefaults(), source: 'defaults', errors: [] };
|
|
@@ -443,10 +589,24 @@ export function loadOwnerConfig(opts = {}) {
|
|
|
443
589
|
return {
|
|
444
590
|
config: getDefaults(),
|
|
445
591
|
source: 'defaults',
|
|
592
|
+
reason: 'unparseable',
|
|
446
593
|
errors: [`failed to read owner.yaml: ${err.message}`],
|
|
447
594
|
};
|
|
448
595
|
}
|
|
449
596
|
|
|
597
|
+
const yaml = getYaml();
|
|
598
|
+
if (!yaml) {
|
|
599
|
+
warnYamlMissing();
|
|
600
|
+
return {
|
|
601
|
+
config: getDefaults(),
|
|
602
|
+
source: 'defaults',
|
|
603
|
+
reason: 'yaml-parser-missing',
|
|
604
|
+
errors: [
|
|
605
|
+
"yaml-parser-missing: 'js-yaml' is not installed, so owner.yaml could not be parsed (run 'npm install' in the plugin directory)",
|
|
606
|
+
],
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
450
610
|
let parsed;
|
|
451
611
|
try {
|
|
452
612
|
parsed = yaml.load(raw);
|
|
@@ -454,6 +614,7 @@ export function loadOwnerConfig(opts = {}) {
|
|
|
454
614
|
return {
|
|
455
615
|
config: getDefaults(),
|
|
456
616
|
source: 'defaults',
|
|
617
|
+
reason: 'unparseable',
|
|
457
618
|
errors: [`YAML parse error: ${err.message}`],
|
|
458
619
|
};
|
|
459
620
|
}
|
|
@@ -462,20 +623,36 @@ export function loadOwnerConfig(opts = {}) {
|
|
|
462
623
|
return {
|
|
463
624
|
config: getDefaults(),
|
|
464
625
|
source: 'defaults',
|
|
626
|
+
reason: 'unparseable',
|
|
465
627
|
errors: ['owner.yaml must contain a YAML mapping at the top level'],
|
|
466
628
|
};
|
|
467
629
|
}
|
|
468
630
|
|
|
469
631
|
const { sections, errors: allErrors } = validateOwnerSections(parsed);
|
|
470
632
|
|
|
471
|
-
// Any REQUIRED section invalid →
|
|
633
|
+
// Any REQUIRED section invalid → whole-file discard (#820), EXCEPT that a
|
|
634
|
+
// VALID optional object section is merged back onto its default (#1244 — see
|
|
635
|
+
// the MERGE RULE in the JSDoc above). `source` stays 'defaults' and `errors`
|
|
636
|
+
// is unchanged, so every existing caller branch is untouched; only the
|
|
637
|
+
// discarded-but-valid `paths:`/`dispatcher:` keys survive, which is what stops
|
|
638
|
+
// CP11 from going silently inert on a partial owner.yaml.
|
|
472
639
|
const requiredInvalid = REQUIRED_SECTIONS.some((name) => !sections[name]?.valid);
|
|
473
640
|
if (requiredInvalid) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
641
|
+
const discardConfig = getDefaults();
|
|
642
|
+
const discardDropped = [];
|
|
643
|
+
for (const name of OPTIONAL_OBJECT_SECTIONS) {
|
|
644
|
+
const sec = sections[name];
|
|
645
|
+
if (sec?.valid && isPlainObject(parsed[name])) {
|
|
646
|
+
discardConfig[name] = { ...discardConfig[name], ...parsed[name] };
|
|
647
|
+
} else if (sec && !sec.valid) {
|
|
648
|
+
// Present but malformed — already replaced by its default above. Report
|
|
649
|
+
// it so a consumer can distinguish "not configured" from "unusable".
|
|
650
|
+
discardDropped.push({ section: name, errors: sec.errors });
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
const discardResult = { config: discardConfig, source: 'defaults', errors: allErrors };
|
|
654
|
+
if (discardDropped.length > 0) discardResult.droppedSections = discardDropped;
|
|
655
|
+
return discardResult;
|
|
479
656
|
}
|
|
480
657
|
|
|
481
658
|
// All REQUIRED sections valid — tolerate malformed OPTIONAL sections instead
|
|
@@ -532,12 +709,16 @@ export function loadOwnerConfig(opts = {}) {
|
|
|
532
709
|
*
|
|
533
710
|
* Synchronous. Defensive — never throws.
|
|
534
711
|
*
|
|
712
|
+
* When `js-yaml` cannot be resolved (no `node_modules`), returns
|
|
713
|
+
* `{ written: false, reason: 'yaml-parser-missing', errors: [...] }` — the file
|
|
714
|
+
* is left untouched rather than half-written (GH#62/#63).
|
|
715
|
+
*
|
|
535
716
|
* @param {object} config
|
|
536
717
|
* @param {{ path?: string }} [opts]
|
|
537
|
-
* @returns {{ written: boolean, errors: string[] }}
|
|
718
|
+
* @returns {{ written: boolean, errors: string[], reason?: 'yaml-parser-missing' }}
|
|
538
719
|
*/
|
|
539
720
|
export function writeOwnerConfig(config, opts = {}) {
|
|
540
|
-
const filePath = opts.path ??
|
|
721
|
+
const filePath = opts.path ?? resolveOwnerYamlPath();
|
|
541
722
|
|
|
542
723
|
const validation = validateOwnerConfig(config);
|
|
543
724
|
if (!validation.valid) {
|
|
@@ -554,6 +735,18 @@ export function writeOwnerConfig(config, opts = {}) {
|
|
|
554
735
|
};
|
|
555
736
|
}
|
|
556
737
|
|
|
738
|
+
const yaml = getYaml();
|
|
739
|
+
if (!yaml) {
|
|
740
|
+
warnYamlMissing();
|
|
741
|
+
return {
|
|
742
|
+
written: false,
|
|
743
|
+
reason: 'yaml-parser-missing',
|
|
744
|
+
errors: [
|
|
745
|
+
"yaml-parser-missing: 'js-yaml' is not installed, so owner.yaml could not be written (run 'npm install' in the plugin directory)",
|
|
746
|
+
],
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
557
750
|
let yamlStr;
|
|
558
751
|
try {
|
|
559
752
|
yamlStr = yaml.dump(config, { lineWidth: 120, noRefs: true });
|
package/scripts/lib/platform.mjs
CHANGED
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
* platform.mjs — platform detection for session-orchestrator (Node.js port of platform.sh)
|
|
3
3
|
* ESM-importable. Uses only Node built-ins. No external dependencies.
|
|
4
4
|
*
|
|
5
|
-
* Exports
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Exports:
|
|
6
|
+
* - lazy memoized accessors (#1153 P5): getPlatform, getPluginRoot, getProjectDir,
|
|
7
|
+
* getStateDir, getConfigFile (+ test-only _resetPlatformCache)
|
|
8
|
+
* - plain constants (no filesystem work): SO_SHARED_DIR, SO_OS, SO_IS_WINDOWS,
|
|
9
|
+
* SO_IS_WSL, SO_PATH_SEP
|
|
10
|
+
* - pure resolvers: detectPlatform, resolvePluginRoot, resolveProjectDir,
|
|
11
|
+
* resolveStateDir, resolveConfigFile
|
|
12
|
+
*
|
|
13
|
+
* NOTHING in this module touches the filesystem at import time.
|
|
9
14
|
*/
|
|
10
15
|
|
|
11
16
|
import { existsSync, statSync } from 'node:fs';
|
|
@@ -293,23 +298,111 @@ export function resolveConfigFile(platform) {
|
|
|
293
298
|
}
|
|
294
299
|
|
|
295
300
|
// ---------------------------------------------------------------------------
|
|
296
|
-
//
|
|
301
|
+
// Lazy, memoized accessors (#1153 P5)
|
|
297
302
|
// ---------------------------------------------------------------------------
|
|
303
|
+
//
|
|
304
|
+
// These five values used to be `export const … = detect…()` evaluated at MODULE
|
|
305
|
+
// LOAD, so every one of the ~31 static importers — including the hottest
|
|
306
|
+
// deny-capable hooks, which run on every single tool call — paid a filesystem
|
|
307
|
+
// walk-up (statSync/existsSync per ancestor directory, twice over for
|
|
308
|
+
// resolvePluginRoot) merely for importing this module, whether or not it ever
|
|
309
|
+
// read the value.
|
|
310
|
+
//
|
|
311
|
+
// They are now computed on FIRST USE and memoized. Call the getter at the point
|
|
312
|
+
// of use, never at a module's top level — a top-level `const X = getProjectDir()`
|
|
313
|
+
// re-creates the exact cost this change removes.
|
|
298
314
|
|
|
299
|
-
/**
|
|
300
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Memo slots. `undefined` is the miss sentinel — `''` is a legitimate
|
|
317
|
+
* resolvePluginRoot() result and must not re-trigger resolution.
|
|
318
|
+
* @type {{platform: ("claude"|"codex"|"cursor"|"pi")|undefined, pluginRoot: string|undefined, projectDir: string|undefined, stateDir: string|undefined, configFile: string|undefined}}
|
|
319
|
+
*/
|
|
320
|
+
const _cache = {
|
|
321
|
+
platform: undefined,
|
|
322
|
+
pluginRoot: undefined,
|
|
323
|
+
projectDir: undefined,
|
|
324
|
+
stateDir: undefined,
|
|
325
|
+
configFile: undefined,
|
|
326
|
+
};
|
|
301
327
|
|
|
302
|
-
/**
|
|
303
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Host platform, detected once per process.
|
|
330
|
+
* @returns {"claude"|"codex"|"cursor"|"pi"}
|
|
331
|
+
*/
|
|
332
|
+
export function getPlatform() {
|
|
333
|
+
if (_cache.platform === undefined) {
|
|
334
|
+
_cache.platform = detectPlatform();
|
|
335
|
+
}
|
|
336
|
+
return _cache.platform;
|
|
337
|
+
}
|
|
304
338
|
|
|
305
|
-
/**
|
|
306
|
-
|
|
339
|
+
/**
|
|
340
|
+
* Absolute path to the session-orchestrator plugin directory, resolved once.
|
|
341
|
+
* @returns {string} Absolute path, or empty string if unresolvable.
|
|
342
|
+
*/
|
|
343
|
+
export function getPluginRoot() {
|
|
344
|
+
if (_cache.pluginRoot === undefined) {
|
|
345
|
+
_cache.pluginRoot = resolvePluginRoot(getPlatform());
|
|
346
|
+
}
|
|
347
|
+
return _cache.pluginRoot;
|
|
348
|
+
}
|
|
307
349
|
|
|
308
|
-
/**
|
|
309
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Absolute path to the current project root, resolved once.
|
|
352
|
+
* @returns {string}
|
|
353
|
+
*/
|
|
354
|
+
export function getProjectDir() {
|
|
355
|
+
if (_cache.projectDir === undefined) {
|
|
356
|
+
_cache.projectDir = resolveProjectDir(getPlatform());
|
|
357
|
+
}
|
|
358
|
+
return _cache.projectDir;
|
|
359
|
+
}
|
|
310
360
|
|
|
311
|
-
/**
|
|
312
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Platform-native state directory name (".claude" | ".codex" | ".cursor" | ".pi").
|
|
363
|
+
* @returns {string}
|
|
364
|
+
*/
|
|
365
|
+
export function getStateDir() {
|
|
366
|
+
if (_cache.stateDir === undefined) {
|
|
367
|
+
_cache.stateDir = resolveStateDir(getPlatform());
|
|
368
|
+
}
|
|
369
|
+
return _cache.stateDir;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Platform config file name ("CLAUDE.md" | "AGENTS.md").
|
|
374
|
+
* @returns {string}
|
|
375
|
+
*/
|
|
376
|
+
export function getConfigFile() {
|
|
377
|
+
if (_cache.configFile === undefined) {
|
|
378
|
+
_cache.configFile = resolveConfigFile(getPlatform());
|
|
379
|
+
}
|
|
380
|
+
return _cache.configFile;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Test-only: drop every memoized value so the next getter re-detects.
|
|
385
|
+
* Production code must never call this — the values are process-stable.
|
|
386
|
+
* @returns {void}
|
|
387
|
+
*/
|
|
388
|
+
export function _resetPlatformCache() {
|
|
389
|
+
_cache.platform = undefined;
|
|
390
|
+
_cache.pluginRoot = undefined;
|
|
391
|
+
_cache.projectDir = undefined;
|
|
392
|
+
_cache.stateDir = undefined;
|
|
393
|
+
_cache.configFile = undefined;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// The deprecated `export let SO_PLATFORM / SO_PLUGIN_ROOT / SO_PROJECT_DIR /
|
|
397
|
+
// SO_STATE_DIR / SO_CONFIG_FILE` live bindings (#1153 P5) are GONE. They were
|
|
398
|
+
// `undefined` until the matching getter had run in the process, which made
|
|
399
|
+
// every bare read a silent wrong answer. Every consumer now calls the getter
|
|
400
|
+
// (getPlatform(), getProjectDir(), …). A re-introduction is caught by the
|
|
401
|
+
// named-export assertion in tests/lib/platform.test.mjs — do not add them back.
|
|
402
|
+
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
// Plain constants — no filesystem work, safe to evaluate at load
|
|
405
|
+
// ---------------------------------------------------------------------------
|
|
313
406
|
|
|
314
407
|
/** Shared orchestrator directory name — always ".orchestrator" */
|
|
315
408
|
export const SO_SHARED_DIR = '.orchestrator';
|