session-orchestrator 4.0.1 → 4.2.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.
Files changed (145) hide show
  1. package/.agents/skills/session-plan/SKILL.md +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/.codex-plugin/skills/session-plan/SKILL.md +1 -1
  6. package/.cursor/skills/session-plan/SKILL.md +1 -1
  7. package/.cursor-plugin/plugin.json +1 -1
  8. package/CHANGELOG.md +57 -0
  9. package/README.md +55 -51
  10. package/agents/ux-evaluator.md +1 -1
  11. package/commands/close.md +3 -3
  12. package/commands/go.md +2 -0
  13. package/commands/memory-cleanup.md +4 -3
  14. package/commands/persona-panel.md +1 -1
  15. package/commands/release.md +4 -4
  16. package/commands/session.md +3 -2
  17. package/docs/README.md +4 -4
  18. package/docs/USER-GUIDE.md +115 -48
  19. package/docs/agent-authoring.md +2 -2
  20. package/docs/baseline.md +55 -1
  21. package/docs/ci-setup.md +1 -1
  22. package/docs/codex-setup.md +1 -0
  23. package/docs/components.md +2 -2
  24. package/docs/cursor-setup.md +1 -0
  25. package/docs/events-schema.md +4 -1
  26. package/docs/instruction-delivery.md +1 -1
  27. package/docs/memory-proposal-flow.md +3 -3
  28. package/docs/migration-v4.md +2 -2
  29. package/docs/owner-config-schema.md +74 -90
  30. package/docs/persona-panel.md +4 -4
  31. package/docs/pi-setup.md +1 -0
  32. package/docs/rule-authoring.md +13 -6
  33. package/docs/scope-collision-guard.md +2 -0
  34. package/docs/session-config-reference.md +55 -22
  35. package/docs/session-config-template.md +9 -5
  36. package/docs/vault-docs-architecture.md +4 -2
  37. package/hooks/_lib/hook-import-set.json +28 -3
  38. package/hooks/_lib/vcs-create-matcher.mjs +214 -16
  39. package/hooks/hooks-codex.json +1 -1
  40. package/hooks/hooks.json +1 -1
  41. package/hooks/pre-bash-issue-budget.mjs +123 -26
  42. package/hooks/subagent-telemetry.mjs +106 -20
  43. package/package.json +4 -4
  44. package/scripts/baseline-archetypes.mjs +28 -0
  45. package/scripts/ci/assert-coverage-green.mjs +100 -0
  46. package/scripts/lib/auto-dialectic.mjs +0 -68
  47. package/scripts/lib/baseline-archetypes.mjs +439 -0
  48. package/scripts/lib/build-live-signals.mjs +5 -6
  49. package/scripts/lib/config/issue-budget.mjs +68 -8
  50. package/scripts/lib/config/private-config-dir.mjs +3 -2
  51. package/scripts/lib/config/remote-hosts.mjs +2 -2
  52. package/scripts/lib/config-schema.mjs +79 -0
  53. package/scripts/lib/events.mjs +3 -3
  54. package/scripts/lib/file-lock.mjs +47 -5
  55. package/scripts/lib/issue-budget-reconcile.mjs +392 -0
  56. package/scripts/lib/issue-budget.mjs +76 -3
  57. package/scripts/lib/learnings/evolve-telemetry.mjs +1 -2
  58. package/scripts/lib/maintenance-due-banner.mjs +440 -0
  59. package/scripts/lib/owner-config.example.yaml +29 -46
  60. package/scripts/lib/owner-yaml.mjs +14 -13
  61. package/scripts/lib/project-hygiene.mjs +182 -6
  62. package/scripts/lib/quality-gate.mjs +13 -6
  63. package/scripts/lib/resource-probe/evaluate.mjs +19 -21
  64. package/scripts/lib/rules-sync.mjs +34 -4
  65. package/scripts/lib/session-close-backfill.mjs +182 -40
  66. package/scripts/lib/session-end/phase-skip.mjs +85 -86
  67. package/scripts/lib/session-end/tail-runner.mjs +178 -0
  68. package/scripts/lib/session-identity/own-session.mjs +24 -13
  69. package/scripts/lib/session-schema/constants.mjs +6 -0
  70. package/scripts/lib/session-schema/validator.mjs +20 -0
  71. package/scripts/lib/session-shape.mjs +558 -0
  72. package/scripts/lib/session-start-probes.mjs +10 -3
  73. package/scripts/lib/session-token-rollup.mjs +95 -10
  74. package/scripts/lib/state-md/frontmatter-mutators.mjs +22 -34
  75. package/scripts/lib/state-md.mjs +1 -0
  76. package/scripts/lib/subagents-schema.mjs +77 -9
  77. package/scripts/lib/telemetry/pricing.mjs +197 -0
  78. package/scripts/lib/telemetry/sync.mjs +50 -1
  79. package/scripts/lib/validate/check-owner-leakage.mjs +17 -8
  80. package/scripts/lib/validate/check-skill-script-paths.mjs +33 -10
  81. package/scripts/lib/validate/check-unwired-features.mjs +8 -7
  82. package/scripts/lib/vault-mirror/process.mjs +2 -1
  83. package/scripts/lib/vault-mirror/render-sessions.mjs +8 -1
  84. package/scripts/lib/vault-status/narrative-mirror.mjs +4 -4
  85. package/scripts/lib/wave-resource-gate.mjs +23 -27
  86. package/scripts/lib/wave-sizing.mjs +10 -3
  87. package/scripts/materialize-wave-scope.mjs +68 -14
  88. package/scripts/print-applicable-rules.mjs +7 -6
  89. package/scripts/print-learnings-index.mjs +3 -2
  90. package/scripts/release.mjs +32 -11
  91. package/scripts/session-shape.mjs +266 -0
  92. package/skills/_shared/config-reading.md +15 -9
  93. package/skills/_shared/private-capability-context.md +89 -0
  94. package/skills/bootstrap/SKILL.md +61 -13
  95. package/skills/bootstrap/_shared-template.md +99 -14
  96. package/skills/bootstrap/deep-template.md +36 -26
  97. package/skills/bootstrap/fast-template.md +44 -8
  98. package/skills/bootstrap/intensity-heuristic.md +10 -4
  99. package/skills/bootstrap/private-contract.md +119 -0
  100. package/skills/bootstrap/public-fallback.md +30 -18
  101. package/skills/bootstrap/standard-template.md +39 -24
  102. package/skills/discovery/probes-ui.md +1 -1
  103. package/skills/docs-orchestrator/audience-mapping.md +1 -1
  104. package/skills/evolve/SKILL.md +2 -2
  105. package/skills/gitlab-ops/SKILL.md +3 -3
  106. package/skills/grill/SKILL.md +1 -1
  107. package/skills/memory-cleanup/SKILL.md +2 -2
  108. package/skills/plan/mode-new.md +9 -0
  109. package/skills/reconcile/SKILL.md +1 -1
  110. package/skills/session-end/SKILL.md +3 -2
  111. package/skills/session-end/phase-3-2-docs-verification.md +1 -1
  112. package/skills/session-end/phase-3-6-tail.md +23 -65
  113. package/skills/session-end/phase-3-7a-recommendations.md +2 -2
  114. package/skills/session-end/references/phase-3-documentation-updates.md +8 -6
  115. package/skills/session-end/references/phase-5-issue-cleanup.md +26 -0
  116. package/skills/session-end/session-metrics-write.md +31 -12
  117. package/skills/session-plan/SKILL.md +56 -48
  118. package/skills/session-plan/wave-template.md +8 -15
  119. package/skills/session-start/SKILL.md +18 -2
  120. package/skills/session-start/phase-2-5-docs-planning.md +1 -1
  121. package/skills/session-start/phase-8-5-express-path.md +12 -9
  122. package/skills/session-start/references/phase-1-5-session-continuity.md +2 -0
  123. package/skills/session-start/references/phase-4-ssot-environment-check.md +21 -5
  124. package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +3 -1
  125. package/skills/test-runner/rubric-v1.md +2 -2
  126. package/skills/wave-executor/SKILL.md +42 -12
  127. package/skills/wave-executor/circuit-breaker.md +3 -1
  128. package/skills/wave-executor/references/wave-loop-dispatch.md +4 -2
  129. package/skills/wave-executor/references/wave-loop-review.md +1 -1
  130. package/skills/wave-executor/references/wave-loop-scope-manifest.md +6 -2
  131. package/templates/nextjs-minimal/package.json +1 -1
  132. package/templates/node-minimal/package.json +1 -1
  133. package/scripts/lib/multi-provider-build/providers.mjs +0 -64
  134. package/scripts/lib/multi-provider-build/templating.mjs +0 -130
  135. package/scripts/lib/owner-config/coerce.mjs +0 -29
  136. package/scripts/lib/owner-config/constants.mjs +0 -21
  137. package/scripts/lib/owner-config/defaults.mjs +0 -50
  138. package/scripts/lib/owner-config/error.mjs +0 -19
  139. package/scripts/lib/owner-config/index.mjs +0 -13
  140. package/scripts/lib/owner-config/merge.mjs +0 -52
  141. package/scripts/lib/owner-config/validate.mjs +0 -259
  142. package/scripts/lib/owner-config-loader.mjs +0 -170
  143. package/scripts/lib/owner-config.mjs +0 -28
  144. package/scripts/lib/soul-resolve.mjs +0 -130
  145. package/scripts/lib/vault-mirror/render.mjs +0 -8
@@ -1,170 +0,0 @@
1
- /**
2
- * owner-config-loader.mjs — File-system loader for owner.yaml (Issue #174).
3
- *
4
- * Companion to the pure schema/validator in `owner-config.mjs`. Resolves the
5
- * canonical config path (XDG-spec aware), reads the YAML, parses it, runs it
6
- * through the validator, and returns a `{ok, value, errors, source, path}`
7
- * envelope.
8
- *
9
- * ── PATH RESOLUTION ──────────────────────────────────────────────────────
10
- *
11
- * Default path (#1223 — delegated to the single resolver
12
- * `config/private-config-dir.mjs`; `SO_CONFIG_HOME` names the private dir
13
- * ITSELF and wins):
14
- * `${SO_CONFIG_HOME ?? ${XDG_CONFIG_HOME ?? ${HOME}/.config}/session-orchestrator}/owner.yaml`
15
- * - macOS / Linux: `~/.config/session-orchestrator/owner.yaml`
16
- * - Windows: `%APPDATA%\session-orchestrator\owner.yaml` when
17
- * APPDATA is set and XDG_CONFIG_HOME is not (Node uses
18
- * USERPROFILE for os.homedir() — falls back gracefully).
19
- *
20
- * Callers may pass an explicit `{path}` override (used by tests + D4
21
- * baseline-propagation when the canonical path is overridden by env).
22
- *
23
- * ── RETURN SHAPE ─────────────────────────────────────────────────────────
24
- *
25
- * {
26
- * ok: boolean, // false on any failure
27
- * value: object|null, // normalized config when ok=true
28
- * errors: string[], // populated on any failure
29
- * source: 'file'|'missing'|'parse-error'|'validation-error',
30
- * path: string, // resolved absolute path
31
- * }
32
- *
33
- * `source: 'missing'` is NOT an error — owner.yaml is opt-in (the bootstrap
34
- * interview in D2 creates it). Callers should treat `source: 'missing'` as
35
- * "no owner persona configured; fall back to plugin defaults".
36
- *
37
- * ── PLATFORM PORTABILITY ─────────────────────────────────────────────────
38
- *
39
- * - Uses `os.homedir()` (Node-stdlib, OS-aware) rather than $HOME so the
40
- * Windows path resolves correctly even when only USERPROFILE is set.
41
- * - File reads are UTF-8 only. Owner.yaml is ASCII-safe by spec; non-UTF-8
42
- * content yields `source: 'parse-error'`.
43
- * - YAML parsing via `js-yaml` (devDep already pulled in by W2 quality-fix).
44
- */
45
-
46
- import { readFile } from 'node:fs/promises';
47
- import { existsSync } from 'node:fs';
48
- import { join } from 'node:path';
49
- import yaml from 'js-yaml';
50
-
51
- import { validate } from './owner-config.mjs';
52
- import { resolvePrivateConfigDir } from './config/private-config-dir.mjs';
53
-
54
- // ---------------------------------------------------------------------------
55
- // Path resolution
56
- // ---------------------------------------------------------------------------
57
-
58
- /**
59
- * Resolve the canonical owner.yaml path on disk: the ONE private-config-dir
60
- * resolver (#1223) plus the file's basename — precedence `SO_CONFIG_HOME` (the
61
- * private dir itself) > `XDG_CONFIG_HOME` (its parent) > `${HOME}/.config`, each
62
- * `.trim()`ed so a whitespace-only value falls through instead of
63
- * short-circuiting (`.claude/rules/development.md` § Error Handling).
64
- *
65
- * Reaches the leaf DIRECTLY rather than through `owner-yaml.mjs`'s
66
- * `resolveOwnerYamlPath()`: that hop exists only to append the same basename and
67
- * drags a `js-yaml`-importing module in with it. The precedence — the part #1223
68
- * consolidated — still lives in exactly one place; only the literal `'owner.yaml'`
69
- * is stated twice.
70
- *
71
- * Before #1223 this function knew only `XDG_CONFIG_HOME` and did not trim, so
72
- * `SO_CONFIG_HOME=<sandbox>` still read the operator's real home.
73
- *
74
- * Returns an absolute path string. Does NOT touch the filesystem.
75
- *
76
- * @returns {string} absolute path to owner.yaml
77
- */
78
- export function resolveOwnerConfigPath() {
79
- return join(resolvePrivateConfigDir(), 'owner.yaml');
80
- }
81
-
82
- // ---------------------------------------------------------------------------
83
- // Loader
84
- // ---------------------------------------------------------------------------
85
-
86
- /**
87
- * Load and validate the owner.yaml config from disk.
88
- *
89
- * Defensive — never throws. Distinguishes four outcomes via the `source`
90
- * field so callers can react differently to "missing file" (opt-in feature
91
- * not yet enabled by the user) vs "malformed YAML" (broken state, surface
92
- * to user).
93
- *
94
- * @param {{path?: string}} [opts]
95
- * @returns {Promise<{ok: boolean, value: object|null, errors: string[], source: string, path: string}>}
96
- */
97
- export async function loadOwnerConfig(opts = {}) {
98
- const path = opts.path ?? resolveOwnerConfigPath();
99
-
100
- if (!existsSync(path)) {
101
- return {
102
- ok: false,
103
- value: null,
104
- errors: [],
105
- source: 'missing',
106
- path,
107
- };
108
- }
109
-
110
- let raw;
111
- try {
112
- raw = await readFile(path, 'utf8');
113
- } catch (err) {
114
- return {
115
- ok: false,
116
- value: null,
117
- errors: [`failed to read owner config: ${err.message}`],
118
- source: 'parse-error',
119
- path,
120
- };
121
- }
122
-
123
- let parsed;
124
- try {
125
- // js-yaml's default schema (CORE_SCHEMA) is safe — it explicitly excludes
126
- // the !!js/function and !!js/regexp tags from the legacy DEFAULT_SCHEMA
127
- // that would let a malicious YAML file execute code or pollute prototypes.
128
- parsed = yaml.load(raw);
129
- } catch (err) {
130
- return {
131
- ok: false,
132
- value: null,
133
- errors: [`YAML parse error: ${err.message}`],
134
- source: 'parse-error',
135
- path,
136
- };
137
- }
138
-
139
- // Empty file or YAML "null" → treat as parse-error so the caller knows
140
- // there's nothing to merge (vs a missing file which opts the user out
141
- // entirely).
142
- if (parsed === null || parsed === undefined) {
143
- return {
144
- ok: false,
145
- value: null,
146
- errors: ['owner config is empty'],
147
- source: 'parse-error',
148
- path,
149
- };
150
- }
151
-
152
- const validation = validate(parsed);
153
- if (!validation.ok) {
154
- return {
155
- ok: false,
156
- value: null,
157
- errors: validation.errors,
158
- source: 'validation-error',
159
- path,
160
- };
161
- }
162
-
163
- return {
164
- ok: true,
165
- value: validation.value,
166
- errors: [],
167
- source: 'file',
168
- path,
169
- };
170
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * owner-config.mjs — Owner Persona schema + validator (Issue #174, Sub-Epic #161).
3
- *
4
- * Thin re-export wrapper. All logic lives in `./owner-config/` submodules:
5
- * constants.mjs — frozen enum arrays + schema version
6
- * error.mjs — OwnerConfigError class
7
- * defaults.mjs — defaults() factory
8
- * validate.mjs — validate() + 7 section helpers
9
- * coerce.mjs — coerce() strict-mode wrapper
10
- * merge.mjs — merge() deep-merge
11
- * index.mjs — re-export hub (aggregates all 10 public symbols)
12
- *
13
- * For the full schema contract and module DAG see `./owner-config/index.mjs`.
14
- * The loader (which does touch the disk) lives in `owner-config-loader.mjs`.
15
- */
16
-
17
- export {
18
- CURRENT_OWNER_SCHEMA_VERSION,
19
- VALID_TONE_STYLES,
20
- VALID_OUTPUT_LEVELS,
21
- VALID_PREAMBLE_LEVELS,
22
- VALID_COMMENTS_LEVELS,
23
- OwnerConfigError,
24
- defaults,
25
- validate,
26
- coerce,
27
- merge,
28
- } from './owner-config/index.mjs';
@@ -1,130 +0,0 @@
1
- /**
2
- * soul-resolve.mjs — Template resolver for soul.md files (Issue #176, D3).
3
- *
4
- * Resolves `{{slot}}` placeholders in soul.md templates using owner persona
5
- * config loaded via `owner-yaml.mjs` (D1). Pure at the `resolveSoul` level;
6
- * `loadAndResolveSoul` performs disk I/O.
7
- *
8
- * ── NO RUNTIME CALLER — read this before assuming a soul.md is resolved ──────
9
- *
10
- * Nothing in `scripts/`, `hooks/`, or any skill body calls either export. Skill
11
- * bodies instruct the coordinator to read soul.md DIRECTLY, so whatever is in
12
- * the file on disk is what the coordinator sees — an unsubstituted `{{slot}}`
13
- * reaches the model verbatim and instructs nothing. `skills/session-start/soul.md`
14
- * is therefore authored pre-resolved: it carries no slots, and the operator's
15
- * `efficiency.output-level` selects one of its literal `### output-level: <value>`
16
- * blocks (see that file's § Output Levels; the skill body performs the lookup).
17
- * Slots that remain in other soul.md files are inert for the same reason.
18
- * Do not add a slot to a soul.md expecting substitution — wire a caller first.
19
- *
20
- * ── Slot syntax ──────────────────────────────────────────────────────────────
21
- *
22
- * {{owner.language}} → 'de' | 'en'
23
- * {{tone.style}} → 'direct' | 'neutral' | 'friendly'
24
- * {{efficiency.output-level}} → 'lite' | 'full' | 'ultra'
25
- * {{efficiency.preamble}} → 'minimal' | 'verbose'
26
- *
27
- * ── Resolution rules ─────────────────────────────────────────────────────────
28
- *
29
- * - Known slot path present in ownerConfig → replaced with the value
30
- * - Known slot path missing in ownerConfig → replaced with default (silent)
31
- * - Unknown slot path → left as-is; warning added to result
32
- *
33
- * ── Exports ───────────────────────────────────────────────────────────────────
34
- *
35
- * resolveSoul(templateContent, ownerConfig) → { resolved: string, warnings: string[] }
36
- * loadAndResolveSoul(soulPath, opts?) → { resolved: string, warnings: string[], source: string }
37
- */
38
-
39
- import { readFileSync } from 'node:fs';
40
- import { loadOwnerConfig, getDefaults } from './owner-yaml.mjs';
41
-
42
- // ---------------------------------------------------------------------------
43
- // Helpers
44
- // ---------------------------------------------------------------------------
45
-
46
- /**
47
- * Look up a dot-notation path such as "efficiency.output-level" in a nested
48
- * object. Returns `undefined` if any segment is missing.
49
- *
50
- * @param {object} obj
51
- * @param {string} dotPath
52
- * @returns {unknown}
53
- */
54
- function getByPath(obj, dotPath) {
55
- const segments = dotPath.split('.');
56
- let cursor = obj;
57
- for (const seg of segments) {
58
- if (cursor === null || cursor === undefined || typeof cursor !== 'object') {
59
- return undefined;
60
- }
61
- cursor = cursor[seg];
62
- }
63
- return cursor;
64
- }
65
-
66
- /**
67
- * Set of slot paths explicitly documented / known by this module.
68
- * Any slot NOT in this set is considered unknown and left in place with a warning.
69
- */
70
- const KNOWN_SLOTS = new Set([
71
- 'owner.language',
72
- 'tone.style',
73
- 'efficiency.output-level',
74
- 'efficiency.preamble',
75
- ]);
76
-
77
- // ---------------------------------------------------------------------------
78
- // Public API
79
- // ---------------------------------------------------------------------------
80
-
81
- /**
82
- * Resolve `{{slot}}` placeholders in `templateContent` using `ownerConfig`.
83
- *
84
- * Pure function — no I/O, no side-effects.
85
- *
86
- * @param {string} templateContent Raw soul.md template text.
87
- * @param {object} ownerConfig Owner persona config (from loadOwnerConfig or getDefaults).
88
- * @returns {{ resolved: string, warnings: string[] }}
89
- */
90
- export function resolveSoul(templateContent, ownerConfig) {
91
- const defaults = getDefaults();
92
- const warnings = [];
93
-
94
- const resolved = templateContent.replace(/\{\{\s*([\w.-]+)\s*\}\}/g, (_match, path) => {
95
- if (!KNOWN_SLOTS.has(path)) {
96
- warnings.push(`Unknown slot path: {{${path}}} — left in place`);
97
- return `{{${path}}}`;
98
- }
99
-
100
- // Try ownerConfig first, then fall back to defaults
101
- let value = getByPath(ownerConfig, path);
102
- if (value === undefined || value === null || value === '') {
103
- value = getByPath(defaults, path);
104
- }
105
-
106
- return String(value ?? '');
107
- });
108
-
109
- return { resolved, warnings };
110
- }
111
-
112
- /**
113
- * Read a soul.md template from `soulPath`, load owner config (from
114
- * `ownerConfigPath` or the default location), and return the resolved content.
115
- *
116
- * @param {string} soulPath Absolute path to the soul.md template.
117
- * @param {{ ownerConfigPath?: string }} [opts]
118
- * @returns {{ resolved: string, warnings: string[], source: 'file'|'defaults'|'partial' }}
119
- */
120
- export function loadAndResolveSoul(soulPath, opts = {}) {
121
- const templateContent = readFileSync(soulPath, 'utf8');
122
-
123
- const { config, source } = loadOwnerConfig(
124
- opts.ownerConfigPath ? { path: opts.ownerConfigPath } : {},
125
- );
126
-
127
- const { resolved, warnings } = resolveSoul(templateContent, config);
128
-
129
- return { resolved, warnings, source };
130
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * render.mjs — Re-export barrel for vault-mirror render modules (Issue #283 split).
3
- *
4
- * Consumers can import from this file or directly from render-learnings.mjs / render-sessions.mjs.
5
- */
6
-
7
- export { detectLearningSchema, generateLearningNote, generateLearningNoteV2 } from './render-learnings.mjs';
8
- export { detectSessionSchema, generateSessionNote, generateSessionNoteV2, generateSessionNoteV3 } from './render-sessions.mjs';