@neuroverseos/governance 0.4.3 → 0.5.1

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 (68) hide show
  1. package/README.md +189 -0
  2. package/dist/adapters/autoresearch.js +2 -2
  3. package/dist/adapters/deep-agents.js +2 -2
  4. package/dist/adapters/express.js +2 -2
  5. package/dist/adapters/github.js +2 -2
  6. package/dist/adapters/index.js +23 -21
  7. package/dist/adapters/langchain.js +2 -2
  8. package/dist/adapters/mentraos.js +8 -6
  9. package/dist/adapters/openai.js +2 -2
  10. package/dist/adapters/openclaw.js +2 -2
  11. package/dist/{add-XSANI3FK.js → add-JP7TC2K3.js} +1 -1
  12. package/dist/admin/index.cjs +2214 -0
  13. package/dist/admin/index.d.cts +362 -0
  14. package/dist/admin/index.d.ts +362 -0
  15. package/dist/admin/index.js +703 -0
  16. package/dist/{build-EGBGZFIJ.js → build-THUEYMVT.js} +5 -5
  17. package/dist/{chunk-YJ34R5NB.js → chunk-5RAQ5DZW.js} +3 -3
  18. package/dist/{chunk-RDA7ISWC.js → chunk-6UPEUMJ2.js} +3 -3
  19. package/dist/chunk-7UU7V3AD.js +447 -0
  20. package/dist/{chunk-ZEIT2QLM.js → chunk-EK77AJAH.js} +22 -4
  21. package/dist/{chunk-3S5AD4AB.js → chunk-FGOSKQDE.js} +3 -3
  22. package/dist/{chunk-GTPV2XGO.js → chunk-GJ6LM4JZ.js} +1 -441
  23. package/dist/chunk-H3REGQRI.js +107 -0
  24. package/dist/{chunk-J2IZBHXJ.js → chunk-LAKUB76X.js} +3 -3
  25. package/dist/{chunk-FVOGUCB6.js → chunk-R23T5SZG.js} +3 -3
  26. package/dist/{chunk-A7SHG75T.js → chunk-RF2L5SYG.js} +3 -3
  27. package/dist/{chunk-QMVQ6KPL.js → chunk-TL4DLMMW.js} +3 -3
  28. package/dist/{chunk-AV7XJJWK.js → chunk-TZBERHFM.js} +3 -3
  29. package/dist/{chunk-3AYKQHYI.js → chunk-UZBW44KD.js} +3 -3
  30. package/dist/{chunk-FS2UUJJO.js → chunk-XPMZB46F.js} +3 -3
  31. package/dist/cli/neuroverse.cjs +962 -284
  32. package/dist/cli/neuroverse.js +46 -22
  33. package/dist/cli/plan.js +1 -1
  34. package/dist/cli/run.cjs +242 -139
  35. package/dist/cli/run.js +23 -3
  36. package/dist/{demo-6OQYWRR6.js → demo-N5K4VXJW.js} +3 -3
  37. package/dist/{derive-7Y7YWVLU.js → derive-5LOMN7GO.js} +4 -4
  38. package/dist/{equity-penalties-NVBAB5WL.js → equity-penalties-PYCJ3Q4U.js} +6 -6
  39. package/dist/{explain-HDFN4ION.js → explain-42TVC3QD.js} +1 -1
  40. package/dist/{guard-6KSCWT2W.js → guard-TPYDFG6V.js} +16 -4
  41. package/dist/{improve-2PWGGO5B.js → improve-HLZGJ54Z.js} +3 -3
  42. package/dist/index.cjs +19 -1
  43. package/dist/index.d.cts +2 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +27 -27
  46. package/dist/keygen-BSZH3NM2.js +77 -0
  47. package/dist/{lens-MHMUDCMQ.js → lens-NFGZHD76.js} +1 -1
  48. package/dist/{mcp-server-TNIWZ7B5.js → mcp-server-5XXNG6VC.js} +2 -2
  49. package/dist/migrate-NH5PVMX4.js +221 -0
  50. package/dist/{playground-3FLDGBET.js → playground-2EU5CFIH.js} +4 -4
  51. package/dist/{redteam-HV6LMKEH.js → redteam-VK6OVHAE.js} +3 -3
  52. package/dist/{session-XZP2754M.js → session-NGA4DUPL.js} +2 -2
  53. package/dist/sign-RRELHKWM.js +11 -0
  54. package/dist/{simulate-VT437EEL.js → simulate-4YNOBMES.js} +1 -1
  55. package/dist/{test-4WTX6RKQ.js → test-HDBPMQTG.js} +3 -3
  56. package/dist/{validate-M52DX22Y.js → validate-6MFQZ2EG.js} +1 -1
  57. package/dist/verify-6AVTWX75.js +151 -0
  58. package/dist/{world-O4HTQPDP.js → world-H5WVURKU.js} +1 -1
  59. package/dist/{world-loader-YTYFOP7D.js → world-loader-J47PCPDZ.js} +1 -1
  60. package/package.json +22 -10
  61. package/dist/{behavioral-SLW7ALEK.js → behavioral-SPWPGYXL.js} +3 -3
  62. package/dist/{bootstrap-2OW5ZLBL.js → bootstrap-IP5QMC3Q.js} +3 -3
  63. package/dist/{chunk-I4RTIMLX.js → chunk-EQUAWNXW.js} +0 -0
  64. package/dist/{chunk-DA5MHFRR.js → chunk-NTHXZAW4.js} +3 -3
  65. package/dist/{chunk-FHXXD2TI.js → chunk-QZ666FCV.js} +6 -6
  66. package/dist/{configure-ai-LL3VAPQW.js → configure-ai-5MP5DWTT.js} +3 -3
  67. package/dist/{decision-flow-3K4D72G4.js → decision-flow-IJPNMVQK.js} +3 -3
  68. /package/dist/{doctor-EC5OYTI3.js → doctor-Q5APJOTS.js} +0 -0
@@ -1,14 +1,3 @@
1
- import {
2
- buildEngineOptions,
3
- trackPlanProgress
4
- } from "./chunk-5U2MQO5P.js";
5
- import {
6
- evaluateGuard
7
- } from "./chunk-ZAF6JH23.js";
8
- import {
9
- loadWorld
10
- } from "./chunk-I4RTIMLX.js";
11
-
12
1
  // src/worlds/mentraos-intent-taxonomy.ts
13
2
  var MENTRA_INTENT_TAXONOMY = [
14
3
  // ── Camera Domain ───────────────────────────────────────────────────────
@@ -447,430 +436,6 @@ function isAIIntent(intent) {
447
436
  return def ? def.domain === "ai_data" || def.domain === "ai_action" : false;
448
437
  }
449
438
 
450
- // src/adapters/mentraos.ts
451
- var DEFAULT_USER_RULES = {
452
- aiDataPolicy: "declared_only",
453
- aiActionPolicy: "confirm_all",
454
- aiPurchasePolicy: "confirm_each",
455
- aiMessagingPolicy: "confirm_each",
456
- dataRetentionPolicy: "app_declared",
457
- maxAIProviders: 5
458
- };
459
- function evaluateUserRules(intent, rules, appContext) {
460
- const def = getMentraIntent(intent);
461
- if (!def) return null;
462
- if (def.domain === "ai_data" && intent !== "ai_retain_session_data") {
463
- if (rules.aiDataPolicy === "block_all") {
464
- return {
465
- verdict: {
466
- status: "BLOCK",
467
- ruleId: "user-rule-ai-data-block",
468
- reason: `User rules block all AI data sends. Intent: ${intent}`,
469
- evidence: makeEvidence("user-rule-ai-data-block")
470
- },
471
- reason: "User has blocked all AI data sends"
472
- };
473
- }
474
- if (rules.aiDataPolicy === "confirm_each") {
475
- return {
476
- verdict: {
477
- status: "PAUSE",
478
- ruleId: "user-rule-ai-data-confirm",
479
- reason: `User rules require confirmation for every AI data send. Intent: ${intent}`,
480
- evidence: makeEvidence("user-rule-ai-data-confirm")
481
- },
482
- reason: "User requires confirmation for each AI data send"
483
- };
484
- }
485
- if (!appContext.aiProviderDeclared) {
486
- return {
487
- verdict: {
488
- status: "BLOCK",
489
- ruleId: "user-rule-undeclared-provider",
490
- reason: `App "${appContext.appId}" has not declared its AI provider. User rules require declared providers only.`,
491
- evidence: makeEvidence("user-rule-undeclared-provider")
492
- },
493
- reason: "App has not declared its AI provider"
494
- };
495
- }
496
- }
497
- if (intent === "ai_retain_session_data") {
498
- if (rules.dataRetentionPolicy === "never") {
499
- return {
500
- verdict: {
501
- status: "BLOCK",
502
- ruleId: "user-rule-no-retention",
503
- reason: `User rules block all data retention. App "${appContext.appId}" cannot retain session data.`,
504
- evidence: makeEvidence("user-rule-no-retention")
505
- },
506
- reason: "User has blocked all data retention"
507
- };
508
- }
509
- if (!appContext.dataRetentionOptedIn) {
510
- return {
511
- verdict: {
512
- status: "BLOCK",
513
- ruleId: "user-rule-retention-no-optin",
514
- reason: `User has not opted in to data retention for app "${appContext.appId}".`,
515
- evidence: makeEvidence("user-rule-retention-no-optin")
516
- },
517
- reason: "User has not opted in to data retention for this app"
518
- };
519
- }
520
- }
521
- if (intent === "ai_auto_purchase") {
522
- if (rules.aiPurchasePolicy === "block_all") {
523
- return {
524
- verdict: {
525
- status: "BLOCK",
526
- ruleId: "user-rule-no-purchases",
527
- reason: "User rules block all AI-initiated purchases.",
528
- evidence: makeEvidence("user-rule-no-purchases")
529
- },
530
- reason: "User has blocked all AI purchases"
531
- };
532
- }
533
- return {
534
- verdict: {
535
- status: "PAUSE",
536
- ruleId: "user-rule-purchase-confirm",
537
- reason: `AI wants to make a purchase. User rules require per-transaction confirmation.`,
538
- evidence: makeEvidence("user-rule-purchase-confirm")
539
- },
540
- reason: "User requires per-transaction confirmation for AI purchases"
541
- };
542
- }
543
- if (intent === "ai_auto_respond_message") {
544
- if (rules.aiMessagingPolicy === "block_all") {
545
- return {
546
- verdict: {
547
- status: "BLOCK",
548
- ruleId: "user-rule-no-messaging",
549
- reason: "User rules block all AI-initiated messaging.",
550
- evidence: makeEvidence("user-rule-no-messaging")
551
- },
552
- reason: "User has blocked all AI messaging"
553
- };
554
- }
555
- return {
556
- verdict: {
557
- status: "PAUSE",
558
- ruleId: "user-rule-message-confirm",
559
- reason: `AI wants to send a message on your behalf. User rules require per-message confirmation.`,
560
- evidence: makeEvidence("user-rule-message-confirm")
561
- },
562
- reason: "User requires per-message confirmation for AI messaging"
563
- };
564
- }
565
- if (def.domain === "ai_action" && intent !== "ai_auto_purchase" && intent !== "ai_auto_respond_message") {
566
- if (rules.aiActionPolicy === "block_all") {
567
- return {
568
- verdict: {
569
- status: "BLOCK",
570
- ruleId: "user-rule-no-ai-actions",
571
- reason: `User rules block all AI auto-actions. Intent: ${intent}`,
572
- evidence: makeEvidence("user-rule-no-ai-actions")
573
- },
574
- reason: "User has blocked all AI auto-actions"
575
- };
576
- }
577
- if (rules.aiActionPolicy === "confirm_all") {
578
- return {
579
- verdict: {
580
- status: "PAUSE",
581
- ruleId: "user-rule-action-confirm",
582
- reason: `AI wants to take action: ${intent}. User rules require confirmation.`,
583
- evidence: makeEvidence("user-rule-action-confirm")
584
- },
585
- reason: "User requires confirmation for all AI actions"
586
- };
587
- }
588
- if (def.base_risk === "high" || def.base_risk === "critical") {
589
- return {
590
- verdict: {
591
- status: "PAUSE",
592
- ruleId: "user-rule-high-risk-confirm",
593
- reason: `AI wants to take high-risk action: ${intent}. User rules require confirmation for high-risk actions.`,
594
- evidence: makeEvidence("user-rule-high-risk-confirm")
595
- },
596
- reason: "User requires confirmation for high-risk AI actions"
597
- };
598
- }
599
- }
600
- if (intent === "ai_share_with_third_party") {
601
- return {
602
- verdict: {
603
- status: "PAUSE",
604
- ruleId: "user-rule-third-party-confirm",
605
- reason: `App wants to share your data with a third party beyond its declared AI provider. Confirmation required.`,
606
- evidence: makeEvidence("user-rule-third-party-confirm")
607
- },
608
- reason: "Third-party data sharing requires user confirmation"
609
- };
610
- }
611
- return null;
612
- }
613
- function makeEvidence(ruleId) {
614
- return {
615
- worldId: "mentraos-user-rules",
616
- worldName: "MentraOS User Rules",
617
- worldVersion: "1.0.0",
618
- evaluatedAt: Date.now(),
619
- invariantsSatisfied: 0,
620
- invariantsTotal: 0,
621
- guardsMatched: [ruleId],
622
- rulesMatched: [],
623
- enforcementLevel: "strict"
624
- };
625
- }
626
- var MentraGovernedExecutor = class {
627
- world;
628
- engineOptions;
629
- options;
630
- planState;
631
- planCallbacks;
632
- _userRules;
633
- _emergencyOverride = false;
634
- _emergencyActivatedAt = null;
635
- _spatialSession = null;
636
- constructor(world, options = {}, userRules = DEFAULT_USER_RULES) {
637
- this.world = world;
638
- this.options = options;
639
- this._userRules = userRules;
640
- this.engineOptions = buildEngineOptions(options, options.plan);
641
- this.planState = { activePlan: options.plan, engineOptions: this.engineOptions };
642
- this.planCallbacks = {
643
- onPlanProgress: options.onPlanProgress,
644
- onPlanComplete: options.onPlanComplete
645
- };
646
- }
647
- /** Get the current user rules */
648
- get userRules() {
649
- return this._userRules;
650
- }
651
- /** Update user rules at runtime (e.g., user changes preferences in phone app) */
652
- updateUserRules(rules) {
653
- this._userRules = { ...this._userRules, ...rules };
654
- }
655
- /**
656
- * Activate emergency override — user is king.
657
- *
658
- * Bypasses all NeuroVerse governance rules (user rules, platform rules).
659
- * Does NOT bypass MentraOS platform constraints (hardware capability,
660
- * declared permissions, session isolation). You can't override physics.
661
- *
662
- * Returns the timestamp of activation for audit trail.
663
- */
664
- activateEmergencyOverride() {
665
- this._emergencyOverride = true;
666
- this._emergencyActivatedAt = Date.now();
667
- this.engineOptions = { ...this.engineOptions, emergencyOverride: true };
668
- return this._emergencyActivatedAt;
669
- }
670
- /**
671
- * Deactivate emergency override — governance resumes.
672
- * Returns the duration the override was active (ms).
673
- */
674
- deactivateEmergencyOverride() {
675
- if (!this._emergencyOverride || !this._emergencyActivatedAt) {
676
- return 0;
677
- }
678
- const duration = Date.now() - this._emergencyActivatedAt;
679
- this._emergencyOverride = false;
680
- this._emergencyActivatedAt = null;
681
- this.engineOptions = { ...this.engineOptions, emergencyOverride: false };
682
- return duration;
683
- }
684
- /** Whether emergency override is currently active */
685
- get isEmergencyOverrideActive() {
686
- return this._emergencyOverride;
687
- }
688
- /** Timestamp when emergency override was activated, or null */
689
- get emergencyActivatedAt() {
690
- return this._emergencyActivatedAt;
691
- }
692
- // ── Spatial Governance (optional) ────────────────────────────────────────
693
- /**
694
- * Attach a spatial session to this executor.
695
- *
696
- * When attached, intents are evaluated against the spatial context
697
- * (zone rules + handshake rules) AFTER user rules but BEFORE
698
- * hardware and platform checks. This is Layer 1.5.
699
- *
700
- * Pass null to detach (e.g., when leaving a zone).
701
- */
702
- setSpatialSession(session) {
703
- this._spatialSession = session;
704
- }
705
- /** Whether a spatial session is currently active */
706
- get hasSpatialSession() {
707
- return this._spatialSession !== null;
708
- }
709
- /** Get the current spatial session description */
710
- get spatialDescription() {
711
- return this._spatialSession?.description ?? null;
712
- }
713
- /**
714
- * Evaluate an intent against user rules + platform world.
715
- *
716
- * Three-layer evaluation:
717
- * 0. Emergency override — if active, skip governance (layers 1 + 1.5 + 3),
718
- * but STILL enforce platform constraints (layer 2)
719
- * 1. User rules check — personal governance override, can BLOCK or PAUSE
720
- * 1.5. Spatial governance — zone + handshake rules (optional, temporary)
721
- * ↑ ONLY ACTIVE when a spatial session is attached
722
- * 2. Hardware capability check — validates glasses support
723
- * ↑ THIS IS A PLATFORM CONSTRAINT — never overridden
724
- * 3. Platform guard engine — full world rule evaluation
725
- */
726
- evaluate(intent, appContext) {
727
- const intentDef = getMentraIntent(intent);
728
- const glassesModel = appContext.glassesModel;
729
- if (!this._emergencyOverride) {
730
- const userRulesResult = evaluateUserRules(intent, this._userRules, appContext);
731
- if (userRulesResult) {
732
- const allowed2 = false;
733
- const requiresConfirmation2 = userRulesResult.verdict.status === "PAUSE";
734
- const result2 = {
735
- allowed: requiresConfirmation2 ? false : false,
736
- requiresConfirmation: requiresConfirmation2,
737
- verdict: userRulesResult.verdict,
738
- intentDef,
739
- userRulesResult: { reason: userRulesResult.reason },
740
- appContext,
741
- decidingLayer: "user_rules"
742
- };
743
- if (requiresConfirmation2) {
744
- this.options.onPause?.(result2);
745
- } else {
746
- this.options.onBlock?.(result2);
747
- }
748
- this.options.onEvaluate?.(result2);
749
- return result2;
750
- }
751
- }
752
- if (!this._emergencyOverride && this._spatialSession) {
753
- const spatialResult = this._spatialSession.evaluate(intent);
754
- if (!spatialResult.allowed && !spatialResult.requiresConfirmation) {
755
- const verdict2 = {
756
- status: "BLOCK",
757
- ruleId: "spatial-zone-rule",
758
- reason: spatialResult.reason,
759
- evidence: makeEvidence("spatial-zone-rule")
760
- };
761
- const result2 = {
762
- allowed: false,
763
- requiresConfirmation: false,
764
- verdict: verdict2,
765
- intentDef,
766
- appContext,
767
- decidingLayer: "spatial"
768
- };
769
- this.options.onBlock?.(result2);
770
- this.options.onEvaluate?.(result2);
771
- return result2;
772
- }
773
- if (spatialResult.requiresConfirmation) {
774
- const verdict2 = {
775
- status: "PAUSE",
776
- ruleId: "spatial-zone-rule",
777
- reason: spatialResult.reason,
778
- evidence: makeEvidence("spatial-zone-rule")
779
- };
780
- const result2 = {
781
- allowed: false,
782
- requiresConfirmation: true,
783
- verdict: verdict2,
784
- intentDef,
785
- appContext,
786
- decidingLayer: "spatial"
787
- };
788
- this.options.onPause?.(result2);
789
- this.options.onEvaluate?.(result2);
790
- return result2;
791
- }
792
- }
793
- if (intentDef && glassesModel && !intentDef.supported_glasses.includes(glassesModel)) {
794
- const verdict2 = {
795
- status: "BLOCK",
796
- ruleId: "hardware-capability",
797
- reason: `${intent} not supported on ${glassesModel} \u2014 requires: ${intentDef.supported_glasses.join(", ")}`,
798
- evidence: {
799
- worldId: this.world.world?.world_id ?? "unknown",
800
- worldName: this.world.world?.name ?? "unknown",
801
- worldVersion: this.world.world?.version ?? "unknown",
802
- evaluatedAt: Date.now(),
803
- invariantsSatisfied: 0,
804
- invariantsTotal: 0,
805
- guardsMatched: ["hardware-capability"],
806
- rulesMatched: [],
807
- enforcementLevel: "strict"
808
- }
809
- };
810
- const result2 = {
811
- allowed: false,
812
- requiresConfirmation: false,
813
- verdict: verdict2,
814
- intentDef,
815
- appContext,
816
- decidingLayer: "hardware"
817
- };
818
- this.options.onBlock?.(result2);
819
- this.options.onEvaluate?.(result2);
820
- return result2;
821
- }
822
- const event = {
823
- intent,
824
- tool: intentDef?.sdk_method ?? intent,
825
- scope: intentDef?.domain ?? "unknown",
826
- actionCategory: intentDef?.action_category,
827
- riskLevel: intentDef?.base_risk ?? "medium",
828
- irreversible: intentDef ? !intentDef.reversible : false,
829
- args: {
830
- app_id: appContext.appId,
831
- ai_provider_declared: appContext.aiProviderDeclared ? 1 : 0,
832
- ai_data_types_sent: appContext.aiDataTypesSent,
833
- ai_retention_opted_in: appContext.dataRetentionOptedIn ? 1 : 0,
834
- glasses_model: glassesModel ?? "unknown",
835
- is_ai_intent: isAIIntent(intent) ? 1 : 0
836
- }
837
- };
838
- const verdict = evaluateGuard(event, this.world, this.engineOptions);
839
- const allowed = verdict.status === "ALLOW" || verdict.status === "REWARD";
840
- const requiresConfirmation = verdict.status === "PAUSE";
841
- if (allowed) {
842
- trackPlanProgress(event, this.planState, this.planCallbacks);
843
- }
844
- const result = {
845
- allowed,
846
- requiresConfirmation,
847
- verdict,
848
- intentDef,
849
- appContext,
850
- decidingLayer: this._emergencyOverride ? "emergency_override" : "platform"
851
- };
852
- if (!allowed && !requiresConfirmation) {
853
- this.options.onBlock?.(result);
854
- }
855
- if (requiresConfirmation) {
856
- this.options.onPause?.(result);
857
- }
858
- this.options.onEvaluate?.(result);
859
- return result;
860
- }
861
- /** Get all known intents for this adapter */
862
- get knownIntents() {
863
- return MENTRA_KNOWN_INTENTS;
864
- }
865
- };
866
- async function createMentraGovernedExecutor(worldPath, options = {}, userRules = DEFAULT_USER_RULES) {
867
- const world = await loadWorld(worldPath);
868
- return new MentraGovernedExecutor(world, options, userRules);
869
- }
870
- function createMentraGovernedExecutorFromWorld(world, options = {}, userRules = DEFAULT_USER_RULES) {
871
- return new MentraGovernedExecutor(world, options, userRules);
872
- }
873
-
874
439
  export {
875
440
  MENTRA_INTENT_TAXONOMY,
876
441
  MENTRA_KNOWN_INTENTS,
@@ -884,10 +449,5 @@ export {
884
449
  getAIDataIntents,
885
450
  getAIActionIntents,
886
451
  getAIIntents,
887
- isAIIntent,
888
- DEFAULT_USER_RULES,
889
- evaluateUserRules,
890
- MentraGovernedExecutor,
891
- createMentraGovernedExecutor,
892
- createMentraGovernedExecutorFromWorld
452
+ isAIIntent
893
453
  };
@@ -0,0 +1,107 @@
1
+ // src/cli/sign.ts
2
+ import { createHash, sign } from "crypto";
3
+ import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
4
+ import { join, relative } from "path";
5
+ import { homedir } from "os";
6
+ var USAGE = `
7
+ neuroverse sign \u2014 Sign a world artifact
8
+
9
+ Usage:
10
+ neuroverse sign --world <dir> [--key <path>]
11
+
12
+ Options:
13
+ --world <dir> World directory to sign (required)
14
+ --key <path> Private key path (default: ~/.neuroverse/keys/neuroverse.key)
15
+
16
+ Examples:
17
+ neuroverse sign --world ./world/
18
+ neuroverse sign --world ./world/ --key ./keys/production.key
19
+ `.trim();
20
+ function parseArgs(argv) {
21
+ let worldPath = "";
22
+ let keyPath = join(homedir(), ".neuroverse", "keys", "neuroverse.key");
23
+ let help = false;
24
+ for (let i = 0; i < argv.length; i++) {
25
+ const arg = argv[i];
26
+ if (arg === "--world" && argv[i + 1]) {
27
+ worldPath = argv[++i];
28
+ } else if (arg === "--key" && argv[i + 1]) {
29
+ keyPath = argv[++i];
30
+ } else if (arg === "--help" || arg === "-h") {
31
+ help = true;
32
+ }
33
+ }
34
+ return { worldPath, keyPath, help };
35
+ }
36
+ function collectFiles(dir, base) {
37
+ const root = base ?? dir;
38
+ const files = [];
39
+ for (const entry of readdirSync(dir)) {
40
+ if (entry === ".nv-signature.json") continue;
41
+ const full = join(dir, entry);
42
+ const stat = statSync(full);
43
+ if (stat.isDirectory()) {
44
+ files.push(...collectFiles(full, root));
45
+ } else {
46
+ files.push(relative(root, full));
47
+ }
48
+ }
49
+ return files.sort();
50
+ }
51
+ function buildManifest(worldPath) {
52
+ const files = collectFiles(worldPath);
53
+ const manifest = {};
54
+ for (const file of files) {
55
+ const content = readFileSync(join(worldPath, file));
56
+ manifest[file] = createHash("sha256").update(content).digest("hex");
57
+ }
58
+ return manifest;
59
+ }
60
+ function canonicalManifest(files) {
61
+ const sorted = Object.keys(files).sort();
62
+ return sorted.map((k) => `${k}:${files[k]}`).join("\n");
63
+ }
64
+ async function main(argv = process.argv.slice(2)) {
65
+ const args = parseArgs(argv);
66
+ if (args.help) {
67
+ process.stdout.write(USAGE + "\n");
68
+ return;
69
+ }
70
+ if (!args.worldPath) {
71
+ process.stderr.write("Error: --world <dir> is required.\n");
72
+ process.exit(1);
73
+ }
74
+ let privateKey;
75
+ try {
76
+ privateKey = readFileSync(args.keyPath, "utf-8");
77
+ } catch {
78
+ process.stderr.write(`Error: Cannot read private key at ${args.keyPath}
79
+ `);
80
+ process.stderr.write('Run "neuroverse keygen" to generate a keypair.\n');
81
+ process.exit(1);
82
+ return;
83
+ }
84
+ const files = buildManifest(args.worldPath);
85
+ const canonical = canonicalManifest(files);
86
+ const manifestHash = createHash("sha256").update(canonical).digest("hex");
87
+ const signature = sign(null, Buffer.from(manifestHash), privateKey).toString("base64");
88
+ const artifact = {
89
+ signatureVersion: "1.0",
90
+ signedAt: (/* @__PURE__ */ new Date()).toISOString(),
91
+ files,
92
+ manifestHash,
93
+ signature
94
+ };
95
+ const outPath = join(args.worldPath, ".nv-signature.json");
96
+ writeFileSync(outPath, JSON.stringify(artifact, null, 2) + "\n", "utf-8");
97
+ process.stdout.write(`Signed ${Object.keys(files).length} files in ${args.worldPath}
98
+ `);
99
+ process.stdout.write(`Signature: ${outPath}
100
+ `);
101
+ }
102
+
103
+ export {
104
+ buildManifest,
105
+ canonicalManifest,
106
+ main
107
+ };
@@ -2,12 +2,12 @@ import {
2
2
  describeActiveWorld,
3
3
  resolveWorldPath
4
4
  } from "./chunk-AKW5YVCE.js";
5
+ import {
6
+ loadWorld
7
+ } from "./chunk-EQUAWNXW.js";
5
8
  import {
6
9
  evaluateGuard
7
10
  } from "./chunk-ZAF6JH23.js";
8
- import {
9
- loadWorld
10
- } from "./chunk-I4RTIMLX.js";
11
11
  import {
12
12
  advancePlan,
13
13
  evaluatePlan,
@@ -5,12 +5,12 @@ import {
5
5
  extractScope,
6
6
  trackPlanProgress
7
7
  } from "./chunk-5U2MQO5P.js";
8
+ import {
9
+ loadWorld
10
+ } from "./chunk-EQUAWNXW.js";
8
11
  import {
9
12
  evaluateGuard
10
13
  } from "./chunk-ZAF6JH23.js";
11
- import {
12
- loadWorld
13
- } from "./chunk-I4RTIMLX.js";
14
14
 
15
15
  // src/adapters/openai.ts
16
16
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {
@@ -4,12 +4,12 @@ import {
4
4
  extractScope,
5
5
  trackPlanProgress
6
6
  } from "./chunk-5U2MQO5P.js";
7
+ import {
8
+ loadWorld
9
+ } from "./chunk-EQUAWNXW.js";
7
10
  import {
8
11
  evaluateGuard
9
12
  } from "./chunk-ZAF6JH23.js";
10
- import {
11
- loadWorld
12
- } from "./chunk-I4RTIMLX.js";
13
13
 
14
14
  // src/adapters/openclaw.ts
15
15
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {
@@ -1,9 +1,9 @@
1
+ import {
2
+ loadWorldFromDirectory
3
+ } from "./chunk-EQUAWNXW.js";
1
4
  import {
2
5
  evaluateGuard
3
6
  } from "./chunk-ZAF6JH23.js";
4
- import {
5
- loadWorldFromDirectory
6
- } from "./chunk-I4RTIMLX.js";
7
7
 
8
8
  // src/adapters/autoresearch.ts
9
9
  var AutoresearchGovernor = class {
@@ -1,9 +1,9 @@
1
+ import {
2
+ loadWorld
3
+ } from "./chunk-EQUAWNXW.js";
1
4
  import {
2
5
  evaluateGuard
3
6
  } from "./chunk-ZAF6JH23.js";
4
- import {
5
- loadWorld
6
- } from "./chunk-I4RTIMLX.js";
7
7
 
8
8
  // src/runtime/govern.ts
9
9
  function actionToGuardEvent(action) {
@@ -4,12 +4,12 @@ import {
4
4
  extractScope,
5
5
  trackPlanProgress
6
6
  } from "./chunk-5U2MQO5P.js";
7
+ import {
8
+ loadWorld
9
+ } from "./chunk-EQUAWNXW.js";
7
10
  import {
8
11
  evaluateGuard
9
12
  } from "./chunk-ZAF6JH23.js";
10
- import {
11
- loadWorld
12
- } from "./chunk-I4RTIMLX.js";
13
13
 
14
14
  // src/adapters/langchain.ts
15
15
  var GovernanceBlockedError2 = class extends GovernanceBlockedError {
@@ -35,7 +35,7 @@ async function addGuard(worldDir, input) {
35
35
  };
36
36
  config.guards.push(guard);
37
37
  await writeFile(guardsPath, JSON.stringify(config, null, 2) + "\n");
38
- const { loadWorldFromDirectory } = await import("./world-loader-YTYFOP7D.js");
38
+ const { loadWorldFromDirectory } = await import("./world-loader-J47PCPDZ.js");
39
39
  const world = await loadWorldFromDirectory(worldDir);
40
40
  const report = validateWorld(world);
41
41
  return {
@@ -83,7 +83,7 @@ async function addRule(worldDir, input) {
83
83
  };
84
84
  const rulePath = join(rulesDir, `rule-${ruleNum}.json`);
85
85
  await writeFile(rulePath, JSON.stringify(rule, null, 2) + "\n");
86
- const { loadWorldFromDirectory } = await import("./world-loader-YTYFOP7D.js");
86
+ const { loadWorldFromDirectory } = await import("./world-loader-J47PCPDZ.js");
87
87
  const world = await loadWorldFromDirectory(worldDir);
88
88
  const report = validateWorld(world);
89
89
  return {
@@ -118,7 +118,7 @@ async function addInvariant(worldDir, input) {
118
118
  };
119
119
  config.invariants.push(invariant);
120
120
  await writeFile(invariantsPath, JSON.stringify(config, null, 2) + "\n");
121
- const { loadWorldFromDirectory } = await import("./world-loader-YTYFOP7D.js");
121
+ const { loadWorldFromDirectory } = await import("./world-loader-J47PCPDZ.js");
122
122
  const world = await loadWorldFromDirectory(worldDir);
123
123
  const report = validateWorld(world);
124
124
  return {