session-orchestrator 5.9.0 → 5.11.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 (78) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.cursor-plugin/plugin.json +1 -1
  5. package/AGENTS.md +2 -0
  6. package/CHANGELOG.md +65 -2
  7. package/README.md +11 -9
  8. package/SECURITY.md +1 -1
  9. package/agents/code-implementer.md +7 -1
  10. package/docs/USER-GUIDE.md +2 -0
  11. package/docs/agent-authoring.md +2 -0
  12. package/docs/ci-setup.md +46 -1
  13. package/docs/events-schema.md +37 -6
  14. package/docs/fleet-checkin-audit.md +172 -0
  15. package/docs/owner-config-schema.md +18 -1
  16. package/docs/owner-privacy-patterns.md +85 -0
  17. package/docs/role-profile-contract.md +139 -0
  18. package/docs/scope-collision-guard.md +15 -2
  19. package/docs/session-config-reference.md +1 -1
  20. package/evals/instruction-ablation/run.mjs +11 -6
  21. package/hooks/_lib/hook-import-set.json +27 -2
  22. package/hooks/_lib/orchestrator-ignore.mjs +112 -0
  23. package/hooks/enforce-commands.mjs +9 -19
  24. package/hooks/enforce-scope.mjs +23 -42
  25. package/hooks/hooks-codex.json +1 -1
  26. package/hooks/hooks.json +1 -1
  27. package/hooks/on-session-end.mjs +8 -1
  28. package/hooks/on-session-start.mjs +7 -0
  29. package/hooks/post-bash-write-verify.mjs +54 -24
  30. package/hooks/pre-task-scope-disjoint.mjs +12 -0
  31. package/hooks/subagent-telemetry.mjs +8 -3
  32. package/hooks/wave-scope-commit-guard.mjs +4 -1
  33. package/package.json +2 -2
  34. package/rules/opt-in-stack/security-web.md +1 -1
  35. package/scripts/emit-session.mjs +28 -0
  36. package/scripts/fleet-checkin-audit.mjs +138 -0
  37. package/scripts/lib/common.mjs +2 -4
  38. package/scripts/lib/context-overhead-format.mjs +57 -0
  39. package/scripts/lib/fleet-checkin-audit.mjs +244 -0
  40. package/scripts/lib/gates/gate-full.mjs +6 -0
  41. package/scripts/lib/gates/gate-helpers.mjs +2 -0
  42. package/scripts/lib/memory-proposals/sink.mjs +79 -17
  43. package/scripts/lib/memory-proposals/store.mjs +245 -9
  44. package/scripts/lib/named-vault-resolver.mjs +1 -1
  45. package/scripts/lib/owner-yaml.mjs +33 -3
  46. package/scripts/lib/platform.mjs +70 -1
  47. package/scripts/lib/pre-push-remote-gate.mjs +107 -0
  48. package/scripts/lib/project-hygiene.mjs +37 -0
  49. package/scripts/lib/quality-gate.mjs +6 -1
  50. package/scripts/lib/redact-spans.mjs +8 -17
  51. package/scripts/lib/role-profile/schema.mjs +219 -0
  52. package/scripts/lib/scope-gate.mjs +68 -5
  53. package/scripts/lib/session-lock.mjs +57 -10
  54. package/scripts/lib/session-record-repair.mjs +63 -30
  55. package/scripts/lib/session-schema/constants.mjs +8 -0
  56. package/scripts/lib/session-schema/validator.mjs +33 -0
  57. package/scripts/lib/subagents-schema.mjs +9 -0
  58. package/scripts/lib/telemetry/pricing.mjs +11 -0
  59. package/scripts/lib/validate/check-owner-leakage.mjs +198 -1015
  60. package/scripts/lib/vault-backfill/template.mjs +1 -1
  61. package/scripts/lib/vault-mirror/render-sessions.mjs +15 -3
  62. package/scripts/lib/vault-status/board-writer.mjs +15 -7
  63. package/scripts/measure-context-overhead.sh +4 -21
  64. package/scripts/migrate-vault-paths.mjs +57 -60
  65. package/scripts/release.mjs +463 -48
  66. package/scripts/run-quality-gate.mjs +47 -0
  67. package/scripts/validate-wave-scope.mjs +59 -6
  68. package/scripts/vault-consolidate.mjs +19 -4
  69. package/skills/claude-md-drift-check/SKILL.md +1 -1
  70. package/skills/claude-md-drift-check/checker.mjs +22 -9
  71. package/skills/npm-publish/SKILL.md +3 -3
  72. package/skills/release/SKILL.md +2 -2
  73. package/skills/repo-audit/SKILL.md +1 -1
  74. package/skills/session-end/metrics-collection.md +28 -4
  75. package/skills/session-end/session-metrics-write.md +1 -1
  76. package/skills/session-start/references/phase-1-2-session-lock.md +1 -1
  77. package/skills/wave-executor/circuit-breaker.md +1 -0
  78. package/skills/wave-executor/references/wave-loop-review.md +26 -2
@@ -26,6 +26,17 @@ import {
26
26
  /** Valid values for the optional `expected_cost_tier` field (ADR-364). */
27
27
  const EXPECTED_COST_TIERS = Object.freeze(['quick', 'standard', 'deep']);
28
28
 
29
+ /**
30
+ * Valid values for the optional `cost_basis` field (#1470 Pkt 4). Must contain
31
+ * `COST_BASIS` from scripts/lib/telemetry/pricing.mjs — the value emit-session
32
+ * writes beside `total_cost_usd`. There is deliberately no payment value: no
33
+ * writer can see what was actually billed.
34
+ */
35
+ const COST_BASES = Object.freeze(['api-list-equivalent']);
36
+
37
+ /** `pricing_table_date` (#1470 Pkt 6): a calendar date, `YYYY-MM-DD`. */
38
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
39
+
29
40
  /**
30
41
  * Valid values for the optional `status` field (Epic #724 C1).
31
42
  * `completed` — record written by a normal /close flow.
@@ -456,6 +467,28 @@ function _validateOptionalFields(entry) {
456
467
  );
457
468
  }
458
469
 
470
+ // #1470 Pkt 4/6 — what the cost figure is and which price table produced it.
471
+ if (entry.cost_basis !== undefined && entry.cost_basis !== null) {
472
+ if (!COST_BASES.includes(entry.cost_basis)) {
473
+ throw new ValidationError(
474
+ `cost_basis must be one of ${COST_BASES.join('|')} or null, got: ${entry.cost_basis}`
475
+ );
476
+ }
477
+ }
478
+ if (entry.pricing_table_date !== undefined && entry.pricing_table_date !== null) {
479
+ if (
480
+ typeof entry.pricing_table_date !== 'string' ||
481
+ !ISO_DATE_RE.test(entry.pricing_table_date) ||
482
+ // Round-trip, not Date.parse alone: V8 rolls 2026-02-30 over to March.
483
+ Number.isNaN(Date.parse(`${entry.pricing_table_date}T00:00:00Z`)) ||
484
+ new Date(`${entry.pricing_table_date}T00:00:00Z`).toISOString().slice(0, 10) !== entry.pricing_table_date
485
+ ) {
486
+ throw new ValidationError(
487
+ `pricing_table_date must be an ISO date (YYYY-MM-DD) or null, got: ${entry.pricing_table_date}`
488
+ );
489
+ }
490
+ }
491
+
459
492
  // Epic #724 C1 — SessionEnd close-through backfill provenance fields.
460
493
  // All additive-optional; null/absent passes without further checks so that
461
494
  // pre-#724 records (and every normally-closed record) validate cleanly.
@@ -55,6 +55,8 @@
55
55
  * total_cost_usd number | null — native total cost in USD (#624, fractional,
56
56
  * best-effort: null when the harness does not
57
57
  * expose it; no rate table is applied)
58
+ * cost_basis 'api-list-equivalent' | null — explicitly supplied cost
59
+ * provenance; null means unknown (#1543)
58
60
  *
59
61
  * OTel aliases (optional, stop-only, additive — #411, schema_version=1 backwards-compat):
60
62
  * gen_ai.usage.input_tokens integer | null — RAW UNCACHED prompt tokens (OTel
@@ -69,6 +71,7 @@
69
71
  import { readFile, appendFile, mkdir } from 'node:fs/promises';
70
72
  import { existsSync } from 'node:fs';
71
73
  import path from 'node:path';
74
+ import { COST_BASIS } from './telemetry/pricing.mjs';
72
75
 
73
76
  // ---------------------------------------------------------------------------
74
77
  // Constants
@@ -267,6 +270,11 @@ export function validateSubagent(entry, options = {}) {
267
270
  }
268
271
  }
269
272
 
273
+ // #1543 additive: never infer provenance from a native dollar value.
274
+ if (entry.cost_basis !== undefined && entry.cost_basis !== null && entry.cost_basis !== COST_BASIS) {
275
+ throw new ValidationError(`cost_basis must be ${COST_BASIS} or null`, 'cost_basis');
276
+ }
277
+
270
278
  // OTel alias — #411 additive, schema_version=1 backwards-compat
271
279
  const otelInputTokens = entry['gen_ai.usage.input_tokens'];
272
280
  if (otelInputTokens !== undefined && otelInputTokens !== null) {
@@ -334,6 +342,7 @@ export function normalizeSubagent(entry) {
334
342
  model: entry.model ?? null,
335
343
  // total_cost_usd — #624 additive, best-effort native cost (null when absent)
336
344
  total_cost_usd: entry.total_cost_usd ?? null,
345
+ cost_basis: entry.cost_basis ?? null,
337
346
  // OTel alias — #411 additive, schema_version=1 backwards-compat
338
347
  'gen_ai.usage.input_tokens': entry['gen_ai.usage.input_tokens'] ?? null,
339
348
  'gen_ai.usage.cache_read_input_tokens': entry['gen_ai.usage.cache_read_input_tokens'] ?? null,
@@ -62,6 +62,17 @@
62
62
  */
63
63
  export const PRICING_TABLE_DATE = '2026-09-29';
64
64
 
65
+ /**
66
+ * What a dollar figure computed from this table IS (#1470 Pkt 4): the API
67
+ * list-price equivalent of the metered tokens — never a payment. Subscription
68
+ * quota, purchased credits and what was actually billed are not visible to
69
+ * this module, so a consumer must not present the figure as any of them.
70
+ * Written beside every persisted cost as `cost_basis`; the session validator's
71
+ * `COST_BASES` must contain it (pinned by tests/scripts/emit-session.test.mjs).
72
+ * @type {'api-list-equivalent'}
73
+ */
74
+ export const COST_BASIS = 'api-list-equivalent';
75
+
65
76
  /**
66
77
  * @typedef {Object} PricingRow
67
78
  * @property {number} input - USD per 1M uncached prompt tokens.