@contextecf/guardian-cli 0.1.6 → 0.1.8

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.
@@ -16275,7 +16275,7 @@ function cloneList(values) {
16275
16275
  }
16276
16276
 
16277
16277
  // packages/guardian-cli/src/runtime.ts
16278
- var GUARDIAN_CLI_VERSION = "0.1.6";
16278
+ var GUARDIAN_CLI_VERSION = "0.1.8";
16279
16279
  var GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
16280
16280
  var GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
16281
16281
  var GUARDIAN_NPM_REGISTRY = "https://registry.npmjs.org/";
@@ -16283,8 +16283,17 @@ var GUARDIAN_GLOBAL_INSTALL_COMMAND = `npm install -g ${GUARDIAN_NPM_PACKAGE_NAM
16283
16283
  var GUARDIAN_NPX_SETUP_COMMAND = `npx ${GUARDIAN_NPM_PACKAGE_NAME}@latest setup`;
16284
16284
  var GUARDIAN_FIRST_RUN_COMMAND = "guardian setup";
16285
16285
  var GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian open";
16286
+ var GUARDIAN_HALO_CHROME_EXTENSION_ID = "dopkdppbiakhbglhgjfacfdhpheejkck";
16287
+ var GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL = `https://chromewebstore.google.com/detail/contextecf-halo/${GUARDIAN_HALO_CHROME_EXTENSION_ID}`;
16286
16288
  var GUARDIAN_RELEASE_DISPATCH_WORKFLOW = "guardian-release-dispatch.yml";
16287
16289
  var GUARDIAN_RELEASE_REPOSITORY = "Intelligent-Context-AI-Inc/ContextECF-GITHUB";
16290
+ var GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES = [
16291
+ "CHROME_WEB_STORE_CLIENT_ID",
16292
+ "CHROME_WEB_STORE_CLIENT_SECRET",
16293
+ "CHROME_WEB_STORE_REFRESH_TOKEN",
16294
+ "CHROME_WEB_STORE_PUBLISHER_ID",
16295
+ "CHROME_WEB_STORE_EXTENSION_ID"
16296
+ ];
16288
16297
  var GUARDIAN_CONTROL_TOWER_URL_ENV = "GUARDIAN_CONTROL_TOWER_URL";
16289
16298
  var GUARDIAN_DEFAULT_CONTROL_TOWER_URL = "http://127.0.0.1:4317/control-tower";
16290
16299
  var GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY";
@@ -16301,6 +16310,195 @@ var GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION = "contextecf/pro
16301
16310
  var PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2 = "contextecf/personal-fabric-contracts/v1";
16302
16311
  var PROMPT_COACH_MODES = ["off", "quiet", "balanced", "hands_on"];
16303
16312
  var DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT = 6;
16313
+ var GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG = [
16314
+ {
16315
+ disposition: "allow",
16316
+ cardStyle: "No visible card",
16317
+ whenShown: "Local Guardian approves the prompt before it leaves the browser.",
16318
+ actions: [
16319
+ {
16320
+ id: "auto-send",
16321
+ label: "Send prompt",
16322
+ role: "none",
16323
+ sendsPrompt: true,
16324
+ sendsRevisedPrompt: false,
16325
+ requiresConfirmation: false,
16326
+ visibleToUser: false
16327
+ }
16328
+ ],
16329
+ sendAsIsAllowed: true,
16330
+ hardBlock: false,
16331
+ receiptExpected: true
16332
+ },
16333
+ {
16334
+ disposition: "warn",
16335
+ cardStyle: "Quick check",
16336
+ whenShown: "Guardian found a low or medium-risk concern, but policy still allows the user to continue.",
16337
+ actions: [
16338
+ {
16339
+ id: "send-as-is",
16340
+ label: "Send as-is",
16341
+ role: "allowed_override",
16342
+ sendsPrompt: true,
16343
+ sendsRevisedPrompt: false,
16344
+ requiresConfirmation: false,
16345
+ visibleToUser: true
16346
+ },
16347
+ {
16348
+ id: "edit-prompt",
16349
+ label: "Edit prompt",
16350
+ role: "safe_escape",
16351
+ sendsPrompt: false,
16352
+ sendsRevisedPrompt: false,
16353
+ requiresConfirmation: false,
16354
+ visibleToUser: true
16355
+ }
16356
+ ],
16357
+ sendAsIsAllowed: true,
16358
+ hardBlock: false,
16359
+ receiptExpected: true
16360
+ },
16361
+ {
16362
+ disposition: "rewrite",
16363
+ cardStyle: "Safer version ready",
16364
+ whenShown: "Guardian prepared a safer prompt, usually by masking sensitive text or narrowing scope.",
16365
+ actions: [
16366
+ {
16367
+ id: "send-revised-prompt",
16368
+ label: "Send revised prompt",
16369
+ role: "recommended",
16370
+ sendsPrompt: true,
16371
+ sendsRevisedPrompt: true,
16372
+ requiresConfirmation: false,
16373
+ visibleToUser: true
16374
+ },
16375
+ {
16376
+ id: "send-as-is",
16377
+ label: "Send as-is",
16378
+ role: "allowed_override",
16379
+ sendsPrompt: true,
16380
+ sendsRevisedPrompt: false,
16381
+ requiresConfirmation: false,
16382
+ visibleToUser: true
16383
+ },
16384
+ {
16385
+ id: "edit-prompt",
16386
+ label: "Edit prompt",
16387
+ role: "safe_escape",
16388
+ sendsPrompt: false,
16389
+ sendsRevisedPrompt: false,
16390
+ requiresConfirmation: false,
16391
+ visibleToUser: true
16392
+ }
16393
+ ],
16394
+ sendAsIsAllowed: true,
16395
+ hardBlock: false,
16396
+ receiptExpected: true
16397
+ },
16398
+ {
16399
+ disposition: "confirm",
16400
+ cardStyle: "Review needed",
16401
+ whenShown: "Guardian needs deliberate approval before sending higher-risk content or action requests.",
16402
+ actions: [
16403
+ {
16404
+ id: "approve-and-send",
16405
+ label: "Approve and send",
16406
+ role: "recommended",
16407
+ sendsPrompt: true,
16408
+ sendsRevisedPrompt: false,
16409
+ requiresConfirmation: true,
16410
+ visibleToUser: true
16411
+ },
16412
+ {
16413
+ id: "edit-prompt",
16414
+ label: "Edit prompt",
16415
+ role: "safe_escape",
16416
+ sendsPrompt: false,
16417
+ sendsRevisedPrompt: false,
16418
+ requiresConfirmation: false,
16419
+ visibleToUser: true
16420
+ }
16421
+ ],
16422
+ sendAsIsAllowed: false,
16423
+ hardBlock: false,
16424
+ receiptExpected: true
16425
+ },
16426
+ {
16427
+ disposition: "block",
16428
+ cardStyle: "Blocked",
16429
+ whenShown: "The prompt violates policy, contains protected secrets, or targets a denied destination.",
16430
+ actions: [
16431
+ {
16432
+ id: "edit-prompt",
16433
+ label: "Edit prompt",
16434
+ role: "safe_escape",
16435
+ sendsPrompt: false,
16436
+ sendsRevisedPrompt: false,
16437
+ requiresConfirmation: false,
16438
+ visibleToUser: true
16439
+ }
16440
+ ],
16441
+ sendAsIsAllowed: false,
16442
+ hardBlock: true,
16443
+ receiptExpected: true
16444
+ },
16445
+ {
16446
+ disposition: "unavailable",
16447
+ cardStyle: "Setup needed",
16448
+ whenShown: "The browser cannot reach Local Guardian, so the prompt is held back.",
16449
+ actions: [
16450
+ {
16451
+ id: "edit-prompt",
16452
+ label: "Edit prompt",
16453
+ role: "safe_escape",
16454
+ sendsPrompt: false,
16455
+ sendsRevisedPrompt: false,
16456
+ requiresConfirmation: false,
16457
+ visibleToUser: true
16458
+ }
16459
+ ],
16460
+ sendAsIsAllowed: false,
16461
+ hardBlock: false,
16462
+ receiptExpected: false
16463
+ },
16464
+ {
16465
+ disposition: "live_sensitive_warning",
16466
+ cardStyle: "Early heads-up",
16467
+ whenShown: "Guardian notices sensitive text while the user is typing, before the formal send-time check.",
16468
+ actions: [
16469
+ {
16470
+ id: "use-placeholder",
16471
+ label: "Use placeholder",
16472
+ role: "recommended",
16473
+ sendsPrompt: false,
16474
+ sendsRevisedPrompt: true,
16475
+ requiresConfirmation: false,
16476
+ visibleToUser: true
16477
+ },
16478
+ {
16479
+ id: "send-as-is",
16480
+ label: "Send as-is",
16481
+ role: "allowed_override",
16482
+ sendsPrompt: true,
16483
+ sendsRevisedPrompt: false,
16484
+ requiresConfirmation: false,
16485
+ visibleToUser: true
16486
+ },
16487
+ {
16488
+ id: "keep-drafting",
16489
+ label: "Keep drafting",
16490
+ role: "safe_escape",
16491
+ sendsPrompt: false,
16492
+ sendsRevisedPrompt: false,
16493
+ requiresConfirmation: false,
16494
+ visibleToUser: true
16495
+ }
16496
+ ],
16497
+ sendAsIsAllowed: true,
16498
+ hardBlock: false,
16499
+ receiptExpected: false
16500
+ }
16501
+ ];
16304
16502
  var GUARDIAN_POSTURE_PROFILE_IDS = [
16305
16503
  "calm",
16306
16504
  "balanced",
@@ -16780,6 +16978,45 @@ var MCP_CLIENTS = ["generic", "codex", "claude-desktop", "cursor"];
16780
16978
  var NATIVE_HOST_BROWSERS = ["chrome", "chromium", "edge"];
16781
16979
  var HELP_TEXT = `guardian \u2014 Project Guardian Personal Context Fabric
16782
16980
 
16981
+ Global install:
16982
+ ${GUARDIAN_GLOBAL_INSTALL_COMMAND}
16983
+
16984
+ First run:
16985
+ ${GUARDIAN_FIRST_RUN_COMMAND}
16986
+
16987
+ No global install:
16988
+ ${GUARDIAN_NPX_SETUP_COMMAND}
16989
+
16990
+ Open Control Tower:
16991
+ ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}
16992
+ start aliases: guardian launch, guardian tower, guardian control-tower
16993
+
16994
+ Everyday commands:
16995
+ guardian --version
16996
+ guardian setup
16997
+ guardian launch
16998
+ guardian open
16999
+ guardian status
17000
+ guardian doctor
17001
+ guardian connect
17002
+ guardian coach options
17003
+ guardian policy list
17004
+ guardian marketplace list
17005
+ guardian posture list
17006
+ guardian privacy show
17007
+
17008
+ Recommended first run:
17009
+ ${GUARDIAN_GLOBAL_INSTALL_COMMAND}
17010
+ guardian setup
17011
+ Open ContextECF Halo and click Connect.
17012
+ guardian open
17013
+
17014
+ Support and developer commands:
17015
+ guardian help --advanced
17016
+
17017
+ Defaults are local-first: raw capture, cloud sync, learning graph, and app autopilot stay off.`;
17018
+ var ADVANCED_HELP_TEXT = `guardian \u2014 Project Guardian Personal Context Fabric
17019
+
16783
17020
  Global install:
16784
17021
  ${GUARDIAN_GLOBAL_INSTALL_COMMAND}
16785
17022
 
@@ -16796,7 +17033,7 @@ Open Control Tower:
16796
17033
  Usage:
16797
17034
  guardian --version
16798
17035
  guardian version [--json]
16799
- guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
17036
+ guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--no-browser-connection] [--extension-id=<chrome-extension-id>]
16800
17037
  guardian install [--json]
16801
17038
  guardian doctor [--json]
16802
17039
  guardian readiness [--json] [--strict]
@@ -16804,7 +17041,7 @@ Usage:
16804
17041
  guardian release flow --version=<semver> [--json]
16805
17042
  guardian release verify --version=<semver> [--json]
16806
17043
  guardian release paste --version=<semver> [--json]
16807
- guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--json]
17044
+ guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--publish-auth=token|trusted_publisher] [--browser-store-publish=manual|api] [--json]
16808
17045
  guardian release secrets [--json]
16809
17046
  guardian release browser-store [--json]
16810
17047
  guardian open [--json] [--print] [--url=http://127.0.0.1:<port>]
@@ -16812,6 +17049,8 @@ Usage:
16812
17049
  guardian start [--json] [--host=127.0.0.1] [--port=4317]
16813
17050
  guardian launch|tower|control-tower [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317]
16814
17051
  guardian stop [--json] [--url=http://127.0.0.1:<port>/control-tower]
17052
+ guardian pair [--json]
17053
+ guardian connect [--json] [--browser=chrome|chromium|edge] [--extension-id=<chrome-extension-id>] [--host=127.0.0.1] [--port=4317]
16815
17054
  guardian service install [--json] [--platform=auto|launchd|systemd|windows-task-scheduler] [--force]
16816
17055
  guardian service status [--json]
16817
17056
  guardian service uninstall [--yes] [--json]
@@ -16820,6 +17059,7 @@ Usage:
16820
17059
  guardian key-store uninstall [--yes] [--json]
16821
17060
  guardian daemon serve [--host=127.0.0.1] [--port=4317]
16822
17061
  guardian daemon pair [--json]
17062
+ guardian extension connect [--json] [--browser=chrome|chromium|edge] [--extension-id=<chrome-extension-id>]
16823
17063
  guardian extension open-setup [--json] [--print] [--url=http://127.0.0.1:<port>/control-tower] [--extension-id=<chrome-extension-id>]
16824
17064
  guardian extension native-host install --extension-id=<chrome-extension-id> [--browser=chrome|chromium|edge] [--target=/path/to/manifest] [--force] [--write-registry --yes] [--json]
16825
17065
  guardian extension native-host status [--browser=chrome|chromium|edge] [--target=/path/to/manifest] [--json]
@@ -16835,6 +17075,7 @@ Usage:
16835
17075
  guardian privacy mode on [--json]
16836
17076
  guardian mcp install [--json] [--client=generic|codex|claude-desktop|cursor|all] [--write] [--target=/path/to/config] [--force]
16837
17077
  guardian mcp serve
17078
+ guardian coach options [--json]
16838
17079
  guardian policy list [--json]
16839
17080
  guardian policy enable <pack-id> [--json]
16840
17081
  guardian policy disable <pack-id> [--json]
@@ -16887,6 +17128,8 @@ async function runGuardianCli(argv, options = {}) {
16887
17128
  return runReleaseCommand(argv.slice(1), flags, options);
16888
17129
  case "open":
16889
17130
  return runControlTowerOpenCommand(flags, options);
17131
+ case "connect":
17132
+ return runExtensionConnectCommand(flags, options);
16890
17133
  case "status":
16891
17134
  write(stdout, await statusGuardian(flags, options));
16892
17135
  return 0;
@@ -16898,6 +17141,14 @@ async function runGuardianCli(argv, options = {}) {
16898
17141
  return runLaunchCommand(flags, options);
16899
17142
  case "stop":
16900
17143
  return runStopCommand(flags, options);
17144
+ case "pair": {
17145
+ if (!flags.has("json")) {
17146
+ return runExtensionConnectCommand(flags, options);
17147
+ }
17148
+ const result = await daemonPair(flags, options);
17149
+ write(result.exitCode === 0 ? stdout : stderr, result.message);
17150
+ return result.exitCode;
17151
+ }
16901
17152
  case "daemon":
16902
17153
  return runDaemonCommand(argv.slice(1), flags, options);
16903
17154
  case "service":
@@ -16920,6 +17171,9 @@ async function runGuardianCli(argv, options = {}) {
16920
17171
  return runPrivacyCommand(argv.slice(1), flags, options);
16921
17172
  case "mcp":
16922
17173
  return runMcpCommand(argv.slice(1), flags, options);
17174
+ case "coach":
17175
+ case "prompt-coach":
17176
+ return runCoachCommand(argv.slice(1), flags, options);
16923
17177
  case "policy":
16924
17178
  return runPolicyCommand(argv.slice(1), flags, options);
16925
17179
  case "marketplace":
@@ -16942,7 +17196,7 @@ async function runGuardianCli(argv, options = {}) {
16942
17196
  case "help":
16943
17197
  case "--help":
16944
17198
  case "-h":
16945
- write(stdout, `${HELP_TEXT}
17199
+ write(stdout, `${flags.has("advanced") ? ADVANCED_HELP_TEXT : HELP_TEXT}
16946
17200
  `);
16947
17201
  return 0;
16948
17202
  default:
@@ -17021,11 +17275,13 @@ async function installGuardian(flags, options = {}) {
17021
17275
  "guardian start",
17022
17276
  "guardian open",
17023
17277
  "guardian mcp install",
17024
- "guardian daemon pair --json",
17025
17278
  "guardian service install",
17026
17279
  "guardian key-store install --yes",
17027
- "guardian extension open-setup",
17028
- "guardian extension native-host install --extension-id=<browser-extension-id>"
17280
+ "guardian connect"
17281
+ ],
17282
+ advancedCommands: [
17283
+ `guardian extension native-host install --extension-id=${GUARDIAN_HALO_CHROME_EXTENSION_ID}`,
17284
+ "guardian pair --json"
17029
17285
  ]
17030
17286
  };
17031
17287
  return flags.has("json") ? `${JSON.stringify(result, null, 2)}
@@ -17038,7 +17294,8 @@ async function installGuardian(flags, options = {}) {
17038
17294
  `First run: ${GUARDIAN_FIRST_RUN_COMMAND}`,
17039
17295
  `Open Control Tower: ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}`,
17040
17296
  `No global install: ${GUARDIAN_NPX_SETUP_COMMAND}`,
17041
- "Next: guardian setup; guardian doctor; guardian readiness; guardian launch; guardian open; guardian mcp install; guardian extension open-setup; guardian daemon pair --json; guardian extension native-host install --extension-id=<browser-extension-id>"
17297
+ "Next: guardian setup; open ContextECF Halo and click Connect; guardian open",
17298
+ "Help: run guardian doctor if setup needs attention."
17042
17299
  ].join("\n")}
17043
17300
  `;
17044
17301
  }
@@ -17046,8 +17303,9 @@ async function runSetupCommand(flags, options) {
17046
17303
  const stdout = options.stdout ?? process.stdout;
17047
17304
  const stderr = options.stderr ?? process.stderr;
17048
17305
  const home = resolveGuardianHome(options.env, options.platform);
17049
- const extensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
17050
- if (extensionId && !isValidChromeExtensionId(extensionId)) {
17306
+ const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
17307
+ const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
17308
+ if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
17051
17309
  write(
17052
17310
  stderr,
17053
17311
  "Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
@@ -17103,10 +17361,80 @@ async function runSetupCommand(flags, options) {
17103
17361
  }
17104
17362
  launch = JSON.parse(launchOutput);
17105
17363
  }
17364
+ const requestedHost = stringFlag(flags, "host") ?? "127.0.0.1";
17365
+ const requestedPort = numberFlag(flags, "port") ?? 4317;
17366
+ const requestedControlTowerUrl = `${formatDaemonBaseUrl(requestedHost, requestedPort)}/control-tower`;
17106
17367
  const resolvedControlTowerUrl = resolveControlTowerUrl(/* @__PURE__ */ new Map(), options.env, profile);
17107
- const controlTowerUrl = launch?.controlTowerUrl ?? (resolvedControlTowerUrl.ok ? resolvedControlTowerUrl.url : GUARDIAN_DEFAULT_CONTROL_TOWER_URL);
17368
+ const controlTowerUrl = launch?.controlTowerUrl ?? (flags.has("host") || flags.has("port") ? requestedControlTowerUrl : resolvedControlTowerUrl.ok ? resolvedControlTowerUrl.url : GUARDIAN_DEFAULT_CONTROL_TOWER_URL);
17369
+ if (!launch && (flags.has("host") || flags.has("port"))) {
17370
+ profile.control_tower = {
17371
+ url: controlTowerUrl,
17372
+ source: "env_or_flag"
17373
+ };
17374
+ await writeProfile(home, profile);
17375
+ }
17108
17376
  const setupUrl = buildControlTowerSetupUrl(controlTowerUrl);
17109
- const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId ?? "<browser-extension-id>"}`;
17377
+ const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId}`;
17378
+ let browserHelper;
17379
+ if (flags.has("no-browser-connection") || flags.has("no-browser-helper")) {
17380
+ browserHelper = {
17381
+ success: false,
17382
+ skipped: true,
17383
+ tokenPrinted: false
17384
+ };
17385
+ } else {
17386
+ let nativeHostOutput = "";
17387
+ let nativeHostError = "";
17388
+ const nativeHostFlags = new Map([
17389
+ ["json", true],
17390
+ ["force", true],
17391
+ ["extension-id", extensionId],
17392
+ ...copyStringFlags(flags, ["browser", "target"])
17393
+ ]);
17394
+ if ((options.platform ?? process.platform) === "win32") {
17395
+ nativeHostFlags.set("write-registry", true);
17396
+ nativeHostFlags.set("yes", true);
17397
+ }
17398
+ const nativeHostExitCode = await runExtensionCommand(
17399
+ ["native-host", "install"],
17400
+ nativeHostFlags,
17401
+ {
17402
+ ...options,
17403
+ stdout: {
17404
+ write: (chunk) => {
17405
+ nativeHostOutput += chunk.toString();
17406
+ return true;
17407
+ }
17408
+ },
17409
+ stderr: {
17410
+ write: (chunk) => {
17411
+ nativeHostError += chunk.toString();
17412
+ return true;
17413
+ }
17414
+ }
17415
+ }
17416
+ );
17417
+ if (nativeHostExitCode === 0) {
17418
+ const nativeHost = JSON.parse(nativeHostOutput);
17419
+ browserHelper = {
17420
+ success: true,
17421
+ skipped: false,
17422
+ browser: nativeHost.browser,
17423
+ hostName: nativeHost.hostName,
17424
+ manifestPath: nativeHost.manifestPath,
17425
+ allowedOrigins: nativeHost.allowedOrigins,
17426
+ tokenPrinted: nativeHost.tokenPrinted
17427
+ };
17428
+ } else {
17429
+ browserHelper = {
17430
+ success: false,
17431
+ skipped: false,
17432
+ error: nativeHostError.trim() || "Guardian browser connection setup failed.",
17433
+ exitCode: nativeHostExitCode,
17434
+ tokenPrinted: false
17435
+ };
17436
+ }
17437
+ }
17110
17438
  const result = {
17111
17439
  schema_version: "contextecf/project-guardian-setup/v1",
17112
17440
  success: true,
@@ -17156,10 +17484,14 @@ async function runSetupCommand(flags, options) {
17156
17484
  },
17157
17485
  browserSetup: {
17158
17486
  setupUrl,
17159
- extensionId: extensionId ?? null,
17487
+ extensionId,
17488
+ defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
17160
17489
  opened: false,
17161
17490
  tokenPrinted: false,
17162
- nativeHostCommand
17491
+ nativeHostCommand,
17492
+ connectInstruction: "Open ContextECF Halo and click Connect. No setup code is needed.",
17493
+ manualFallbackCommand: "guardian pair --json",
17494
+ nativeHost: browserHelper
17163
17495
  },
17164
17496
  nextCommands: [
17165
17497
  "guardian status",
@@ -17168,12 +17500,10 @@ async function runSetupCommand(flags, options) {
17168
17500
  "guardian policy list",
17169
17501
  "guardian posture list",
17170
17502
  "guardian preferences show",
17171
- "guardian extension open-setup",
17172
- "guardian daemon pair --json",
17173
17503
  "guardian service install",
17174
- "guardian key-store install --yes",
17175
- nativeHostCommand
17176
- ]
17504
+ "guardian key-store install --yes"
17505
+ ],
17506
+ advancedCommands: ["guardian extension connect", nativeHostCommand, "guardian pair --json"]
17177
17507
  };
17178
17508
  write(
17179
17509
  stdout,
@@ -17186,8 +17516,11 @@ async function runSetupCommand(flags, options) {
17186
17516
  result.launch.opened ? `Opening: ${result.launch.controlTowerUrl}` : void 0,
17187
17517
  `MCP artifacts: ${result.mcp.writtenFiles.length > 0 ? result.mcp.writtenFiles.join(", ") : "skipped" in result.mcp && result.mcp.skipped ? "skipped" : "none"}`,
17188
17518
  `Browser setup: ${result.browserSetup.setupUrl}`,
17519
+ result.browserSetup.nativeHost.success ? `Browser connection: ready for ContextECF Halo (${result.browserSetup.extensionId})` : result.browserSetup.nativeHost.skipped ? "Browser connection: skipped" : `Browser connection: needs attention${result.browserSetup.nativeHost.error ? ` (${result.browserSetup.nativeHost.error})` : ""}`,
17520
+ "Extension setup: open ContextECF Halo and click Connect. No setup code needed.",
17189
17521
  "Token printed: no",
17190
- `Next: ${result.nextCommands.join("; ")}`
17522
+ `Next: ${result.nextCommands.join("; ")}`,
17523
+ "Help: run guardian connect if the browser says Local Guardian is not connected."
17191
17524
  ].filter(Boolean).join("\n")}
17192
17525
  `
17193
17526
  );
@@ -17262,8 +17595,8 @@ function buildGuardianDistributionReadiness(npmPreviewReady) {
17262
17595
  },
17263
17596
  aiToolIntegration: {
17264
17597
  mcpInstallCommand: "guardian mcp install --client=all --write",
17265
- browserSetupCommand: "guardian extension open-setup",
17266
- nativeHostInstallCommand: "guardian extension native-host install --extension-id=<browser-extension-id>"
17598
+ browserSetupCommand: "guardian connect",
17599
+ nativeHostInstallCommand: `guardian extension native-host install --extension-id=${GUARDIAN_HALO_CHROME_EXTENSION_ID}`
17267
17600
  },
17268
17601
  browserStoreHandoff: {
17269
17602
  status: npmPreviewReady ? "operator_handoff_ready_not_submitted" : "blocked_until_preview_ready",
@@ -17287,7 +17620,7 @@ function buildGuardianDistributionReadiness(npmPreviewReady) {
17287
17620
  boundaries: [
17288
17621
  "Use dry_run=true before public publication.",
17289
17622
  "dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
17290
- "The workflow can publish the npm preview package, upload evidence, and run public install smokes; it does not sign native installers or approve future browser-store listings.",
17623
+ "The workflow can publish the npm preview package, upload evidence, submit future Chrome Web Store updates for review when browser_store_publish=api, and run public install smokes; it does not sign native installers or prove future browser-store approval.",
17291
17624
  "GitHub Actions OIDC/provenance applies to CI release context; manual local publishes are recorded separately and should not claim CI provenance."
17292
17625
  ]
17293
17626
  },
@@ -17308,12 +17641,16 @@ function buildGuardianReleaseDispatchCommand(dryRun) {
17308
17641
  });
17309
17642
  }
17310
17643
  function buildGuardianReleaseDispatchCommandFor(input) {
17644
+ const publishAuth = input.publishAuth ?? "token";
17645
+ const browserStorePublish = input.browserStorePublish ?? "manual";
17311
17646
  return [
17312
17647
  `gh workflow run ${GUARDIAN_RELEASE_DISPATCH_WORKFLOW} \\`,
17313
17648
  ` -f release_version=${input.releaseVersion} \\`,
17314
17649
  ` -f channels=${input.channels} \\`,
17315
17650
  ` -f dry_run=${input.dryRun ? "true" : "false"} \\`,
17316
- ` -f run_docker_smoke=${input.runDockerSmoke ? "true" : "false"}`
17651
+ ` -f run_docker_smoke=${input.runDockerSmoke ? "true" : "false"} \\`,
17652
+ ` -f publish_auth=${publishAuth} \\`,
17653
+ ` -f browser_store_publish=${browserStorePublish}`
17317
17654
  ].join("\n");
17318
17655
  }
17319
17656
  async function runReleaseCommand(argv, flags, options) {
@@ -17420,11 +17757,23 @@ async function runReleaseCommand(argv, flags, options) {
17420
17757
  }
17421
17758
  const dryRun = flags.has("publish") ? false : booleanFlag(flags, "dry-run", true);
17422
17759
  const runDockerSmoke = booleanFlag(flags, "run-docker-smoke", true);
17760
+ const publishAuth = stringFlag(flags, "publish-auth") ?? "token";
17761
+ if (!isValidReleasePublishAuth(publishAuth)) {
17762
+ write(stderr, "Invalid --publish-auth. Expected one of: token, trusted_publisher.\n");
17763
+ return 1;
17764
+ }
17765
+ const browserStorePublish = stringFlag(flags, "browser-store-publish") ?? "manual";
17766
+ if (!isValidBrowserStorePublish(browserStorePublish)) {
17767
+ write(stderr, "Invalid --browser-store-publish. Expected one of: manual, api.\n");
17768
+ return 1;
17769
+ }
17423
17770
  const result = buildGuardianReleaseDispatchCommandResult({
17424
17771
  releaseVersion,
17425
17772
  channels,
17426
17773
  dryRun,
17427
- runDockerSmoke
17774
+ runDockerSmoke,
17775
+ publishAuth,
17776
+ browserStorePublish
17428
17777
  });
17429
17778
  write(stdout, renderGuardianReleaseDispatchCommand(result, flags));
17430
17779
  return 0;
@@ -17492,6 +17841,7 @@ function renderGuardianReleaseHelp(result, flags) {
17492
17841
  `;
17493
17842
  }
17494
17843
  function buildGuardianReleaseDispatchCommandResult(input) {
17844
+ const npmLaneSelected = input.channels === "all" || input.channels === "npm";
17495
17845
  return {
17496
17846
  schema_version: "contextecf/project-guardian-release-dispatch-command/v1",
17497
17847
  cli_version: GUARDIAN_CLI_VERSION,
@@ -17500,13 +17850,21 @@ function buildGuardianReleaseDispatchCommandResult(input) {
17500
17850
  channels: input.channels,
17501
17851
  dryRun: input.dryRun,
17502
17852
  runDockerSmoke: input.runDockerSmoke,
17853
+ publishAuth: input.publishAuth,
17854
+ browserStorePublish: input.browserStorePublish,
17503
17855
  command: buildGuardianReleaseDispatchCommandFor(input),
17504
- ...input.dryRun ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
17856
+ ...input.dryRun || input.publishAuth === "trusted_publisher" || !npmLaneSelected ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
17857
+ ...input.browserStorePublish === "api" && !input.dryRun ? {
17858
+ requiredBrowserStoreCredentialNames: [...GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES]
17859
+ } : {},
17505
17860
  provenance: "github_actions_oidc_supported",
17506
17861
  boundaries: [
17507
17862
  "Use dry_run=true before public publication.",
17508
- "dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
17509
- "This dispatch can publish the npm preview package, upload evidence, and run public install smokes; it does not sign native installers or approve future browser-store listings.",
17863
+ "dry_run=false with publish_auth=token requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
17864
+ "dry_run=false with publish_auth=trusted_publisher requires npm Trusted Publishing to be configured for this GitHub Actions workflow and package.",
17865
+ "browser_store_publish=manual keeps Chrome Web Store upload as an operator ZIP handoff.",
17866
+ "browser_store_publish=api uploads an existing Chrome Web Store item update and submits it for review when Chrome Web Store API secrets are configured.",
17867
+ "This dispatch can publish the npm preview package, upload evidence, submit future Chrome Web Store updates for review, and run public install smokes; it does not sign native installers or prove future browser-store approval.",
17510
17868
  "A release-dispatch command is operator guidance, not production-gate proof."
17511
17869
  ],
17512
17870
  tokenPrinted: false,
@@ -17525,7 +17883,10 @@ function renderGuardianReleaseDispatchCommand(result, flags) {
17525
17883
  `Workflow: ${result.workflow}`,
17526
17884
  `Channels: ${result.channels}`,
17527
17885
  `Docker smoke: ${result.runDockerSmoke ? "yes" : "no"}`,
17886
+ `Publish auth: ${result.publishAuth}`,
17887
+ `Browser store publish: ${result.browserStorePublish}`,
17528
17888
  result.requiredPublishCredentialName ? `Required repository secret: ${result.requiredPublishCredentialName}` : "Required repository secret: not needed for dry run",
17889
+ result.requiredBrowserStoreCredentialNames ? `Required browser-store secrets: ${result.requiredBrowserStoreCredentialNames.join(", ")}` : "Required browser-store secrets: not needed for manual browser handoff",
17529
17890
  "Command:",
17530
17891
  result.command,
17531
17892
  "Boundaries:",
@@ -17540,6 +17901,7 @@ function buildGuardianBrowserStoreHandoffCommandResult() {
17540
17901
  cli_version: GUARDIAN_CLI_VERSION,
17541
17902
  status: "chrome_distribution_proven_next_submission_pack_ready",
17542
17903
  primaryStore: "chrome_web_store",
17904
+ publicListingUrl: GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
17543
17905
  productionGate: {
17544
17906
  id: "browser-store-distribution",
17545
17907
  status: "proven",
@@ -17606,6 +17968,7 @@ function renderGuardianBrowserStoreHandoffCommand(result, flags) {
17606
17968
  "Project Guardian Browser Store Handoff",
17607
17969
  `Status: ${result.status}`,
17608
17970
  `Primary store: ${result.primaryStore}`,
17971
+ `Public listing: ${result.publicListingUrl}`,
17609
17972
  `Production gate: ${result.productionGate.id} (${result.productionGate.status})`,
17610
17973
  "1. Build submission pack:",
17611
17974
  result.commands.submissionPack,
@@ -17626,15 +17989,23 @@ function renderGuardianBrowserStoreHandoffCommand(result, flags) {
17626
17989
  `;
17627
17990
  }
17628
17991
  function buildGuardianReleaseSecretSetup() {
17992
+ const chromeWebStoreSecretMatcher = GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES.join("|");
17629
17993
  return {
17630
17994
  schema_version: "contextecf/project-guardian-release-secret-setup/v1",
17631
17995
  cli_version: GUARDIAN_CLI_VERSION,
17632
17996
  repository: GUARDIAN_RELEASE_REPOSITORY,
17633
17997
  requiredForPublish: "NPM_TOKEN",
17998
+ requiredForBrowserStoreApi: GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES,
17634
17999
  githubActionsSecretUrl: `https://github.com/${GUARDIAN_RELEASE_REPOSITORY}/settings/secrets/actions/new`,
17635
18000
  commands: {
17636
18001
  setNpmToken: `gh secret set NPM_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
18002
+ setChromeWebStoreClientId: `gh secret set CHROME_WEB_STORE_CLIENT_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
18003
+ setChromeWebStoreClientSecret: `gh secret set CHROME_WEB_STORE_CLIENT_SECRET --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
18004
+ setChromeWebStoreRefreshToken: `gh secret set CHROME_WEB_STORE_REFRESH_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
18005
+ setChromeWebStorePublisherId: `gh secret set CHROME_WEB_STORE_PUBLISHER_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
18006
+ setChromeWebStoreExtensionId: `gh secret set CHROME_WEB_STORE_EXTENSION_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
17637
18007
  verifyNpmTokenPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^NPM_TOKEN\\b'`,
18008
+ verifyChromeWebStoreSecretsPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^(${chromeWebStoreSecretMatcher})\\b'`,
17638
18009
  dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
17639
18010
  dryRun: true,
17640
18011
  releaseVersion: "<version>",
@@ -17646,13 +18017,23 @@ function buildGuardianReleaseSecretSetup() {
17646
18017
  releaseVersion: "<version>",
17647
18018
  channels: "all",
17648
18019
  runDockerSmoke: true
18020
+ }),
18021
+ browserStoreApiPublishDispatch: buildGuardianReleaseDispatchCommandFor({
18022
+ dryRun: false,
18023
+ releaseVersion: "<version>",
18024
+ channels: "browser",
18025
+ runDockerSmoke: true,
18026
+ publishAuth: "trusted_publisher",
18027
+ browserStorePublish: "api"
17649
18028
  })
17650
18029
  },
17651
18030
  boundaries: [
17652
18031
  "NPM_TOKEN belongs only in GitHub Actions repository secrets for guarded dry_run=false npm publication.",
18032
+ "Chrome Web Store API OAuth values belong only in GitHub Actions repository secrets for guarded browser_store_publish=api upload/submission.",
17653
18033
  "Do not paste npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content into chat, PR bodies, release evidence, or CLI output.",
17654
18034
  "Use dry_run=true before dry_run=false; dry-run dispatch does not require NPM_TOKEN.",
17655
- "Adding NPM_TOKEN enables the npm preview publish lane only; it does not close signed-installer, browser-store, high-risk desktop, or autonomous app production gates."
18035
+ "Adding NPM_TOKEN enables the npm preview publish lane only; it does not close signed-installer, browser-store, high-risk desktop, or autonomous app production gates.",
18036
+ "Chrome Web Store API secrets enable browser update upload/submission only; official review approval evidence is still required for production browser-store claims."
17656
18037
  ],
17657
18038
  tokenPrinted: false,
17658
18039
  rawContentIncluded: false
@@ -17666,16 +18047,27 @@ function renderGuardianReleaseSecretSetup(result, flags) {
17666
18047
  return `${[
17667
18048
  "Project Guardian Release Secret Setup",
17668
18049
  `Repository: ${result.repository}`,
17669
- `Required for publish: ${result.requiredForPublish}`,
18050
+ `Required for npm publish: ${result.requiredForPublish}`,
18051
+ `Required for Chrome Web Store API: ${result.requiredForBrowserStoreApi.join(", ")}`,
17670
18052
  `GitHub Actions secret page: ${result.githubActionsSecretUrl}`,
17671
- "Set secret:",
18053
+ "NPM publish secret:",
17672
18054
  result.commands.setNpmToken,
17673
- "Verify secret presence:",
18055
+ "Verify npm secret presence:",
17674
18056
  result.commands.verifyNpmTokenPresence,
18057
+ "Chrome Web Store API secrets:",
18058
+ result.commands.setChromeWebStoreClientId,
18059
+ result.commands.setChromeWebStoreClientSecret,
18060
+ result.commands.setChromeWebStoreRefreshToken,
18061
+ result.commands.setChromeWebStorePublisherId,
18062
+ result.commands.setChromeWebStoreExtensionId,
18063
+ "Verify Chrome Web Store API secret presence:",
18064
+ result.commands.verifyChromeWebStoreSecretsPresence,
17675
18065
  "Dry-run release command:",
17676
18066
  result.commands.dryRunDispatch,
17677
- "Publish release command:",
18067
+ "Default publish command with manual browser-store upload:",
17678
18068
  result.commands.publishDispatch,
18069
+ "Browser-store API publish command:",
18070
+ result.commands.browserStoreApiPublishDispatch,
17679
18071
  "Boundaries:",
17680
18072
  ...result.boundaries.map((boundary) => `- ${boundary}`),
17681
18073
  "Token printed: no"
@@ -17896,9 +18288,9 @@ function buildGuardianReleaseVerify(releaseVersion) {
17896
18288
  commands: {
17897
18289
  registryVersion: `npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
17898
18290
  publicInstall: `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
18291
+ chromeWebStoreListing: GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
17899
18292
  installedVersion: "guardian --version",
17900
18293
  setup: "guardian setup",
17901
- launch: "guardian launch",
17902
18294
  status: "guardian status",
17903
18295
  openControlTower: "guardian open",
17904
18296
  copyPasteLocalSmoke,
@@ -17927,9 +18319,8 @@ function buildGuardianReleasePaste(releaseVersion) {
17927
18319
  "guardian --version",
17928
18320
  "guardian stop",
17929
18321
  "guardian setup",
17930
- "guardian launch",
17931
- "guardian open",
17932
- "guardian status"
18322
+ "guardian status",
18323
+ "guardian open"
17933
18324
  ];
17934
18325
  return {
17935
18326
  schema_version: "contextecf/project-guardian-release-paste/v1",
@@ -17940,9 +18331,9 @@ function buildGuardianReleasePaste(releaseVersion) {
17940
18331
  command: commands.join("\n"),
17941
18332
  commands,
17942
18333
  boundaries: [
17943
- "This paste block verifies public npm visibility, global install, first-run setup, daemon launch, Control Tower open, and status.",
18334
+ "This paste block verifies public npm visibility, global install, stale-process cleanup, first-run setup, Local Guardian status, and Control Tower open.",
17944
18335
  "It does not publish to npm and must not include npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content.",
17945
- "guardian stop is included before setup so stale local daemons or local token mismatches are cleared before launch."
18336
+ "guardian stop is included before setup so stale Local Guardian processes or local token mismatches are cleared before setup relaunches the local service."
17946
18337
  ],
17947
18338
  tokenPrinted: false,
17948
18339
  rawContentIncluded: false
@@ -17969,18 +18360,19 @@ function renderGuardianReleaseVerify(result, flags) {
17969
18360
  `Status: ${result.status}`,
17970
18361
  "1. Confirm registry visibility:",
17971
18362
  result.commands.registryVersion,
17972
- "2. Install the published version:",
18363
+ "2. Confirm public Chrome Web Store listing:",
18364
+ result.commands.chromeWebStoreListing,
18365
+ "3. Install the published version:",
17973
18366
  result.commands.publicInstall,
17974
- "3. Confirm installed CLI version:",
18367
+ "4. Confirm installed CLI version:",
17975
18368
  result.commands.installedVersion,
17976
- "4. Run first-use smoke:",
18369
+ "5. Run first-use smoke:",
17977
18370
  result.commands.setup,
17978
- result.commands.launch,
17979
18371
  result.commands.status,
17980
18372
  result.commands.openControlTower,
17981
- "5. Copy-paste local smoke block:",
18373
+ "6. Copy-paste local smoke block:",
17982
18374
  result.commands.copyPasteLocalSmoke,
17983
- "6. Verify release evidence:",
18375
+ "7. Verify release evidence:",
17984
18376
  result.commands.publishStatusVerification,
17985
18377
  result.commands.finishLineStatus,
17986
18378
  "Evidence outputs:",
@@ -17997,6 +18389,12 @@ function isValidReleaseVersion(value) {
17997
18389
  function isValidReleaseChannels(value) {
17998
18390
  return ["all", "npm", "browser", "evidence"].includes(value);
17999
18391
  }
18392
+ function isValidReleasePublishAuth(value) {
18393
+ return value === "token" || value === "trusted_publisher";
18394
+ }
18395
+ function isValidBrowserStorePublish(value) {
18396
+ return value === "manual" || value === "api";
18397
+ }
18000
18398
  function renderGuardianProductionReadiness(result, flags) {
18001
18399
  if (flags.has("json")) {
18002
18400
  return `${JSON.stringify(result, null, 2)}
@@ -18099,9 +18497,9 @@ async function statusGuardian(flags, options) {
18099
18497
  `Profile: ${home}`,
18100
18498
  `Runtime profile: ${result.runtime.profileDaemonStatus}`,
18101
18499
  `Control Tower: ${result.controlTowerUrl ?? "not configured"}`,
18102
- `Daemon health: ${result.daemon.status}${result.daemon.statusCode ? ` (HTTP ${result.daemon.statusCode})` : ""}`,
18103
- result.daemon.error ? `Daemon detail: ${result.daemon.error}` : void 0,
18104
- result.daemonVersionMismatch ? `Daemon version: ${result.daemonVersionMismatch.daemonVersion} (this CLI is ${result.daemonVersionMismatch.cliVersion} \u2014 versions differ, likely because the CLI was reinstalled or changed version while this daemon kept running; run guardian stop && guardian launch to restart it on the current version)` : void 0,
18500
+ `Local Guardian: ${result.daemon.status}${result.daemon.statusCode ? ` (HTTP ${result.daemon.statusCode})` : ""}`,
18501
+ result.daemon.error ? `Connection detail: ${result.daemon.error}` : void 0,
18502
+ result.daemonVersionMismatch ? `Local Guardian version: ${result.daemonVersionMismatch.daemonVersion} (this CLI is ${result.daemonVersionMismatch.cliVersion} \u2014 versions differ, likely because the CLI was reinstalled or changed version while Local Guardian kept running; run guardian stop && guardian launch to restart it on the current version)` : void 0,
18105
18503
  `MCP stdio: ${result.runtime.mcpStdioAvailable ? "available" : "unavailable"}`,
18106
18504
  `Posture Profile: ${result.postureProfile.selected}`,
18107
18505
  `Prompt Coach: ${result.preferences.promptCoachMode}`,
@@ -18208,7 +18606,7 @@ async function runLaunchCommand(flags, options) {
18208
18606
  nextCommands: [
18209
18607
  "guardian open",
18210
18608
  "guardian status",
18211
- "guardian daemon pair --json",
18609
+ "Open ContextECF Halo and click Connect",
18212
18610
  "guardian policy list"
18213
18611
  ]
18214
18612
  };
@@ -18217,7 +18615,7 @@ async function runLaunchCommand(flags, options) {
18217
18615
  flags.has("json") ? `${JSON.stringify(result, null, 2)}
18218
18616
  ` : `${[
18219
18617
  "Project Guardian launched.",
18220
- `Daemon: ${result.daemonUrl}${result.reusedExistingDaemon ? " (already running)" : ""}`,
18618
+ `Local Guardian: ${result.daemonUrl}${result.reusedExistingDaemon ? " (already running)" : ""}`,
18221
18619
  `Control Tower: ${result.controlTowerUrl}`,
18222
18620
  shouldOpen ? `Opening: ${result.controlTowerUrl}` : void 0,
18223
18621
  "Next: guardian open; guardian status"
@@ -18328,14 +18726,14 @@ async function runStartCommand(flags, options) {
18328
18726
  controlTowerUrl: requestedControlTowerUrl,
18329
18727
  healthUrl,
18330
18728
  healthStatus: "reachable",
18331
- nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
18729
+ nextCommands: ["guardian open", "guardian status", "Open ContextECF Halo and click Connect"]
18332
18730
  };
18333
18731
  write(
18334
18732
  stdout,
18335
18733
  flags.has("json") ? `${JSON.stringify(result2, null, 2)}
18336
18734
  ` : `${[
18337
- "Guardian daemon already running.",
18338
- `Daemon: ${requestedDaemonUrl}`,
18735
+ "Local Guardian already running.",
18736
+ `Local Guardian: ${requestedDaemonUrl}`,
18339
18737
  `Control Tower: ${requestedControlTowerUrl}`,
18340
18738
  "Next: guardian open"
18341
18739
  ].join("\n")}
@@ -18344,7 +18742,7 @@ async function runStartCommand(flags, options) {
18344
18742
  return 0;
18345
18743
  }
18346
18744
  if (!options.startDetachedDaemon) {
18347
- write(stderr, "Guardian detached daemon launcher is unavailable in this runtime.\n");
18745
+ write(stderr, "Guardian local background launcher is unavailable in this runtime.\n");
18348
18746
  return 1;
18349
18747
  }
18350
18748
  const started = await options.startDetachedDaemon({ home, host, port: selected.port });
@@ -18365,14 +18763,14 @@ async function runStartCommand(flags, options) {
18365
18763
  pid: started.pid,
18366
18764
  healthUrl,
18367
18765
  healthStatus: existing.error ? "unreachable" : "not_reachable",
18368
- nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
18766
+ nextCommands: ["guardian open", "guardian status", "Open ContextECF Halo and click Connect"]
18369
18767
  };
18370
18768
  write(
18371
18769
  stdout,
18372
18770
  flags.has("json") ? `${JSON.stringify(result, null, 2)}
18373
18771
  ` : `${[
18374
- "Guardian daemon start requested.",
18375
- `Daemon: ${daemonUrl}`,
18772
+ "Local Guardian start requested.",
18773
+ `Local Guardian: ${daemonUrl}`,
18376
18774
  `Control Tower: ${controlTowerUrl}`,
18377
18775
  started.pid ? `PID: ${started.pid}` : void 0,
18378
18776
  "Next: guardian open"
@@ -18383,8 +18781,8 @@ async function runStartCommand(flags, options) {
18383
18781
  }
18384
18782
  function renderDaemonTokenMismatchMessage(requestedDaemonUrl, port) {
18385
18783
  return [
18386
- `Guardian found another daemon or container at ${requestedDaemonUrl}, but it rejected this profile's local runtime token.`,
18387
- "This usually means an older Guardian daemon or Docker demo is still using the port.",
18784
+ `Guardian found another local service or container at ${requestedDaemonUrl}, but it rejected this profile's local connection token.`,
18785
+ "This usually means an older Guardian background service or Docker demo is still using the port.",
18388
18786
  `Recovery: stop the other process/container, or run Guardian on a different port with guardian launch --port=${port + 1}.`,
18389
18787
  `Diagnostics: guardian status; docker ps --filter publish=${port}`,
18390
18788
  ""
@@ -18417,7 +18815,7 @@ async function runStopCommand(flags, options) {
18417
18815
  if (!stopped.ok) {
18418
18816
  write(
18419
18817
  stderr,
18420
- `Guardian daemon did not stop cleanly${stopped.statusCode ? ` (HTTP ${stopped.statusCode})` : ""}: ${stopped.error ?? "unknown_error"}
18818
+ `Local Guardian did not stop cleanly${stopped.statusCode ? ` (HTTP ${stopped.statusCode})` : ""}: ${stopped.error ?? "unknown_error"}
18421
18819
  `
18422
18820
  );
18423
18821
  return 1;
@@ -18428,12 +18826,12 @@ async function runStopCommand(flags, options) {
18428
18826
  success: true,
18429
18827
  daemonStatus: profile.runtime.daemon_status,
18430
18828
  stopUrl: stopUrl.url,
18431
- note: "Guardian daemon stop requested."
18829
+ note: "Local Guardian stop requested."
18432
18830
  };
18433
18831
  write(
18434
18832
  stdout,
18435
18833
  flags.has("json") ? `${JSON.stringify(result, null, 2)}
18436
- ` : `${["Guardian daemon stop requested.", "Status: not_started_mvp"].join("\n")}
18834
+ ` : `${["Local Guardian stop requested.", "Status: not_started_mvp"].join("\n")}
18437
18835
  `
18438
18836
  );
18439
18837
  return 0;
@@ -18505,7 +18903,7 @@ Proof: ${result2.proofPath}
18505
18903
  }
18506
18904
  const host = stringFlag(flags, "host") ?? "127.0.0.1";
18507
18905
  if (!isLoopbackHost(host)) {
18508
- write(stderr, "Guardian service supervision only accepts loopback daemon hosts.\n");
18906
+ write(stderr, "Guardian service supervision only accepts loopback Local Guardian hosts.\n");
18509
18907
  return 1;
18510
18908
  }
18511
18909
  const port = numberFlag(flags, "port") ?? 4317;
@@ -18762,7 +19160,7 @@ async function daemonPair(flags, options) {
18762
19160
  [GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY]: bridgeConfig,
18763
19161
  [GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY]: token
18764
19162
  },
18765
- note: "Store this token in the Guardian browser extension local settings, then run guardian daemon serve."
19163
+ note: "Advanced fallback only. Most users should run guardian setup, open ContextECF Halo, and click Connect."
18766
19164
  };
18767
19165
  if (flags.has("json")) {
18768
19166
  return { exitCode: 0, message: `${JSON.stringify(pairing, null, 2)}
@@ -18771,13 +19169,10 @@ async function daemonPair(flags, options) {
18771
19169
  return {
18772
19170
  exitCode: 0,
18773
19171
  message: `${[
18774
- "Guardian browser bridge pairing",
18775
- `Storage key: ${pairing.storageKey}`,
18776
- `Loopback URL: ${pairing.loopbackBaseUrl}`,
18777
- `Transport: ${pairing.transport}`,
18778
- `Native host: ${pairing.nativeHostName}`,
18779
- `Token: ${pairing.token}`,
18780
- pairing.note
19172
+ "Guardian browser connection uses one-click setup now.",
19173
+ "Run guardian connect, then open ContextECF Halo and click Connect.",
19174
+ "Support setup codes are only printed by guardian pair --json.",
19175
+ "Token printed: no"
18781
19176
  ].join("\n")}
18782
19177
  `
18783
19178
  };
@@ -18786,6 +19181,9 @@ async function runExtensionCommand(argv, flags, options) {
18786
19181
  const subcommand = argv[0] ?? "native-host";
18787
19182
  const stdout = options.stdout ?? process.stdout;
18788
19183
  const stderr = options.stderr ?? process.stderr;
19184
+ if (subcommand === "connect") {
19185
+ return runExtensionConnectCommand(flags, options);
19186
+ }
18789
19187
  if (subcommand === "open-setup") {
18790
19188
  return runExtensionOpenSetupCommand(flags, options);
18791
19189
  }
@@ -18973,13 +19371,18 @@ Re-run with --force to replace it.
18973
19371
  registryMutationRequested: writeRegistry,
18974
19372
  registryProofPath,
18975
19373
  tokenPrinted: false,
18976
- nextCommands: ["guardian launch", "guardian daemon pair --json"]
19374
+ nextCommands: [
19375
+ "guardian launch",
19376
+ "Open ContextECF Halo and click Connect",
19377
+ "guardian extension native-host status"
19378
+ ],
19379
+ advancedCommands: ["guardian pair --json"]
18977
19380
  };
18978
19381
  write(
18979
19382
  stdout,
18980
19383
  flags.has("json") ? `${JSON.stringify(result, null, 2)}
18981
19384
  ` : `${[
18982
- "Guardian native host installed.",
19385
+ "Guardian browser connection installed.",
18983
19386
  `Browser: ${browser}`,
18984
19387
  `Host: ${plan.hostName}`,
18985
19388
  `Manifest: ${plan.manifestPath}`,
@@ -18994,6 +19397,121 @@ Re-run with --force to replace it.
18994
19397
  );
18995
19398
  return 0;
18996
19399
  }
19400
+ async function runExtensionConnectCommand(flags, options) {
19401
+ const stdout = options.stdout ?? process.stdout;
19402
+ const stderr = options.stderr ?? process.stderr;
19403
+ const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
19404
+ const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
19405
+ if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
19406
+ write(
19407
+ stderr,
19408
+ "Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
19409
+ );
19410
+ return 1;
19411
+ }
19412
+ const install = JSON.parse(await installGuardian(/* @__PURE__ */ new Map([["json", true]]), options));
19413
+ let launchOutput = "";
19414
+ const launchFlags = new Map([
19415
+ ["json", true],
19416
+ ["print", true],
19417
+ ...copyStringFlags(flags, ["host", "port"])
19418
+ ]);
19419
+ const launchExitCode = await runLaunchCommand(launchFlags, {
19420
+ ...options,
19421
+ stdout: {
19422
+ write: (chunk) => {
19423
+ launchOutput += chunk.toString();
19424
+ return true;
19425
+ }
19426
+ },
19427
+ stderr
19428
+ });
19429
+ if (launchExitCode !== 0) {
19430
+ return launchExitCode;
19431
+ }
19432
+ const launch = JSON.parse(launchOutput);
19433
+ const helperFlags = new Map([
19434
+ ["json", true],
19435
+ ["force", true],
19436
+ ["extension-id", extensionId],
19437
+ ...copyStringFlags(flags, ["browser", "target"])
19438
+ ]);
19439
+ if ((options.platform ?? process.platform) === "win32") {
19440
+ helperFlags.set("write-registry", true);
19441
+ helperFlags.set("yes", true);
19442
+ }
19443
+ let helperOutput = "";
19444
+ let helperError = "";
19445
+ const helperExitCode = await runExtensionCommand(["native-host", "install"], helperFlags, {
19446
+ ...options,
19447
+ stdout: {
19448
+ write: (chunk) => {
19449
+ helperOutput += chunk.toString();
19450
+ return true;
19451
+ }
19452
+ },
19453
+ stderr: {
19454
+ write: (chunk) => {
19455
+ helperError += chunk.toString();
19456
+ return true;
19457
+ }
19458
+ }
19459
+ });
19460
+ if (helperExitCode !== 0) {
19461
+ write(
19462
+ stderr,
19463
+ helperError.trim() ? `${helperError.trim()}
19464
+ ` : "Guardian could not prepare the browser connection. Run guardian setup, then try again.\n"
19465
+ );
19466
+ return helperExitCode;
19467
+ }
19468
+ const helper = JSON.parse(helperOutput);
19469
+ const result = {
19470
+ schema_version: "contextecf/project-guardian-browser-connect/v1",
19471
+ success: true,
19472
+ extensionId,
19473
+ defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
19474
+ install: {
19475
+ profileDir: install.profileDir,
19476
+ tokenCreated: install.tokenCreated,
19477
+ tokenPrinted: false
19478
+ },
19479
+ localGuardian: {
19480
+ running: true,
19481
+ opened: launch.opened,
19482
+ reusedExistingDaemon: launch.reusedExistingDaemon,
19483
+ daemonUrl: launch.daemonUrl,
19484
+ controlTowerUrl: launch.controlTowerUrl,
19485
+ pid: launch.pid,
19486
+ healthStatus: launch.healthStatus
19487
+ },
19488
+ browser: helper.browser,
19489
+ helperInstalled: true,
19490
+ helperStatus: {
19491
+ hostName: helper.hostName,
19492
+ manifestPath: helper.manifestPath,
19493
+ allowedOrigins: helper.allowedOrigins,
19494
+ tokenPrinted: helper.tokenPrinted
19495
+ },
19496
+ tokenPrinted: false,
19497
+ nextCommands: ["Open ContextECF Halo and click Connect", "guardian open", "guardian status"],
19498
+ supportCommands: ["guardian extension open-setup --print", "guardian pair --json"]
19499
+ };
19500
+ write(
19501
+ stdout,
19502
+ flags.has("json") ? `${JSON.stringify(result, null, 2)}
19503
+ ` : `${[
19504
+ "Guardian browser connection is ready.",
19505
+ `Local Guardian: ${result.localGuardian.daemonUrl}${result.localGuardian.reusedExistingDaemon ? " (already running)" : ""}`,
19506
+ `Browser: ${result.browser}`,
19507
+ "Next: open ContextECF Halo and click Connect.",
19508
+ "No setup code needed.",
19509
+ "Token printed: no"
19510
+ ].join("\n")}
19511
+ `
19512
+ );
19513
+ return 0;
19514
+ }
18997
19515
  async function runExtensionOpenSetupCommand(flags, options) {
18998
19516
  const stdout = options.stdout ?? process.stdout;
18999
19517
  const stderr = options.stderr ?? process.stderr;
@@ -19003,8 +19521,9 @@ async function runExtensionOpenSetupCommand(flags, options) {
19003
19521
  write(stderr, "Guardian is not installed. Run guardian install first.\n");
19004
19522
  return 1;
19005
19523
  }
19006
- const extensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
19007
- if (extensionId && !isValidChromeExtensionId(extensionId)) {
19524
+ const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
19525
+ const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
19526
+ if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
19008
19527
  write(
19009
19528
  stderr,
19010
19529
  "Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
@@ -19018,22 +19537,24 @@ async function runExtensionOpenSetupCommand(flags, options) {
19018
19537
  return 1;
19019
19538
  }
19020
19539
  const setupUrl = buildControlTowerSetupUrl(resolved.url);
19021
- const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId ?? "<browser-extension-id>"}`;
19540
+ const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId}`;
19022
19541
  const result = {
19023
19542
  schema_version: "contextecf/project-guardian-extension-setup/v1",
19024
19543
  success: true,
19025
19544
  opened: !flags.has("print"),
19026
19545
  controlTowerUrl: resolved.url,
19027
19546
  setupUrl,
19028
- extensionId: extensionId ?? null,
19547
+ extensionId,
19548
+ defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
19029
19549
  tokenPrinted: false,
19030
19550
  nextCommands: [
19031
19551
  "guardian launch",
19032
- "guardian daemon pair --json",
19033
19552
  nativeHostCommand,
19034
- "guardian extension native-host status"
19553
+ "guardian extension native-host status",
19554
+ "Open ContextECF Halo and click Connect"
19035
19555
  ],
19036
- note: extensionId ? "Guardian browser setup opened with a concrete native host install command." : "Guardian browser setup opened with placeholder extension-id guidance."
19556
+ advancedCommands: ["guardian pair --json"],
19557
+ note: extensionId ? "Guardian browser setup opened for ContextECF Halo." : "Guardian browser setup opened."
19037
19558
  };
19038
19559
  if (result.opened) {
19039
19560
  const opener = options.openUrl ?? ((url2) => openUrlInDefaultBrowser(url2, options));
@@ -19045,7 +19566,8 @@ async function runExtensionOpenSetupCommand(flags, options) {
19045
19566
  ` : `${[
19046
19567
  result.opened ? `Opening Guardian browser setup: ${setupUrl}` : `Guardian browser setup: ${setupUrl}`,
19047
19568
  "Token printed: no",
19048
- `Next: ${result.nextCommands.join("; ")}`
19569
+ `Next: ${result.nextCommands.join("; ")}`,
19570
+ `Advanced fallback: ${result.advancedCommands.join("; ")}`
19049
19571
  ].join("\n")}
19050
19572
  `
19051
19573
  );
@@ -19572,7 +20094,7 @@ function buildGuardianServiceArtifact(input) {
19572
20094
  if (input.platform === "systemd") {
19573
20095
  return `${[
19574
20096
  "[Unit]",
19575
- "Description=Project Guardian local daemon",
20097
+ "Description=Project Guardian Local Guardian background service",
19576
20098
  "After=network.target",
19577
20099
  "",
19578
20100
  "[Service]",
@@ -19591,7 +20113,7 @@ function buildGuardianServiceArtifact(input) {
19591
20113
  '<?xml version="1.0" encoding="UTF-16"?>',
19592
20114
  '<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">',
19593
20115
  " <RegistrationInfo>",
19594
- " <Description>Project Guardian local daemon</Description>",
20116
+ " <Description>Project Guardian Local Guardian background service</Description>",
19595
20117
  " </RegistrationInfo>",
19596
20118
  " <Triggers>",
19597
20119
  " <LogonTrigger><Enabled>true</Enabled></LogonTrigger>",
@@ -20573,6 +21095,59 @@ async function runReceiptsCommand(argv, flags, options) {
20573
21095
  write(stdout, await verifyReceipts(flags, options));
20574
21096
  return 0;
20575
21097
  }
21098
+ async function runCoachCommand(argv, flags, options) {
21099
+ const subcommand = argv[0] ?? "options";
21100
+ const stdout = options.stdout ?? process.stdout;
21101
+ const stderr = options.stderr ?? process.stderr;
21102
+ if (subcommand === "options" || subcommand === "catalog") {
21103
+ write(stdout, renderGuardianPromptCardOptions(buildGuardianPromptCardOptions(), flags));
21104
+ return 0;
21105
+ }
21106
+ write(stderr, `Unknown Guardian coach command: ${subcommand}
21107
+ `);
21108
+ return 1;
21109
+ }
21110
+ function buildGuardianPromptCardOptions() {
21111
+ return {
21112
+ schema_version: "contextecf/project-guardian-prompt-card-options/v1",
21113
+ cli_version: GUARDIAN_CLI_VERSION,
21114
+ status: "catalog_ready",
21115
+ summary: "Guardian prompt cards keep the user in control: warnings and safer rewrites can be sent as-is, while hard blocks cannot.",
21116
+ catalog: GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG,
21117
+ rules: [
21118
+ "Show a clear reason before asking the user to decide.",
21119
+ "Offer Send as-is for warnings and safer rewrites when policy allows override.",
21120
+ "Never offer Send as-is for hard blocks or unavailable Local Guardian checks.",
21121
+ "Keep Edit prompt available as the safe path for every visible send-time card.",
21122
+ "Do not store raw sensitive prompt text in this catalog or CLI output."
21123
+ ],
21124
+ tokenPrinted: false,
21125
+ rawContentIncluded: false
21126
+ };
21127
+ }
21128
+ function renderGuardianPromptCardOptions(result, flags) {
21129
+ if (flags.has("json")) {
21130
+ return `${JSON.stringify(result, null, 2)}
21131
+ `;
21132
+ }
21133
+ return `${[
21134
+ "Guardian Prompt Card Options",
21135
+ result.summary,
21136
+ "",
21137
+ "Programmed cards:",
21138
+ ...result.catalog.map((entry) => {
21139
+ const visibleActions = entry.actions.filter((action) => action.visibleToUser).map((action) => action.label);
21140
+ const labels = visibleActions.length > 0 ? visibleActions.join(", ") : "Prompt sends automatically";
21141
+ return `- ${entry.cardStyle}: ${labels}`;
21142
+ }),
21143
+ "",
21144
+ "Rules:",
21145
+ ...result.rules.map((rule) => `- ${rule}`),
21146
+ "Token printed: no",
21147
+ "Raw prompt content included: no"
21148
+ ].join("\n")}
21149
+ `;
21150
+ }
20576
21151
  async function runPolicyCommand(argv, flags, options) {
20577
21152
  const subcommand = argv[0] ?? "list";
20578
21153
  const stdout = options.stdout ?? process.stdout;
@@ -23003,6 +23578,7 @@ function openUrlInDefaultBrowser(url2, options = {}) {
23003
23578
  });
23004
23579
  }
23005
23580
  export {
23581
+ GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES,
23006
23582
  GUARDIAN_CLI_VERSION,
23007
23583
  GUARDIAN_CONTROL_TOWER_URL_ENV,
23008
23584
  GUARDIAN_DEFAULT_CONTROL_TOWER_URL,
@@ -23012,6 +23588,8 @@ export {
23012
23588
  GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION,
23013
23589
  GUARDIAN_FIRST_RUN_COMMAND,
23014
23590
  GUARDIAN_GLOBAL_INSTALL_COMMAND,
23591
+ GUARDIAN_HALO_CHROME_EXTENSION_ID,
23592
+ GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
23015
23593
  GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV,
23016
23594
  GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV,
23017
23595
  GUARDIAN_NOT_PROVEN_PRODUCTION_GATES,
@@ -23024,6 +23602,7 @@ export {
23024
23602
  GUARDIAN_POSTURE_PROFILE_CATALOG,
23025
23603
  GUARDIAN_POSTURE_PROFILE_IDS,
23026
23604
  GUARDIAN_PROFILE_SCHEMA_VERSION,
23605
+ GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG,
23027
23606
  GUARDIAN_PROVIDER_IDS,
23028
23607
  GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
23029
23608
  GUARDIAN_RELEASE_REPOSITORY,