@neuroverseos/governance 0.10.0 → 0.12.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 (95) hide show
  1. package/dist/adapters/autoresearch.cjs +19 -1
  2. package/dist/adapters/autoresearch.d.cts +1 -1
  3. package/dist/adapters/autoresearch.d.ts +1 -1
  4. package/dist/adapters/autoresearch.js +2 -2
  5. package/dist/adapters/deep-agents.cjs +19 -1
  6. package/dist/adapters/deep-agents.d.cts +2 -2
  7. package/dist/adapters/deep-agents.d.ts +2 -2
  8. package/dist/adapters/deep-agents.js +2 -2
  9. package/dist/adapters/express.cjs +19 -1
  10. package/dist/adapters/express.d.cts +1 -1
  11. package/dist/adapters/express.d.ts +1 -1
  12. package/dist/adapters/express.js +2 -2
  13. package/dist/adapters/github.cjs +19 -1
  14. package/dist/adapters/github.d.cts +2 -2
  15. package/dist/adapters/github.d.ts +2 -2
  16. package/dist/adapters/github.js +2 -2
  17. package/dist/adapters/index.cjs +19 -1
  18. package/dist/adapters/index.d.cts +2 -2
  19. package/dist/adapters/index.d.ts +2 -2
  20. package/dist/adapters/index.js +8 -8
  21. package/dist/adapters/langchain.cjs +19 -1
  22. package/dist/adapters/langchain.d.cts +2 -2
  23. package/dist/adapters/langchain.d.ts +2 -2
  24. package/dist/adapters/langchain.js +2 -2
  25. package/dist/adapters/mentraos.cjs +19 -1
  26. package/dist/adapters/mentraos.d.cts +2 -2
  27. package/dist/adapters/mentraos.d.ts +2 -2
  28. package/dist/adapters/mentraos.js +2 -2
  29. package/dist/adapters/openai.cjs +19 -1
  30. package/dist/adapters/openai.d.cts +2 -2
  31. package/dist/adapters/openai.d.ts +2 -2
  32. package/dist/adapters/openai.js +2 -2
  33. package/dist/adapters/openclaw.cjs +19 -1
  34. package/dist/adapters/openclaw.d.cts +2 -2
  35. package/dist/adapters/openclaw.d.ts +2 -2
  36. package/dist/adapters/openclaw.js +2 -2
  37. package/dist/admin/index.cjs +19 -1
  38. package/dist/admin/index.js +1 -1
  39. package/dist/audit-JYNN3MOQ.js +98 -0
  40. package/dist/audit-behavior-C62FdRAC.d.cts +100 -0
  41. package/dist/audit-behavior-DFy7LeYv.d.ts +100 -0
  42. package/dist/{behavioral-SPWPGYXL.js → behavioral-4TKMHZQZ.js} +2 -2
  43. package/dist/{chunk-OQU65525.js → chunk-24YW7BHC.js} +1 -1
  44. package/dist/{chunk-BZYQHJDM.js → chunk-2KTPIE57.js} +25 -5
  45. package/dist/{chunk-TJ5L2UTE.js → chunk-5K3LATTM.js} +1 -1
  46. package/dist/{chunk-HDNDL6D5.js → chunk-5LDBYOSJ.js} +1 -1
  47. package/dist/{chunk-FDPPZLSQ.js → chunk-5ZWKM7MO.js} +1 -1
  48. package/dist/{chunk-B3IIPTY3.js → chunk-6MB6TMAG.js} +1 -1
  49. package/dist/{chunk-IOVXB6QN.js → chunk-GXTAHCND.js} +1 -1
  50. package/dist/{chunk-FKQCPRKI.js → chunk-MAOIHKFO.js} +1 -1
  51. package/dist/{chunk-ZAF6JH23.js → chunk-MBOW6YXN.js} +19 -1
  52. package/dist/{chunk-A2UZTLRV.js → chunk-MLXKSX3L.js} +1 -1
  53. package/dist/{chunk-7FL3U7Z5.js → chunk-MWGEXHOD.js} +1 -1
  54. package/dist/{chunk-6CV4XG3J.js → chunk-QFDFAWZ6.js} +1 -1
  55. package/dist/{chunk-2VAWP6FI.js → chunk-RAS62JXV.js} +1 -1
  56. package/dist/{chunk-OTZU76DH.js → chunk-XAF3CYCW.js} +1 -1
  57. package/dist/{chunk-T6GMRZWC.js → chunk-XTYQCTDD.js} +1 -1
  58. package/dist/{chunk-TIXVEPS2.js → chunk-YN7OI5ZV.js} +1 -1
  59. package/dist/cli/neuroverse.cjs +229 -93
  60. package/dist/cli/neuroverse.js +16 -12
  61. package/dist/cli/plan.cjs +18 -0
  62. package/dist/cli/radiant.cjs +42 -4
  63. package/dist/cli/radiant.js +3 -3
  64. package/dist/cli/run.cjs +18 -0
  65. package/dist/cli/run.js +4 -4
  66. package/dist/{decision-flow-IJPNMVQK.js → decision-flow-5VI5YG6A.js} +2 -2
  67. package/dist/{demo-6W3YXLAX.js → demo-GYX6CYHC.js} +2 -2
  68. package/dist/engine/guard-engine.cjs +19 -1
  69. package/dist/engine/guard-engine.d.cts +21 -1
  70. package/dist/engine/guard-engine.d.ts +21 -1
  71. package/dist/engine/guard-engine.js +1 -1
  72. package/dist/{equity-penalties-CCO3GVHS.js → equity-penalties-NOM46NEO.js} +2 -2
  73. package/dist/{guard-IHJEKHL2.js → guard-PQ3SYV4Y.js} +3 -3
  74. package/dist/{guard-contract-ddiIPlOg.d.cts → guard-contract-Oznf-Kgq.d.cts} +32 -0
  75. package/dist/{guard-contract-q6HJAq3Q.d.ts → guard-contract-w_i_6gh-.d.ts} +32 -0
  76. package/dist/{impact-WIAM66IH.js → impact-LDJLTVRU.js} +3 -3
  77. package/dist/index.cjs +62 -1
  78. package/dist/index.d.cts +4 -3
  79. package/dist/index.d.ts +4 -3
  80. package/dist/index.js +49 -8
  81. package/dist/{mcp-server-CKYBHXWK.js → mcp-server-W3MWSKD7.js} +2 -2
  82. package/dist/{playground-3TTBN7XD.js → playground-SSZRNUAF.js} +1 -1
  83. package/dist/radiant/index.cjs +450 -5
  84. package/dist/radiant/index.d.cts +151 -1
  85. package/dist/radiant/index.d.ts +151 -1
  86. package/dist/radiant/index.js +405 -2
  87. package/dist/{redteam-W644UMWN.js → redteam-KCULS7EW.js} +1 -1
  88. package/dist/{server-EI5JCIBU.js → server-EGRGGSM2.js} +2 -2
  89. package/dist/{session-FMAROEIE.js → session-PZLTL22G.js} +2 -2
  90. package/dist/{shared-PpalGKxc.d.cts → shared-BC8mOpt0.d.cts} +1 -1
  91. package/dist/{shared-DAzdfWtU.d.ts → shared-CP63gNNW.d.ts} +1 -1
  92. package/dist/{test-XDB2DH3L.js → test-LIHGWHBA.js} +1 -1
  93. package/dist/{trace-2YDNAXMK.js → trace-DC3D7XPD.js} +2 -2
  94. package/package.json +1 -1
  95. /package/dist/{doctor-XEMLO6UA.js → doctor-SIWQGTAO.js} +0 -0
@@ -322,8 +322,26 @@ function isExternalScope(scope) {
322
322
  ];
323
323
  return !internalPatterns.some((p) => p.test(scope));
324
324
  }
325
- var MAX_INPUT_LENGTH = 1e5;
326
325
  function evaluateGuard(event, world, options = {}) {
326
+ const verdict = evaluateGuardCore(event, world, options);
327
+ return options.mode === "observe" ? toShadowVerdict(verdict) : verdict;
328
+ }
329
+ function toShadowVerdict(verdict) {
330
+ if (verdict.status === "ALLOW") return verdict;
331
+ return {
332
+ ...verdict,
333
+ status: "ALLOW",
334
+ shadowStatus: verdict.status,
335
+ shadowReason: verdict.reason,
336
+ // Preserve the original reason as shadowReason and wipe the
337
+ // top-level reason so callers that display `reason` for BLOCK/PAUSE
338
+ // don't accidentally surface an enforcement message.
339
+ reason: void 0,
340
+ warning: verdict.reason ? `Observe mode: would have ${verdict.status.toLowerCase()} \u2014 ${verdict.reason}` : `Observe mode: would have ${verdict.status.toLowerCase()}`
341
+ };
342
+ }
343
+ var MAX_INPUT_LENGTH = 1e5;
344
+ function evaluateGuardCore(event, world, options = {}) {
327
345
  const startTime = performance.now();
328
346
  const level = options.level ?? "standard";
329
347
  const includeTrace = options.trace ?? false;
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-GJ6LM4JZ.js";
4
4
  import {
5
5
  evaluateGuard
6
- } from "../chunk-ZAF6JH23.js";
6
+ } from "../chunk-MBOW6YXN.js";
7
7
  import "../chunk-QLPTHTVB.js";
8
8
  import "../chunk-QWGCMQQD.js";
9
9
 
@@ -0,0 +1,98 @@
1
+ import {
2
+ readStdin
3
+ } from "./chunk-BQZMOEML.js";
4
+ import {
5
+ resolveWorldPath
6
+ } from "./chunk-AKW5YVCE.js";
7
+ import {
8
+ loadWorld
9
+ } from "./chunk-I4RTIMLX.js";
10
+ import {
11
+ evaluateGuard
12
+ } from "./chunk-MBOW6YXN.js";
13
+ import "./chunk-QLPTHTVB.js";
14
+ import "./chunk-QWGCMQQD.js";
15
+
16
+ // src/cli/audit.ts
17
+ function parseArgs(argv) {
18
+ let worldPath = "";
19
+ let trace = false;
20
+ let level;
21
+ let multi = false;
22
+ let crossingsOnly = false;
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const a = argv[i];
25
+ if (a === "--world") worldPath = argv[++i] ?? "";
26
+ else if (a === "--trace") trace = true;
27
+ else if (a === "--level") {
28
+ const v = argv[++i];
29
+ if (v === "basic" || v === "standard" || v === "strict") level = v;
30
+ } else if (a === "--multi") multi = true;
31
+ else if (a === "--crossings-only") crossingsOnly = true;
32
+ }
33
+ return { worldPath, trace, level, multi, crossingsOnly };
34
+ }
35
+ function usage() {
36
+ process.stderr.write(
37
+ "Usage: neuroverse audit --world <path> [--trace] [--level basic|standard|strict] [--multi] [--crossings-only]\n\nReads GuardEvent JSON from stdin. With --multi, reads a JSON array.\nEvaluates in observe mode \u2014 no enforcement. Verdicts carry\nshadowStatus/shadowReason for any event that would have crossed.\n"
38
+ );
39
+ }
40
+ async function main(argv = process.argv.slice(2)) {
41
+ const args = parseArgs(argv);
42
+ if (!args.worldPath) {
43
+ usage();
44
+ process.exit(1);
45
+ }
46
+ let world;
47
+ try {
48
+ const resolved = resolveWorldPath(args.worldPath);
49
+ if (!resolved) {
50
+ process.stderr.write(`Failed to resolve world path: ${args.worldPath}
51
+ `);
52
+ process.exit(1);
53
+ }
54
+ world = await loadWorld(resolved);
55
+ } catch (err) {
56
+ process.stderr.write(`Failed to load world: ${err instanceof Error ? err.message : err}
57
+ `);
58
+ process.exit(1);
59
+ }
60
+ let raw = "";
61
+ try {
62
+ raw = await readStdin();
63
+ } catch (err) {
64
+ process.stderr.write(`Failed to read stdin: ${err instanceof Error ? err.message : err}
65
+ `);
66
+ process.exit(1);
67
+ }
68
+ if (!raw.trim()) {
69
+ process.stderr.write("No input on stdin. Pipe a GuardEvent or a JSON array with --multi.\n");
70
+ process.exit(1);
71
+ }
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(raw);
75
+ } catch (err) {
76
+ process.stderr.write(`Invalid JSON on stdin: ${err instanceof Error ? err.message : err}
77
+ `);
78
+ process.exit(1);
79
+ }
80
+ const options = { trace: args.trace, level: args.level, mode: "observe" };
81
+ if (args.multi) {
82
+ if (!Array.isArray(parsed)) {
83
+ process.stderr.write("--multi expects a JSON array on stdin.\n");
84
+ process.exit(1);
85
+ }
86
+ const verdicts = parsed.map(
87
+ (e) => evaluateGuard(e, world, options)
88
+ );
89
+ const out = args.crossingsOnly ? verdicts.filter((v) => v.shadowStatus && v.shadowStatus !== "ALLOW") : verdicts;
90
+ process.stdout.write(JSON.stringify(out, null, 2) + "\n");
91
+ return;
92
+ }
93
+ const verdict = evaluateGuard(parsed, world, options);
94
+ process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
95
+ }
96
+ export {
97
+ main
98
+ };
@@ -0,0 +1,100 @@
1
+ import { d as GuardStatus, G as GuardVerdict } from './guard-contract-Oznf-Kgq.cjs';
2
+ import { WorldDefinition } from './types.cjs';
3
+
4
+ /**
5
+ * @neuroverseos/governance — auditBehavior
6
+ *
7
+ * Takes an observed event (from the Radiant pipeline: a commit, a PR, a
8
+ * Slack message, a Notion edit) and evaluates it against a worldmodel in
9
+ * observe mode — without any enforcement side effects. Returns the shadow
10
+ * verdict so callers can record crossings of declared invariants.
11
+ *
12
+ * This is the primitive that lets Bevia / Radiant / Mirror-Mode tooling
13
+ * show leaders where their worldmodel is being bumped against, without
14
+ * imposing any stop/pause/modify semantics on the team's work.
15
+ *
16
+ * Relationship to evaluateGuard:
17
+ *
18
+ * evaluateGuard({ intent, ... }, world, { mode: 'enforce' })
19
+ * → what an AI agent receives when governance says "BLOCK this action"
20
+ *
21
+ * evaluateGuard({ intent, ... }, world, { mode: 'observe' })
22
+ * → what tooling like Bevia receives when governance says "this would
23
+ * have been blocked if enforced, but pass through and record"
24
+ *
25
+ * auditBehavior(event, world)
26
+ * → convenience on top of the observe path that (a) maps a
27
+ * behavioral event into a synthetic GuardEvent, (b) calls
28
+ * evaluateGuard in observe mode, and (c) returns a Crossing
29
+ * record shaped for behavioral logs.
30
+ *
31
+ * The mapping from behavioral events to GuardEvents is intentionally
32
+ * conservative: we use the event's `kind` as the tool, its `content` as
33
+ * the intent, and pass through timestamp + actor as metadata. Callers
34
+ * that want richer mappings (classifying event semantics into tool
35
+ * namespaces, etc.) can construct a GuardEvent directly and call
36
+ * evaluateGuard themselves.
37
+ */
38
+
39
+ /**
40
+ * Minimal shape an observed event needs to be auditable. Matches the
41
+ * Radiant `Event` type's relevant fields but doesn't require importing
42
+ * the full radiant domain module — keeps auditBehavior consumable by any
43
+ * adapter that emits events.
44
+ */
45
+ interface AuditableEvent {
46
+ /** Source-system-unique id (e.g. "github-push-abc123", "slack-msg-789"). */
47
+ id: string;
48
+ /** ISO 8601. */
49
+ timestamp: string;
50
+ /** Free-form kind tag from the adapter — 'commit', 'pr_opened', 'chat_message', etc. */
51
+ kind?: string;
52
+ /** Textual content of the event — commit message, PR body, chat text, etc. */
53
+ content?: string;
54
+ /** Actor id that produced the event. */
55
+ actorId?: string;
56
+ /** Actor kind — 'human' | 'ai' | 'bot' | 'unknown'. */
57
+ actorKind?: string;
58
+ /** Optional repo / channel / page reference, passed through as GuardEvent.scope. */
59
+ scope?: string;
60
+ }
61
+ /**
62
+ * A single crossing record — an observed event that would have triggered
63
+ * a non-ALLOW verdict if the world were running in enforce mode.
64
+ *
65
+ * When `wouldHaveBlocked` is `false`, the event passed all layers cleanly
66
+ * and no crossing occurred. Crossing records are most useful when
67
+ * `wouldHaveBlocked` is `true` — that's a moment the leader said they
68
+ * cared about, and here's evidence their team bumped into it.
69
+ */
70
+ interface Crossing {
71
+ eventId: string;
72
+ timestamp: string;
73
+ kind?: string;
74
+ actorId?: string;
75
+ /** The status the engine would have returned in enforce mode. */
76
+ shadowStatus: GuardStatus;
77
+ /** Human-readable reason the shadow verdict fired. */
78
+ shadowReason?: string;
79
+ /** Rule or guard id that produced the shadow verdict. */
80
+ ruleId?: string;
81
+ /** Shortened quote of the event content — useful for a crossings panel. */
82
+ excerpt?: string;
83
+ /** True when the engine would have blocked/paused/etc. in enforce mode. */
84
+ wouldHaveBlocked: boolean;
85
+ /** Full verdict in case callers want the complete object. */
86
+ verdict: GuardVerdict;
87
+ }
88
+ /**
89
+ * Evaluate a single behavioral event against a world in observe mode.
90
+ */
91
+ declare function auditBehavior(event: AuditableEvent, world: WorldDefinition): Crossing;
92
+ /**
93
+ * Convenience: audit a whole stream of events. Returns one Crossing per
94
+ * event; the caller can filter `wouldHaveBlocked` to get only the
95
+ * interesting ones. Deterministic — same events + same world = same
96
+ * crossings, every time.
97
+ */
98
+ declare function auditBehaviors(events: AuditableEvent[], world: WorldDefinition): Crossing[];
99
+
100
+ export { type AuditableEvent as A, type Crossing as C, auditBehavior as a, auditBehaviors as b };
@@ -0,0 +1,100 @@
1
+ import { d as GuardStatus, G as GuardVerdict } from './guard-contract-w_i_6gh-.js';
2
+ import { WorldDefinition } from './types.js';
3
+
4
+ /**
5
+ * @neuroverseos/governance — auditBehavior
6
+ *
7
+ * Takes an observed event (from the Radiant pipeline: a commit, a PR, a
8
+ * Slack message, a Notion edit) and evaluates it against a worldmodel in
9
+ * observe mode — without any enforcement side effects. Returns the shadow
10
+ * verdict so callers can record crossings of declared invariants.
11
+ *
12
+ * This is the primitive that lets Bevia / Radiant / Mirror-Mode tooling
13
+ * show leaders where their worldmodel is being bumped against, without
14
+ * imposing any stop/pause/modify semantics on the team's work.
15
+ *
16
+ * Relationship to evaluateGuard:
17
+ *
18
+ * evaluateGuard({ intent, ... }, world, { mode: 'enforce' })
19
+ * → what an AI agent receives when governance says "BLOCK this action"
20
+ *
21
+ * evaluateGuard({ intent, ... }, world, { mode: 'observe' })
22
+ * → what tooling like Bevia receives when governance says "this would
23
+ * have been blocked if enforced, but pass through and record"
24
+ *
25
+ * auditBehavior(event, world)
26
+ * → convenience on top of the observe path that (a) maps a
27
+ * behavioral event into a synthetic GuardEvent, (b) calls
28
+ * evaluateGuard in observe mode, and (c) returns a Crossing
29
+ * record shaped for behavioral logs.
30
+ *
31
+ * The mapping from behavioral events to GuardEvents is intentionally
32
+ * conservative: we use the event's `kind` as the tool, its `content` as
33
+ * the intent, and pass through timestamp + actor as metadata. Callers
34
+ * that want richer mappings (classifying event semantics into tool
35
+ * namespaces, etc.) can construct a GuardEvent directly and call
36
+ * evaluateGuard themselves.
37
+ */
38
+
39
+ /**
40
+ * Minimal shape an observed event needs to be auditable. Matches the
41
+ * Radiant `Event` type's relevant fields but doesn't require importing
42
+ * the full radiant domain module — keeps auditBehavior consumable by any
43
+ * adapter that emits events.
44
+ */
45
+ interface AuditableEvent {
46
+ /** Source-system-unique id (e.g. "github-push-abc123", "slack-msg-789"). */
47
+ id: string;
48
+ /** ISO 8601. */
49
+ timestamp: string;
50
+ /** Free-form kind tag from the adapter — 'commit', 'pr_opened', 'chat_message', etc. */
51
+ kind?: string;
52
+ /** Textual content of the event — commit message, PR body, chat text, etc. */
53
+ content?: string;
54
+ /** Actor id that produced the event. */
55
+ actorId?: string;
56
+ /** Actor kind — 'human' | 'ai' | 'bot' | 'unknown'. */
57
+ actorKind?: string;
58
+ /** Optional repo / channel / page reference, passed through as GuardEvent.scope. */
59
+ scope?: string;
60
+ }
61
+ /**
62
+ * A single crossing record — an observed event that would have triggered
63
+ * a non-ALLOW verdict if the world were running in enforce mode.
64
+ *
65
+ * When `wouldHaveBlocked` is `false`, the event passed all layers cleanly
66
+ * and no crossing occurred. Crossing records are most useful when
67
+ * `wouldHaveBlocked` is `true` — that's a moment the leader said they
68
+ * cared about, and here's evidence their team bumped into it.
69
+ */
70
+ interface Crossing {
71
+ eventId: string;
72
+ timestamp: string;
73
+ kind?: string;
74
+ actorId?: string;
75
+ /** The status the engine would have returned in enforce mode. */
76
+ shadowStatus: GuardStatus;
77
+ /** Human-readable reason the shadow verdict fired. */
78
+ shadowReason?: string;
79
+ /** Rule or guard id that produced the shadow verdict. */
80
+ ruleId?: string;
81
+ /** Shortened quote of the event content — useful for a crossings panel. */
82
+ excerpt?: string;
83
+ /** True when the engine would have blocked/paused/etc. in enforce mode. */
84
+ wouldHaveBlocked: boolean;
85
+ /** Full verdict in case callers want the complete object. */
86
+ verdict: GuardVerdict;
87
+ }
88
+ /**
89
+ * Evaluate a single behavioral event against a world in observe mode.
90
+ */
91
+ declare function auditBehavior(event: AuditableEvent, world: WorldDefinition): Crossing;
92
+ /**
93
+ * Convenience: audit a whole stream of events. Returns one Crossing per
94
+ * event; the caller can filter `wouldHaveBlocked` to get only the
95
+ * interesting ones. Deterministic — same events + same world = same
96
+ * crossings, every time.
97
+ */
98
+ declare function auditBehaviors(events: AuditableEvent[], world: WorldDefinition): Crossing[];
99
+
100
+ export { type AuditableEvent as A, type Crossing as C, auditBehavior as a, auditBehaviors as b };
@@ -5,8 +5,8 @@ import {
5
5
  } from "./chunk-CNSO6XW5.js";
6
6
  import {
7
7
  readAuditLog
8
- } from "./chunk-2VAWP6FI.js";
9
- import "./chunk-ZAF6JH23.js";
8
+ } from "./chunk-RAS62JXV.js";
9
+ import "./chunk-MBOW6YXN.js";
10
10
  import "./chunk-QLPTHTVB.js";
11
11
  import "./chunk-QWGCMQQD.js";
12
12
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readAuditLog
3
- } from "./chunk-2VAWP6FI.js";
3
+ } from "./chunk-RAS62JXV.js";
4
4
 
5
5
  // src/engine/impact-report.ts
6
6
  function generateImpactReport(events) {
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-I4RTIMLX.js";
7
7
  import {
8
8
  evaluateGuard
9
- } from "./chunk-ZAF6JH23.js";
9
+ } from "./chunk-MBOW6YXN.js";
10
10
 
11
11
  // src/radiant/core/compress.ts
12
12
  function compressWorldmodel(content) {
@@ -1830,6 +1830,7 @@ async function auditGovernance(events, worldPath) {
1830
1830
  return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
1831
1831
  }
1832
1832
  const verdicts = [];
1833
+ const crossings = [];
1833
1834
  for (const ce of events) {
1834
1835
  const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
1835
1836
  const scope = ce.event.metadata?.scope || void 0;
@@ -1840,16 +1841,32 @@ async function auditGovernance(events, worldPath) {
1840
1841
  scope,
1841
1842
  actionCategory: mapKindToCategory(ce.event.kind)
1842
1843
  },
1843
- world
1844
+ world,
1845
+ { mode: "observe" }
1844
1846
  );
1847
+ const shadow = result.shadowStatus ?? "ALLOW";
1845
1848
  verdicts.push({
1846
1849
  eventId: ce.event.id,
1847
1850
  domain: ce.domain,
1848
- status: result.status,
1849
- reason: result.reason,
1851
+ status: shadow,
1852
+ reason: result.shadowReason,
1850
1853
  ruleId: result.ruleId,
1851
1854
  warning: result.warning
1852
1855
  });
1856
+ if (shadow !== "ALLOW") {
1857
+ crossings.push({
1858
+ eventId: ce.event.id,
1859
+ timestamp: ce.event.timestamp,
1860
+ kind: ce.event.kind,
1861
+ actorId: ce.event.actor.id,
1862
+ shadowStatus: shadow,
1863
+ shadowReason: result.shadowReason,
1864
+ ruleId: result.ruleId,
1865
+ excerpt: intent.length > 280 ? intent.slice(0, 279) + "\u2026" : intent,
1866
+ wouldHaveBlocked: true,
1867
+ verdict: result
1868
+ });
1869
+ }
1853
1870
  } catch {
1854
1871
  verdicts.push({
1855
1872
  eventId: ce.event.id,
@@ -1868,6 +1885,7 @@ async function auditGovernance(events, worldPath) {
1868
1885
  human,
1869
1886
  cyber,
1870
1887
  joint,
1888
+ crossings,
1871
1889
  summary
1872
1890
  };
1873
1891
  }
@@ -1923,6 +1941,7 @@ function emptyAudit(total, reason) {
1923
1941
  human: { allow: 0, modify: 0, block: 0, details: [] },
1924
1942
  cyber: { allow: 0, modify: 0, block: 0, details: [] },
1925
1943
  joint: { allow: 0, modify: 0, block: 0, details: [] },
1944
+ crossings: [],
1926
1945
  summary: reason
1927
1946
  };
1928
1947
  }
@@ -2899,7 +2918,8 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
2899
2918
  scores,
2900
2919
  eventCount: events.length,
2901
2920
  activeAdapters,
2902
- worldStack
2921
+ worldStack,
2922
+ governance
2903
2923
  };
2904
2924
  }
2905
2925
  function filterEventsByUser(events, username) {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-I4RTIMLX.js";
4
4
  import {
5
5
  evaluateGuard
6
- } from "./chunk-ZAF6JH23.js";
6
+ } from "./chunk-MBOW6YXN.js";
7
7
 
8
8
  // src/adapters/autoresearch.ts
9
9
  var AutoresearchGovernor = class {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-I4RTIMLX.js";
4
4
  import {
5
5
  evaluateGuard
6
- } from "./chunk-ZAF6JH23.js";
6
+ } from "./chunk-MBOW6YXN.js";
7
7
 
8
8
  // src/adapters/express.ts
9
9
  function methodToCategory(method) {
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-I4RTIMLX.js";
8
8
  import {
9
9
  evaluateGuard
10
- } from "./chunk-ZAF6JH23.js";
10
+ } from "./chunk-MBOW6YXN.js";
11
11
  import {
12
12
  advancePlan,
13
13
  evaluatePlan,
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-I4RTIMLX.js";
11
11
  import {
12
12
  evaluateGuard
13
- } from "./chunk-ZAF6JH23.js";
13
+ } from "./chunk-MBOW6YXN.js";
14
14
 
15
15
  // src/adapters/openai.ts
16
16
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-I4RTIMLX.js";
13
13
  import {
14
14
  evaluateGuard
15
- } from "./chunk-ZAF6JH23.js";
15
+ } from "./chunk-MBOW6YXN.js";
16
16
 
17
17
  // src/adapters/mentraos.ts
18
18
  var DEFAULT_USER_RULES = {
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-I4RTIMLX.js";
10
10
  import {
11
11
  evaluateGuard
12
- } from "./chunk-ZAF6JH23.js";
12
+ } from "./chunk-MBOW6YXN.js";
13
13
 
14
14
  // src/adapters/langchain.ts
15
15
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {
@@ -89,8 +89,26 @@ function isExternalScope(scope) {
89
89
  ];
90
90
  return !internalPatterns.some((p) => p.test(scope));
91
91
  }
92
- var MAX_INPUT_LENGTH = 1e5;
93
92
  function evaluateGuard(event, world, options = {}) {
93
+ const verdict = evaluateGuardCore(event, world, options);
94
+ return options.mode === "observe" ? toShadowVerdict(verdict) : verdict;
95
+ }
96
+ function toShadowVerdict(verdict) {
97
+ if (verdict.status === "ALLOW") return verdict;
98
+ return {
99
+ ...verdict,
100
+ status: "ALLOW",
101
+ shadowStatus: verdict.status,
102
+ shadowReason: verdict.reason,
103
+ // Preserve the original reason as shadowReason and wipe the
104
+ // top-level reason so callers that display `reason` for BLOCK/PAUSE
105
+ // don't accidentally surface an enforcement message.
106
+ reason: void 0,
107
+ warning: verdict.reason ? `Observe mode: would have ${verdict.status.toLowerCase()} \u2014 ${verdict.reason}` : `Observe mode: would have ${verdict.status.toLowerCase()}`
108
+ };
109
+ }
110
+ var MAX_INPUT_LENGTH = 1e5;
111
+ function evaluateGuardCore(event, world, options = {}) {
94
112
  const startTime = performance.now();
95
113
  const level = options.level ?? "standard";
96
114
  const includeTrace = options.trace ?? false;
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-I4RTIMLX.js";
9
9
  import {
10
10
  evaluateGuard
11
- } from "./chunk-ZAF6JH23.js";
11
+ } from "./chunk-MBOW6YXN.js";
12
12
 
13
13
  // src/adapters/github.ts
14
14
  var GitHubGovernanceBlockedError = class extends GovernanceBlockedError {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-I4RTIMLX.js";
4
4
  import {
5
5
  evaluateGuard
6
- } from "./chunk-ZAF6JH23.js";
6
+ } from "./chunk-MBOW6YXN.js";
7
7
 
8
8
  // src/runtime/govern.ts
9
9
  function actionToGuardEvent(action) {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-INWQHLPS.js";
4
4
  import {
5
5
  evaluateGuard
6
- } from "./chunk-ZAF6JH23.js";
6
+ } from "./chunk-MBOW6YXN.js";
7
7
 
8
8
  // src/engine/intent-classifier.ts
9
9
  function buildSystemPrompt(knownIntents) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  evaluateGuard
3
- } from "./chunk-ZAF6JH23.js";
3
+ } from "./chunk-MBOW6YXN.js";
4
4
 
5
5
  // src/engine/audit-logger.ts
6
6
  var FileAuditLogger = class {
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-I4RTIMLX.js";
10
10
  import {
11
11
  evaluateGuard
12
- } from "./chunk-ZAF6JH23.js";
12
+ } from "./chunk-MBOW6YXN.js";
13
13
  import {
14
14
  advancePlan,
15
15
  evaluatePlan,
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-I4RTIMLX.js";
10
10
  import {
11
11
  evaluateGuard
12
- } from "./chunk-ZAF6JH23.js";
12
+ } from "./chunk-MBOW6YXN.js";
13
13
 
14
14
  // src/engine/tool-classifier.ts
15
15
  var TOOL_CATEGORY_MAP = {
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-I4RTIMLX.js";
10
10
  import {
11
11
  evaluateGuard
12
- } from "./chunk-ZAF6JH23.js";
12
+ } from "./chunk-MBOW6YXN.js";
13
13
 
14
14
  // src/adapters/openclaw.ts
15
15
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {