@contextecf/guardian-cli 0.1.3 → 0.1.4

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.
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __esm = (fn, res) => function __init() {
5
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ var __esm = (fn, res, err) => function __init() {
5
+ if (err) throw err[0];
6
+ try {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ } catch (e) {
9
+ throw err = [e], e;
10
+ }
6
11
  };
7
12
  var __export = (target, all) => {
8
13
  for (var name in all)
@@ -73,7 +78,7 @@ var init_core = __esm({
73
78
  NEVER = /* @__PURE__ */ Object.freeze({
74
79
  status: "aborted"
75
80
  });
76
- $brand = Symbol("zod_brand");
81
+ $brand = /* @__PURE__ */ Symbol("zod_brand");
77
82
  $ZodAsyncError = class extends Error {
78
83
  constructor() {
79
84
  super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
@@ -10242,8 +10247,8 @@ function registry() {
10242
10247
  var _a2, $output, $input, $ZodRegistry, globalRegistry;
10243
10248
  var init_registries = __esm({
10244
10249
  "node_modules/zod/v4/core/registries.js"() {
10245
- $output = Symbol("ZodOutput");
10246
- $input = Symbol("ZodInput");
10250
+ $output = /* @__PURE__ */ Symbol("ZodOutput");
10251
+ $input = /* @__PURE__ */ Symbol("ZodInput");
10247
10252
  $ZodRegistry = class {
10248
10253
  constructor() {
10249
10254
  this._map = /* @__PURE__ */ new WeakMap();
@@ -17052,6 +17057,8 @@ async function runGuardianCli(argv, options = {}) {
17052
17057
  write(stdout, renderGuardianProductionReadiness(readiness, flags));
17053
17058
  return flags.has("strict") && (readiness.npmPreview.status !== "ready" || readiness.fullProduction.status !== "ready") ? 1 : 0;
17054
17059
  }
17060
+ case "release":
17061
+ return runReleaseCommand(argv.slice(1), flags, options);
17055
17062
  case "open":
17056
17063
  return runControlTowerOpenCommand(flags, options);
17057
17064
  case "status":
@@ -17205,7 +17212,7 @@ async function installGuardian(flags, options = {}) {
17205
17212
  `First run: ${GUARDIAN_FIRST_RUN_COMMAND}`,
17206
17213
  `Open Control Tower: ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}`,
17207
17214
  `No global install: ${GUARDIAN_NPX_SETUP_COMMAND}`,
17208
- "Next: guardian setup; guardian doctor; guardian readiness; guardian launch; guardian mcp install; guardian extension open-setup; guardian daemon pair --json; guardian extension native-host install --extension-id=<browser-extension-id>"
17215
+ "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>"
17209
17216
  ].join("\n")}
17210
17217
  `;
17211
17218
  }
@@ -17252,7 +17259,7 @@ async function runSetupCommand(flags, options) {
17252
17259
  ["json", true],
17253
17260
  ...copyStringFlags(flags, ["host", "port"])
17254
17261
  ]);
17255
- if (flags.has("print")) {
17262
+ if (!flags.has("open") || flags.has("print")) {
17256
17263
  launchFlags.set("print", true);
17257
17264
  }
17258
17265
  const launchExitCode = await runLaunchCommand(launchFlags, {
@@ -17331,6 +17338,7 @@ async function runSetupCommand(flags, options) {
17331
17338
  nextCommands: [
17332
17339
  "guardian status",
17333
17340
  "guardian readiness",
17341
+ "guardian open",
17334
17342
  "guardian policy list",
17335
17343
  "guardian posture list",
17336
17344
  "guardian preferences show",
@@ -17408,10 +17416,761 @@ async function buildGuardianProductionReadinessStatus(home, profile, env = proce
17408
17416
  productionGateEvidenceStatus: protectedEvidence.productionGateEvidence?.status ?? "not_recorded",
17409
17417
  productionGateEvidencePath: protectedEvidence.productionGateEvidence?.evidencePath
17410
17418
  },
17419
+ distribution: buildGuardianDistributionReadiness(npmPreviewReady),
17420
+ tokenPrinted: false,
17421
+ rawContentIncluded: false
17422
+ };
17423
+ }
17424
+ function buildGuardianDistributionReadiness(npmPreviewReady) {
17425
+ return {
17426
+ status: npmPreviewReady ? "preview_install_ready" : "setup_or_release_evidence_required",
17427
+ oneLineInstallCommand: GUARDIAN_GLOBAL_INSTALL_COMMAND,
17428
+ oneLineTryCommand: GUARDIAN_NPX_SETUP_COMMAND,
17429
+ openControlTowerCommand: GUARDIAN_OPEN_CONTROL_TOWER_COMMAND,
17430
+ localUserCommands: {
17431
+ setup: GUARDIAN_FIRST_RUN_COMMAND,
17432
+ launch: "guardian launch",
17433
+ open: "guardian open",
17434
+ status: "guardian status",
17435
+ readiness: "guardian readiness"
17436
+ },
17437
+ aiToolIntegration: {
17438
+ mcpInstallCommand: "guardian mcp install --client=all --write",
17439
+ browserSetupCommand: "guardian extension open-setup",
17440
+ nativeHostInstallCommand: "guardian extension native-host install --extension-id=<browser-extension-id>"
17441
+ },
17442
+ browserStoreHandoff: {
17443
+ status: npmPreviewReady ? "operator_handoff_ready_not_submitted" : "blocked_until_preview_ready",
17444
+ submissionPackCommand: "npm run guardian:browser-store:submission-pack",
17445
+ closeoutChecklistPath: "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
17446
+ productionGateStatus: "not_proven"
17447
+ },
17448
+ enterpriseDeployment: {
17449
+ status: "managed_rollout_ready_for_customer_pack",
17450
+ note: "Use enterprise policy packs, managed browser deployment, and customer evidence as a separate company or school-district rollout lane; it does not prove public browser-store distribution."
17451
+ },
17452
+ releaseAutomation: {
17453
+ workflow: GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
17454
+ dryRunCommand: buildGuardianReleaseDispatchCommand(true),
17455
+ publishCommand: buildGuardianReleaseDispatchCommand(false),
17456
+ requiredPublishCredentialName: "NPM_TOKEN",
17457
+ channels: ["all", "npm", "browser", "evidence"],
17458
+ defaultDockerSmoke: true,
17459
+ provenance: "github_actions_oidc_supported",
17460
+ status: npmPreviewReady ? "ready_for_dispatch_after_preview_evidence" : "blocked_until_preview_release_evidence_passes",
17461
+ boundaries: [
17462
+ "Use dry_run=true before public publication.",
17463
+ "dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
17464
+ "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.",
17465
+ "GitHub Actions OIDC/provenance applies to CI release context; manual local publishes are recorded separately and should not claim CI provenance."
17466
+ ]
17467
+ },
17468
+ boundaries: [
17469
+ "One-line npm install and Control Tower launch prove preview distribution only.",
17470
+ "Chrome Web Store distribution is proven for the evidenced ContextECF Halo listing; future store submissions still require fresh official review evidence.",
17471
+ "Enterprise managed deployment can support company or school-district rollout but remains a separate rollout lane.",
17472
+ "MCP and browser setup commands must not print runtime tokens, raw prompts, raw responses, source archives, source maps, credentials, or private policy packs."
17473
+ ]
17474
+ };
17475
+ }
17476
+ function buildGuardianReleaseDispatchCommand(dryRun) {
17477
+ return buildGuardianReleaseDispatchCommandFor({
17478
+ dryRun,
17479
+ releaseVersion: "<version>",
17480
+ channels: "all",
17481
+ runDockerSmoke: true
17482
+ });
17483
+ }
17484
+ function buildGuardianReleaseDispatchCommandFor(input2) {
17485
+ return [
17486
+ `gh workflow run ${GUARDIAN_RELEASE_DISPATCH_WORKFLOW} \\`,
17487
+ ` -f release_version=${input2.releaseVersion} \\`,
17488
+ ` -f channels=${input2.channels} \\`,
17489
+ ` -f dry_run=${input2.dryRun ? "true" : "false"} \\`,
17490
+ ` -f run_docker_smoke=${input2.runDockerSmoke ? "true" : "false"}`
17491
+ ].join("\n");
17492
+ }
17493
+ async function runReleaseCommand(argv, flags, options) {
17494
+ const subcommand = argv[0];
17495
+ const stdout = options.stdout ?? process.stdout;
17496
+ const stderr = options.stderr ?? process.stderr;
17497
+ if (!subcommand || subcommand === "help" || subcommand === "quickstart") {
17498
+ write(stdout, renderGuardianReleaseHelp(buildGuardianReleaseHelp(), flags));
17499
+ return 0;
17500
+ }
17501
+ if (subcommand === "browser-store" || subcommand === "browser-store-handoff" || subcommand === "store") {
17502
+ write(
17503
+ stdout,
17504
+ renderGuardianBrowserStoreHandoffCommand(
17505
+ buildGuardianBrowserStoreHandoffCommandResult(),
17506
+ flags
17507
+ )
17508
+ );
17509
+ return 0;
17510
+ }
17511
+ if (subcommand === "secrets" || subcommand === "secret-setup" || subcommand === "npm-token") {
17512
+ write(stdout, renderGuardianReleaseSecretSetup(buildGuardianReleaseSecretSetup(), flags));
17513
+ return 0;
17514
+ }
17515
+ if (subcommand === "checklist" || subcommand === "plan") {
17516
+ const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
17517
+ if (!releaseVersion2) {
17518
+ write(
17519
+ stderr,
17520
+ "Missing release version. Usage: guardian release checklist --version=<semver>\n"
17521
+ );
17522
+ return 1;
17523
+ }
17524
+ if (!isValidReleaseVersion(releaseVersion2)) {
17525
+ write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
17526
+ return 1;
17527
+ }
17528
+ write(
17529
+ stdout,
17530
+ renderGuardianReleaseChecklist(buildGuardianReleaseChecklist(releaseVersion2), flags)
17531
+ );
17532
+ return 0;
17533
+ }
17534
+ if (subcommand === "flow" || subcommand === "train" || subcommand === "next") {
17535
+ const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
17536
+ if (!releaseVersion2) {
17537
+ write(stderr, "Missing release version. Usage: guardian release flow --version=<semver>\n");
17538
+ return 1;
17539
+ }
17540
+ if (!isValidReleaseVersion(releaseVersion2)) {
17541
+ write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
17542
+ return 1;
17543
+ }
17544
+ write(stdout, renderGuardianReleaseFlow(buildGuardianReleaseFlow(releaseVersion2), flags));
17545
+ return 0;
17546
+ }
17547
+ if (subcommand === "verify" || subcommand === "post-release") {
17548
+ const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
17549
+ if (!releaseVersion2) {
17550
+ write(stderr, "Missing release version. Usage: guardian release verify --version=<semver>\n");
17551
+ return 1;
17552
+ }
17553
+ if (!isValidReleaseVersion(releaseVersion2)) {
17554
+ write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
17555
+ return 1;
17556
+ }
17557
+ write(stdout, renderGuardianReleaseVerify(buildGuardianReleaseVerify(releaseVersion2), flags));
17558
+ return 0;
17559
+ }
17560
+ if (subcommand === "paste" || subcommand === "smoke" || subcommand === "install-smoke") {
17561
+ const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
17562
+ if (!releaseVersion2) {
17563
+ write(stderr, "Missing release version. Usage: guardian release paste --version=<semver>\n");
17564
+ return 1;
17565
+ }
17566
+ if (!isValidReleaseVersion(releaseVersion2)) {
17567
+ write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
17568
+ return 1;
17569
+ }
17570
+ write(stdout, renderGuardianReleasePaste(buildGuardianReleasePaste(releaseVersion2), flags));
17571
+ return 0;
17572
+ }
17573
+ if (subcommand !== "command" && subcommand !== "dispatch") {
17574
+ write(stderr, `Unknown Guardian release command: ${subcommand}
17575
+ `);
17576
+ return 1;
17577
+ }
17578
+ const releaseVersion = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
17579
+ if (!releaseVersion) {
17580
+ write(
17581
+ stderr,
17582
+ "Missing release version. Usage: guardian release command --version=<semver> [--publish|--dry-run=false]\n"
17583
+ );
17584
+ return 1;
17585
+ }
17586
+ if (!isValidReleaseVersion(releaseVersion)) {
17587
+ write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
17588
+ return 1;
17589
+ }
17590
+ const channels = stringFlag(flags, "channels") ?? "all";
17591
+ if (!isValidReleaseChannels(channels)) {
17592
+ write(stderr, "Invalid --channels. Expected one of: all, npm, browser, evidence.\n");
17593
+ return 1;
17594
+ }
17595
+ const dryRun = flags.has("publish") ? false : booleanFlag(flags, "dry-run", true);
17596
+ const runDockerSmoke = booleanFlag(flags, "run-docker-smoke", true);
17597
+ const result = buildGuardianReleaseDispatchCommandResult({
17598
+ releaseVersion,
17599
+ channels,
17600
+ dryRun,
17601
+ runDockerSmoke
17602
+ });
17603
+ write(stdout, renderGuardianReleaseDispatchCommand(result, flags));
17604
+ return 0;
17605
+ }
17606
+ function buildGuardianReleaseHelp() {
17607
+ return {
17608
+ schema_version: "contextecf/project-guardian-release-help/v1",
17609
+ cli_version: GUARDIAN_CLI_VERSION,
17610
+ repository: GUARDIAN_RELEASE_REPOSITORY,
17611
+ status: "release_owner_quickstart",
17612
+ commands: {
17613
+ checklist: "guardian release checklist --version=<version>",
17614
+ flow: "guardian release flow --version=<version>",
17615
+ secrets: "guardian release secrets",
17616
+ dryRunDispatch: "guardian release command --version=<version>",
17617
+ publishDispatch: "guardian release command --version=<version> --publish",
17618
+ verifyPublishedVersion: "guardian release verify --version=<version>",
17619
+ pasteLocalSmoke: "guardian release paste --version=<version>",
17620
+ browserStoreHandoff: "guardian release browser-store",
17621
+ readiness: "guardian readiness"
17622
+ },
17623
+ suggestedOrder: [
17624
+ "Run the checklist for the target version.",
17625
+ "Set or verify the repository publish credential if this is a public npm release.",
17626
+ "Run the dry-run dispatch before any publish dispatch.",
17627
+ "Run the publish dispatch only after dry-run evidence passes.",
17628
+ "Verify the published version and refresh release evidence.",
17629
+ "Use browser-store handoff only for submission/review evidence; it does not upload or approve listings."
17630
+ ],
17631
+ boundaries: [
17632
+ "Release quickstart output is operator guidance only, not release evidence or production-gate proof.",
17633
+ "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 release commands, chat, PR bodies, or evidence.",
17634
+ "Public npm preview publication does not close signed-installer, browser-store, high-risk desktop action, or autonomous local app execution production gates.",
17635
+ "Full production claims remain blocked until every not-proven production gate has real validated external evidence."
17636
+ ],
17637
+ tokenPrinted: false,
17638
+ rawContentIncluded: false
17639
+ };
17640
+ }
17641
+ function renderGuardianReleaseHelp(result, flags) {
17642
+ if (flags.has("json")) {
17643
+ return `${JSON.stringify(result, null, 2)}
17644
+ `;
17645
+ }
17646
+ return `${[
17647
+ "Project Guardian Release Quickstart",
17648
+ `Repository: ${result.repository}`,
17649
+ `Status: ${result.status}`,
17650
+ "Commands:",
17651
+ `- Checklist: ${result.commands.checklist}`,
17652
+ `- Flow: ${result.commands.flow}`,
17653
+ `- Secrets: ${result.commands.secrets}`,
17654
+ `- Dry run: ${result.commands.dryRunDispatch}`,
17655
+ `- Publish: ${result.commands.publishDispatch}`,
17656
+ `- Verify published version: ${result.commands.verifyPublishedVersion}`,
17657
+ `- Copy-paste local smoke: ${result.commands.pasteLocalSmoke}`,
17658
+ `- Browser-store handoff: ${result.commands.browserStoreHandoff}`,
17659
+ `- Readiness: ${result.commands.readiness}`,
17660
+ "Suggested order:",
17661
+ ...result.suggestedOrder.map((step, index) => `${index + 1}. ${step}`),
17662
+ "Boundaries:",
17663
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
17664
+ "Token printed: no"
17665
+ ].join("\n")}
17666
+ `;
17667
+ }
17668
+ function buildGuardianReleaseDispatchCommandResult(input2) {
17669
+ return {
17670
+ schema_version: "contextecf/project-guardian-release-dispatch-command/v1",
17671
+ cli_version: GUARDIAN_CLI_VERSION,
17672
+ workflow: GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
17673
+ releaseVersion: input2.releaseVersion,
17674
+ channels: input2.channels,
17675
+ dryRun: input2.dryRun,
17676
+ runDockerSmoke: input2.runDockerSmoke,
17677
+ command: buildGuardianReleaseDispatchCommandFor(input2),
17678
+ ...input2.dryRun ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
17679
+ provenance: "github_actions_oidc_supported",
17680
+ boundaries: [
17681
+ "Use dry_run=true before public publication.",
17682
+ "dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
17683
+ "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.",
17684
+ "A release-dispatch command is operator guidance, not production-gate proof."
17685
+ ],
17686
+ tokenPrinted: false,
17687
+ rawContentIncluded: false
17688
+ };
17689
+ }
17690
+ function renderGuardianReleaseDispatchCommand(result, flags) {
17691
+ if (flags.has("json")) {
17692
+ return `${JSON.stringify(result, null, 2)}
17693
+ `;
17694
+ }
17695
+ return `${[
17696
+ "Project Guardian Release Dispatch Command",
17697
+ `Release: ${result.releaseVersion}`,
17698
+ `Mode: ${result.dryRun ? "dry run" : "publish"}`,
17699
+ `Workflow: ${result.workflow}`,
17700
+ `Channels: ${result.channels}`,
17701
+ `Docker smoke: ${result.runDockerSmoke ? "yes" : "no"}`,
17702
+ result.requiredPublishCredentialName ? `Required repository secret: ${result.requiredPublishCredentialName}` : "Required repository secret: not needed for dry run",
17703
+ "Command:",
17704
+ result.command,
17705
+ "Boundaries:",
17706
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
17707
+ "Token printed: no"
17708
+ ].join("\n")}
17709
+ `;
17710
+ }
17711
+ function buildGuardianBrowserStoreHandoffCommandResult() {
17712
+ return {
17713
+ schema_version: "contextecf/project-guardian-browser-store-handoff-command/v1",
17714
+ cli_version: GUARDIAN_CLI_VERSION,
17715
+ status: "chrome_distribution_proven_next_submission_pack_ready",
17716
+ primaryStore: "chrome_web_store",
17717
+ productionGate: {
17718
+ id: "browser-store-distribution",
17719
+ status: "proven",
17720
+ nextSubmissionRequiresFreshOfficialReviewEvidence: true
17721
+ },
17722
+ commands: {
17723
+ submissionPack: "npm run guardian:browser-store:submission-pack -- --json --output-dir release/evidence/guardian-browser-store-submission-pack",
17724
+ preSubmissionSmoke: "GUARDIAN_BROWSER_STORE_SMOKE_WORKSPACE=/tmp/guardian-browser-store-pre-submission-smoke bash release/evidence/guardian-browser-store-submission-pack/run-pre-submission-readiness-smoke.sh",
17725
+ preSubmissionReadiness: [
17726
+ "npm run guardian:browser-store:readiness:collect -- \\",
17727
+ " --package artifacts/guardian-browser-store/guardian-browser-extension-<version>.zip \\",
17728
+ " --assert-pre-submission-only \\",
17729
+ " --assert-mv3-validation-passed \\",
17730
+ " --assert-source-archive-excluded \\",
17731
+ " --assert-store-credentials-excluded \\",
17732
+ " --output release/evidence/guardian-browser-store-submission-pack/pre-submission-readiness.json"
17733
+ ].join("\n"),
17734
+ reviewPreflightAfterApproval: [
17735
+ "npm run guardian:browser-store:review-preflight -- \\",
17736
+ " --store-evidence release/evidence/guardian-browser-store-submission-pack/browser-store-evidence-input.json \\",
17737
+ " --assert-metadata-only \\",
17738
+ " --assert-no-store-credentials \\",
17739
+ " --assert-approved-review-status \\",
17740
+ " --assert-public-listing-url \\",
17741
+ " --output release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json"
17742
+ ].join("\n"),
17743
+ collectorAfterApproval: [
17744
+ "npm run guardian:production-gates:collect:browser-store -- \\",
17745
+ " --store-evidence release/evidence/guardian-browser-store-submission-pack/browser-store-evidence-input.json \\",
17746
+ " --review-preflight-summary release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json \\",
17747
+ " --assert-no-source-archives \\",
17748
+ " --assert-package-digest-matches-release \\",
17749
+ " --assert-listing-matches-release-boundary \\",
17750
+ " --assert-listing-names-not-proven-gates \\",
17751
+ " --assert-production-claim-absent \\",
17752
+ " --output release/evidence/guardian-production-gates/browser-store-distribution.json"
17753
+ ].join("\n"),
17754
+ finalGateValidation: "npm run validate:guardian-production-gates -- --claim production"
17755
+ },
17756
+ evidence: {
17757
+ submissionPackDir: "release/evidence/guardian-browser-store-submission-pack",
17758
+ closeoutChecklistPath: "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
17759
+ preSubmissionChecklistPath: "docs/project-guardian/browser-store-pre-submission-checklist.md",
17760
+ readinessOutput: "release/evidence/guardian-browser-store-submission-pack/pre-submission-readiness.json",
17761
+ reviewPreflightOutput: "release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json",
17762
+ productionGatePacket: "release/evidence/guardian-production-gates/browser-store-distribution.json"
17763
+ },
17764
+ boundaries: [
17765
+ "This command surface prepares browser-store submission handoff for future extension versions; it does not upload, submit, approve, or distribute the extension.",
17766
+ "Chrome Web Store distribution is proven for the evidenced ContextECF Halo listing; each future extension package still needs fresh review/submission evidence before updating that proof.",
17767
+ "Do not place browser-store credentials, dashboard cookies, source archives, source maps, runtime tokens, private policy packs, raw prompts, raw responses, or customer content in browser-store evidence.",
17768
+ "Enterprise managed browser deployment is a separate customer rollout lane and does not replace public store review evidence for public listings."
17769
+ ],
17411
17770
  tokenPrinted: false,
17412
17771
  rawContentIncluded: false
17413
17772
  };
17414
17773
  }
17774
+ function renderGuardianBrowserStoreHandoffCommand(result, flags) {
17775
+ if (flags.has("json")) {
17776
+ return `${JSON.stringify(result, null, 2)}
17777
+ `;
17778
+ }
17779
+ return `${[
17780
+ "Project Guardian Browser Store Handoff",
17781
+ `Status: ${result.status}`,
17782
+ `Primary store: ${result.primaryStore}`,
17783
+ `Production gate: ${result.productionGate.id} (${result.productionGate.status})`,
17784
+ "1. Build submission pack:",
17785
+ result.commands.submissionPack,
17786
+ "2. Run pre-submission smoke:",
17787
+ result.commands.preSubmissionSmoke,
17788
+ "3. Record pre-submission readiness:",
17789
+ result.commands.preSubmissionReadiness,
17790
+ "4. After official approval, run review preflight:",
17791
+ result.commands.reviewPreflightAfterApproval,
17792
+ "5. After official approval, collect production-gate evidence:",
17793
+ result.commands.collectorAfterApproval,
17794
+ `Closeout checklist: ${result.evidence.closeoutChecklistPath}`,
17795
+ `Pre-submission checklist: ${result.evidence.preSubmissionChecklistPath}`,
17796
+ "Boundaries:",
17797
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
17798
+ "Token printed: no"
17799
+ ].join("\n")}
17800
+ `;
17801
+ }
17802
+ function buildGuardianReleaseSecretSetup() {
17803
+ return {
17804
+ schema_version: "contextecf/project-guardian-release-secret-setup/v1",
17805
+ cli_version: GUARDIAN_CLI_VERSION,
17806
+ repository: GUARDIAN_RELEASE_REPOSITORY,
17807
+ requiredForPublish: "NPM_TOKEN",
17808
+ githubActionsSecretUrl: `https://github.com/${GUARDIAN_RELEASE_REPOSITORY}/settings/secrets/actions/new`,
17809
+ commands: {
17810
+ setNpmToken: `gh secret set NPM_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
17811
+ verifyNpmTokenPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^NPM_TOKEN\\b'`,
17812
+ dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
17813
+ dryRun: true,
17814
+ releaseVersion: "<version>",
17815
+ channels: "all",
17816
+ runDockerSmoke: true
17817
+ }),
17818
+ publishDispatch: buildGuardianReleaseDispatchCommandFor({
17819
+ dryRun: false,
17820
+ releaseVersion: "<version>",
17821
+ channels: "all",
17822
+ runDockerSmoke: true
17823
+ })
17824
+ },
17825
+ boundaries: [
17826
+ "NPM_TOKEN belongs only in GitHub Actions repository secrets for guarded dry_run=false npm publication.",
17827
+ "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.",
17828
+ "Use dry_run=true before dry_run=false; dry-run dispatch does not require NPM_TOKEN.",
17829
+ "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."
17830
+ ],
17831
+ tokenPrinted: false,
17832
+ rawContentIncluded: false
17833
+ };
17834
+ }
17835
+ function renderGuardianReleaseSecretSetup(result, flags) {
17836
+ if (flags.has("json")) {
17837
+ return `${JSON.stringify(result, null, 2)}
17838
+ `;
17839
+ }
17840
+ return `${[
17841
+ "Project Guardian Release Secret Setup",
17842
+ `Repository: ${result.repository}`,
17843
+ `Required for publish: ${result.requiredForPublish}`,
17844
+ `GitHub Actions secret page: ${result.githubActionsSecretUrl}`,
17845
+ "Set secret:",
17846
+ result.commands.setNpmToken,
17847
+ "Verify secret presence:",
17848
+ result.commands.verifyNpmTokenPresence,
17849
+ "Dry-run release command:",
17850
+ result.commands.dryRunDispatch,
17851
+ "Publish release command:",
17852
+ result.commands.publishDispatch,
17853
+ "Boundaries:",
17854
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
17855
+ "Token printed: no"
17856
+ ].join("\n")}
17857
+ `;
17858
+ }
17859
+ function buildGuardianReleaseChecklist(releaseVersion) {
17860
+ return {
17861
+ schema_version: "contextecf/project-guardian-release-checklist/v1",
17862
+ cli_version: GUARDIAN_CLI_VERSION,
17863
+ releaseVersion,
17864
+ repository: GUARDIAN_RELEASE_REPOSITORY,
17865
+ status: "preview_release_operator_ready_full_production_blocked",
17866
+ operatorCommands: {
17867
+ secretSetup: "guardian release secrets",
17868
+ dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
17869
+ dryRun: true,
17870
+ releaseVersion,
17871
+ channels: "all",
17872
+ runDockerSmoke: true
17873
+ }),
17874
+ publishDispatch: buildGuardianReleaseDispatchCommandFor({
17875
+ dryRun: false,
17876
+ releaseVersion,
17877
+ channels: "all",
17878
+ runDockerSmoke: true
17879
+ }),
17880
+ browserStoreHandoff: "guardian release browser-store",
17881
+ readiness: "guardian readiness"
17882
+ },
17883
+ requiredRepositoryCredentialName: "NPM_TOKEN",
17884
+ evidenceOutputs: [
17885
+ "release/evidence/guardian-release-dispatch-summary.json",
17886
+ "release/evidence/guardian-npm-publish-execution-summary.json",
17887
+ "release/evidence/guardian-npm-publish-status-verification.json",
17888
+ "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
17889
+ "release/evidence/guardian-finish-line-status.json"
17890
+ ],
17891
+ notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES.map((gate) => ({
17892
+ id: gate.id,
17893
+ label: gate.label,
17894
+ owner: gate.owner,
17895
+ releaseBoundary: gate.releaseBoundary
17896
+ })),
17897
+ boundaries: [
17898
+ "This checklist is an operator command surface for Guardian preview releases; it is not production-gate proof.",
17899
+ "Run the dry-run dispatch before any dry_run=false publish dispatch.",
17900
+ "dry_run=false requires NPM_TOKEN in GitHub Actions repository secrets and must not print npm tokens, OTP values, or .npmrc contents.",
17901
+ "The checklist does not sign native installers, submit browser-store packages, execute high-risk desktop actions, or enable autonomous local app execution.",
17902
+ "Full production claims remain blocked until every not-proven production gate has real validated external evidence."
17903
+ ],
17904
+ tokenPrinted: false,
17905
+ rawContentIncluded: false
17906
+ };
17907
+ }
17908
+ function buildGuardianReleaseFlow(releaseVersion) {
17909
+ const checklist = buildGuardianReleaseChecklist(releaseVersion);
17910
+ const verify = buildGuardianReleaseVerify(releaseVersion);
17911
+ const dryRunDispatch = buildGuardianReleaseDispatchCommandFor({
17912
+ dryRun: true,
17913
+ releaseVersion,
17914
+ channels: "all",
17915
+ runDockerSmoke: true
17916
+ });
17917
+ const publishDispatch = buildGuardianReleaseDispatchCommandFor({
17918
+ dryRun: false,
17919
+ releaseVersion,
17920
+ channels: "all",
17921
+ runDockerSmoke: true
17922
+ });
17923
+ return {
17924
+ schema_version: "contextecf/project-guardian-release-flow/v1",
17925
+ cli_version: GUARDIAN_CLI_VERSION,
17926
+ releaseVersion,
17927
+ repository: GUARDIAN_RELEASE_REPOSITORY,
17928
+ status: "release_owner_flow_ready_full_production_blocked",
17929
+ steps: [
17930
+ {
17931
+ id: "review-checklist",
17932
+ label: "Review the release checklist",
17933
+ command: `guardian release checklist --version=${releaseVersion}`,
17934
+ credentialRequired: false
17935
+ },
17936
+ {
17937
+ id: "verify-secrets",
17938
+ label: "Verify npm publish secret setup",
17939
+ command: "guardian release secrets",
17940
+ credentialRequired: false
17941
+ },
17942
+ {
17943
+ id: "dry-run-dispatch",
17944
+ label: "Run the GitHub Actions dry run",
17945
+ command: dryRunDispatch,
17946
+ credentialRequired: false
17947
+ },
17948
+ {
17949
+ id: "publish-dispatch",
17950
+ label: "Run the guarded publish dispatch after dry-run evidence passes",
17951
+ command: publishDispatch,
17952
+ credentialRequired: true
17953
+ },
17954
+ {
17955
+ id: "verify-public-release",
17956
+ label: "Verify the published package and local install smoke",
17957
+ command: `guardian release verify --version=${releaseVersion}`,
17958
+ credentialRequired: false
17959
+ },
17960
+ {
17961
+ id: "copy-paste-local-smoke",
17962
+ label: "Copy-paste the local end-user smoke block",
17963
+ command: `guardian release paste --version=${releaseVersion}`,
17964
+ credentialRequired: false
17965
+ },
17966
+ {
17967
+ id: "browser-store-handoff",
17968
+ label: "Prepare browser-store submission handoff",
17969
+ command: "guardian release browser-store",
17970
+ credentialRequired: false
17971
+ }
17972
+ ],
17973
+ copyPasteLocalSmoke: verify.commands.copyPasteLocalSmoke,
17974
+ evidenceOutputs: Array.from(
17975
+ /* @__PURE__ */ new Set([
17976
+ ...checklist.evidenceOutputs,
17977
+ ...verify.evidenceOutputs,
17978
+ "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json"
17979
+ ])
17980
+ ),
17981
+ notProvenProductionGates: checklist.notProvenProductionGates.map((gate) => ({
17982
+ id: gate.id,
17983
+ label: gate.label,
17984
+ releaseBoundary: gate.releaseBoundary
17985
+ })),
17986
+ boundaries: [
17987
+ "This release flow is copy-paste operator guidance only; it is not release evidence or production-gate proof.",
17988
+ "Publish dispatch requires NPM_TOKEN in GitHub Actions repository secrets and must not print npm tokens, OTP values, or .npmrc contents.",
17989
+ "Run the dry-run dispatch before the guarded dry_run=false publish dispatch.",
17990
+ "Public npm preview publication and local install smoke prove the CLI preview lane only.",
17991
+ "Signed native installers, high-risk desktop action execution, and autonomous local app execution remain separate not-proven production gates until real external evidence is collected and validated."
17992
+ ],
17993
+ tokenPrinted: false,
17994
+ rawContentIncluded: false
17995
+ };
17996
+ }
17997
+ function renderGuardianReleaseFlow(result, flags) {
17998
+ if (flags.has("json")) {
17999
+ return `${JSON.stringify(result, null, 2)}
18000
+ `;
18001
+ }
18002
+ const lines = [
18003
+ "Project Guardian Release Flow",
18004
+ `Release: ${result.releaseVersion}`,
18005
+ `Repository: ${result.repository}`,
18006
+ `Status: ${result.status}`,
18007
+ "Steps:",
18008
+ ...result.steps.flatMap((step, index) => [
18009
+ `${index + 1}. ${step.label}${step.credentialRequired ? " (requires NPM_TOKEN secret)" : ""}:`,
18010
+ step.command
18011
+ ]),
18012
+ "Post-publish copy-paste local smoke:",
18013
+ result.copyPasteLocalSmoke,
18014
+ "Evidence outputs:",
18015
+ ...result.evidenceOutputs.map((output2) => `- ${output2}`),
18016
+ "Not-proven production gates:",
18017
+ ...result.notProvenProductionGates.map(
18018
+ (gate) => `- ${gate.label}: ${gate.releaseBoundary ?? "not proven"}`
18019
+ ),
18020
+ "Boundaries:",
18021
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
18022
+ "Token printed: no"
18023
+ ];
18024
+ return `${lines.join("\n")}
18025
+ `;
18026
+ }
18027
+ function renderGuardianReleaseChecklist(result, flags) {
18028
+ if (flags.has("json")) {
18029
+ return `${JSON.stringify(result, null, 2)}
18030
+ `;
18031
+ }
18032
+ return `${[
18033
+ "Project Guardian Release Checklist",
18034
+ `Release: ${result.releaseVersion}`,
18035
+ `Repository: ${result.repository}`,
18036
+ `Status: ${result.status}`,
18037
+ `Required repository credential: ${result.requiredRepositoryCredentialName}`,
18038
+ "1. Secret setup:",
18039
+ result.operatorCommands.secretSetup,
18040
+ "2. Dry-run dispatch:",
18041
+ result.operatorCommands.dryRunDispatch,
18042
+ "3. Publish dispatch:",
18043
+ result.operatorCommands.publishDispatch,
18044
+ "4. Browser-store handoff:",
18045
+ result.operatorCommands.browserStoreHandoff,
18046
+ "5. Readiness check:",
18047
+ result.operatorCommands.readiness,
18048
+ "Evidence outputs:",
18049
+ ...result.evidenceOutputs.map((output2) => `- ${output2}`),
18050
+ "Not-proven production gates:",
18051
+ ...result.notProvenProductionGates.map(
18052
+ (gate) => `- ${gate.label}: ${gate.releaseBoundary ?? "not proven"}`
18053
+ ),
18054
+ "Boundaries:",
18055
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
18056
+ "Token printed: no"
18057
+ ].join("\n")}
18058
+ `;
18059
+ }
18060
+ function buildGuardianReleaseVerify(releaseVersion) {
18061
+ const copyPasteLocalSmoke = buildGuardianReleasePaste(releaseVersion).command;
18062
+ return {
18063
+ schema_version: "contextecf/project-guardian-release-verify/v1",
18064
+ cli_version: GUARDIAN_CLI_VERSION,
18065
+ releaseVersion,
18066
+ repository: GUARDIAN_RELEASE_REPOSITORY,
18067
+ packageName: GUARDIAN_NPM_PACKAGE_NAME,
18068
+ registry: GUARDIAN_NPM_REGISTRY,
18069
+ status: "post_release_verification_required",
18070
+ commands: {
18071
+ registryVersion: `npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
18072
+ publicInstall: `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
18073
+ installedVersion: "guardian --version",
18074
+ setup: "guardian setup",
18075
+ launch: "guardian launch",
18076
+ status: "guardian status",
18077
+ openControlTower: "guardian open",
18078
+ copyPasteLocalSmoke,
18079
+ publishStatusVerification: "npm run guardian:npm:publish:verify-status -- --status release/evidence/guardian-npm-publish-status.json --assert-ready --verify-artifacts --output release/evidence/guardian-npm-publish-status-verification.json",
18080
+ finishLineStatus: "npm run guardian:finish-line:status -- --npm-publish-status release/evidence/guardian-npm-publish-status.json --json --output release/evidence/guardian-finish-line-status.json"
18081
+ },
18082
+ evidenceOutputs: [
18083
+ "release/evidence/guardian-npm-publish-status.json",
18084
+ "release/evidence/guardian-npm-publish-status-verification.json",
18085
+ "release/evidence/guardian-finish-line-status.json"
18086
+ ],
18087
+ boundaries: [
18088
+ "This command surface verifies public preview release visibility and installability; it does not publish to npm.",
18089
+ "Do not print npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content in release verification evidence.",
18090
+ "A passing public npm install smoke proves the CLI preview lane only; signed installers, high-risk desktop action execution, and autonomous app execution remain separate production gates.",
18091
+ "Full production claims remain blocked until every not-proven production gate has real validated external evidence."
18092
+ ],
18093
+ tokenPrinted: false,
18094
+ rawContentIncluded: false
18095
+ };
18096
+ }
18097
+ function buildGuardianReleasePaste(releaseVersion) {
18098
+ const commands = [
18099
+ `npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
18100
+ `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
18101
+ "guardian --version",
18102
+ "guardian stop",
18103
+ "guardian setup",
18104
+ "guardian launch",
18105
+ "guardian open",
18106
+ "guardian status"
18107
+ ];
18108
+ return {
18109
+ schema_version: "contextecf/project-guardian-release-paste/v1",
18110
+ cli_version: GUARDIAN_CLI_VERSION,
18111
+ releaseVersion,
18112
+ packageName: GUARDIAN_NPM_PACKAGE_NAME,
18113
+ registry: GUARDIAN_NPM_REGISTRY,
18114
+ command: commands.join("\n"),
18115
+ commands,
18116
+ boundaries: [
18117
+ "This paste block verifies public npm visibility, global install, first-run setup, daemon launch, Control Tower open, and status.",
18118
+ "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.",
18119
+ "guardian stop is included before setup so stale local daemons or local token mismatches are cleared before launch."
18120
+ ],
18121
+ tokenPrinted: false,
18122
+ rawContentIncluded: false
18123
+ };
18124
+ }
18125
+ function renderGuardianReleasePaste(result, flags) {
18126
+ if (flags.has("json")) {
18127
+ return `${JSON.stringify(result, null, 2)}
18128
+ `;
18129
+ }
18130
+ return `${result.command}
18131
+ `;
18132
+ }
18133
+ function renderGuardianReleaseVerify(result, flags) {
18134
+ if (flags.has("json")) {
18135
+ return `${JSON.stringify(result, null, 2)}
18136
+ `;
18137
+ }
18138
+ return `${[
18139
+ "Project Guardian Release Verification",
18140
+ `Release: ${result.releaseVersion}`,
18141
+ `Package: ${result.packageName}`,
18142
+ `Registry: ${result.registry}`,
18143
+ `Status: ${result.status}`,
18144
+ "1. Confirm registry visibility:",
18145
+ result.commands.registryVersion,
18146
+ "2. Install the published version:",
18147
+ result.commands.publicInstall,
18148
+ "3. Confirm installed CLI version:",
18149
+ result.commands.installedVersion,
18150
+ "4. Run first-use smoke:",
18151
+ result.commands.setup,
18152
+ result.commands.launch,
18153
+ result.commands.status,
18154
+ result.commands.openControlTower,
18155
+ "5. Copy-paste local smoke block:",
18156
+ result.commands.copyPasteLocalSmoke,
18157
+ "6. Verify release evidence:",
18158
+ result.commands.publishStatusVerification,
18159
+ result.commands.finishLineStatus,
18160
+ "Evidence outputs:",
18161
+ ...result.evidenceOutputs.map((output2) => `- ${output2}`),
18162
+ "Boundaries:",
18163
+ ...result.boundaries.map((boundary) => `- ${boundary}`),
18164
+ "Token printed: no"
18165
+ ].join("\n")}
18166
+ `;
18167
+ }
18168
+ function isValidReleaseVersion(value) {
18169
+ return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(value);
18170
+ }
18171
+ function isValidReleaseChannels(value) {
18172
+ return ["all", "npm", "browser", "evidence"].includes(value);
18173
+ }
17415
18174
  function renderGuardianProductionReadiness(result, flags) {
17416
18175
  if (flags.has("json")) {
17417
18176
  return `${JSON.stringify(result, null, 2)}
@@ -17424,6 +18183,18 @@ function renderGuardianProductionReadiness(result, flags) {
17424
18183
  `Doctor: ${result.doctorOverall.toUpperCase()}`,
17425
18184
  `NPM preview install: ${result.npmPreview.status.toUpperCase()} - ${result.npmPreview.reason}`,
17426
18185
  result.npmPreview.publishCommand ? `NPM publish command: ${result.npmPreview.publishCommand}` : "NPM publish command: not available until publish dry-run evidence passes",
18186
+ `Distribution: ${result.distribution.status}`,
18187
+ `Install: ${result.distribution.oneLineInstallCommand}`,
18188
+ `Try without global install: ${result.distribution.oneLineTryCommand}`,
18189
+ `Open Control Tower: ${result.distribution.openControlTowerCommand}`,
18190
+ `AI tool setup: ${result.distribution.aiToolIntegration.mcpInstallCommand}; ${result.distribution.aiToolIntegration.browserSetupCommand}`,
18191
+ `Browser-store handoff: ${result.distribution.browserStoreHandoff.status}; gate ${result.distribution.browserStoreHandoff.productionGateStatus}`,
18192
+ `Browser-store checklist: ${result.distribution.browserStoreHandoff.closeoutChecklistPath}`,
18193
+ `Release workflow: ${result.distribution.releaseAutomation.workflow}; status=${result.distribution.releaseAutomation.status}`,
18194
+ `Release dry run:
18195
+ ${result.distribution.releaseAutomation.dryRunCommand}`,
18196
+ `Release publish:
18197
+ ${result.distribution.releaseAutomation.publishCommand}`,
17427
18198
  `Full production release: ${result.fullProduction.status.toUpperCase()} - ${result.fullProduction.reason}`,
17428
18199
  `Production gate evidence: ${result.fullProduction.productionGateEvidenceStatus}`,
17429
18200
  `Blocked production gates: ${result.fullProduction.blockedGateCount}`,
@@ -17452,6 +18223,10 @@ async function statusGuardian(flags, options) {
17452
18223
  installed: profile !== void 0,
17453
18224
  daemonStatus: daemonHealth.daemon.status
17454
18225
  });
18226
+ const daemonVersionMismatch = daemonHealth.daemon.status === "reachable" && daemonHealth.daemon.version !== void 0 && daemonHealth.daemon.version !== GUARDIAN_CLI_VERSION ? { cliVersion: GUARDIAN_CLI_VERSION, daemonVersion: daemonHealth.daemon.version } : null;
18227
+ if (daemonVersionMismatch) {
18228
+ nextCommands.push("guardian stop", "guardian launch");
18229
+ }
17455
18230
  const result = {
17456
18231
  schema_version: "contextecf/project-guardian-status/v1",
17457
18232
  cli_version: GUARDIAN_CLI_VERSION,
@@ -17485,6 +18260,7 @@ async function statusGuardian(flags, options) {
17485
18260
  serviceSupervision,
17486
18261
  osKeyStorage,
17487
18262
  notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES,
18263
+ daemonVersionMismatch,
17488
18264
  nextCommands
17489
18265
  };
17490
18266
  if (flags.has("json")) {
@@ -17499,6 +18275,7 @@ async function statusGuardian(flags, options) {
17499
18275
  `Control Tower: ${result.controlTowerUrl ?? "not configured"}`,
17500
18276
  `Daemon health: ${result.daemon.status}${result.daemon.statusCode ? ` (HTTP ${result.daemon.statusCode})` : ""}`,
17501
18277
  result.daemon.error ? `Daemon detail: ${result.daemon.error}` : void 0,
18278
+ 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,
17502
18279
  `MCP stdio: ${result.runtime.mcpStdioAvailable ? "available" : "unavailable"}`,
17503
18280
  `Posture Profile: ${result.postureProfile.selected}`,
17504
18281
  `Prompt Coach: ${result.preferences.promptCoachMode}`,
@@ -17588,7 +18365,7 @@ async function runLaunchCommand(flags, options) {
17588
18365
  return startExitCode;
17589
18366
  }
17590
18367
  const start = JSON.parse(startOutput);
17591
- const shouldOpen = !flags.has("print");
18368
+ const shouldOpen = flags.has("open") && !flags.has("print");
17592
18369
  if (shouldOpen) {
17593
18370
  const opener = options.openUrl ?? ((url2) => openUrlInDefaultBrowser(url2, options));
17594
18371
  await opener(start.controlTowerUrl);
@@ -17602,7 +18379,12 @@ async function runLaunchCommand(flags, options) {
17602
18379
  controlTowerUrl: start.controlTowerUrl,
17603
18380
  pid: start.pid,
17604
18381
  healthStatus: start.healthStatus,
17605
- nextCommands: ["guardian status", "guardian daemon pair --json", "guardian policy list"]
18382
+ nextCommands: [
18383
+ "guardian open",
18384
+ "guardian status",
18385
+ "guardian daemon pair --json",
18386
+ "guardian policy list"
18387
+ ]
17606
18388
  };
17607
18389
  write(
17608
18390
  stdout,
@@ -17612,7 +18394,7 @@ async function runLaunchCommand(flags, options) {
17612
18394
  `Daemon: ${result.daemonUrl}${result.reusedExistingDaemon ? " (already running)" : ""}`,
17613
18395
  `Control Tower: ${result.controlTowerUrl}`,
17614
18396
  shouldOpen ? `Opening: ${result.controlTowerUrl}` : void 0,
17615
- "Next: guardian status"
18397
+ "Next: guardian open; guardian status"
17616
18398
  ].filter(Boolean).join("\n")}
17617
18399
  `
17618
18400
  );
@@ -18036,6 +18818,7 @@ function requestGuardianDaemonHealth(request) {
18036
18818
  const parsedBody = parseJsonObject(body);
18037
18819
  const service = typeof parsedBody?.service === "string" ? parsedBody.service : void 0;
18038
18820
  const rawContentPersistence = typeof parsedBody?.rawContentPersistence === "boolean" ? parsedBody.rawContentPersistence : void 0;
18821
+ const version2 = typeof parsedBody?.version === "string" ? parsedBody.version : void 0;
18039
18822
  const error51 = typeof parsedBody?.error === "string" ? parsedBody.error : void 0;
18040
18823
  const ok = typeof statusCode === "number" && statusCode >= 200 && statusCode < 300;
18041
18824
  resolve({
@@ -18044,6 +18827,7 @@ function requestGuardianDaemonHealth(request) {
18044
18827
  statusCode,
18045
18828
  service,
18046
18829
  rawContentPersistence,
18830
+ version: version2,
18047
18831
  error: ok ? void 0 : error51 ?? "daemon_health_failed"
18048
18832
  });
18049
18833
  });
@@ -21742,6 +22526,7 @@ async function buildDaemonHealthStatus(home, flags, options, profile) {
21742
22526
  statusCode: checked.statusCode,
21743
22527
  service: checked.service,
21744
22528
  rawContentPersistence: checked.rawContentPersistence,
22529
+ version: checked.version,
21745
22530
  error: checked.error
21746
22531
  }
21747
22532
  };
@@ -22054,6 +22839,18 @@ async function buildGuardianDoctorStatus(home, profile, env = process.env) {
22054
22839
  rawContentIncluded: false
22055
22840
  };
22056
22841
  }
22842
+ function isGuardianSupportedNodeVersion(nodeVersion) {
22843
+ const parts = nodeVersion.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10));
22844
+ const [major = 0, minor = 0, patch = 0] = parts;
22845
+ const [minMajor, minMinor, minPatch] = GUARDIAN_MIN_SUPPORTED_NODE_VERSION;
22846
+ if (major !== minMajor) {
22847
+ return major > minMajor;
22848
+ }
22849
+ if (minor !== minMinor) {
22850
+ return minor > minMinor;
22851
+ }
22852
+ return patch >= minPatch;
22853
+ }
22057
22854
  async function buildDoctorChecks(home, profile, env = process.env) {
22058
22855
  const encryption = buildGuardianLocalDataEncryptionStatus(
22059
22856
  env,
@@ -22063,6 +22860,12 @@ async function buildDoctorChecks(home, profile, env = process.env) {
22063
22860
  const serviceSupervision = await buildGuardianServiceSupervisionStatus(home);
22064
22861
  const osKeyStorage = await buildGuardianOsKeyStorageStatus(home);
22065
22862
  return [
22863
+ {
22864
+ id: "node-runtime",
22865
+ label: "Node.js runtime",
22866
+ status: isGuardianSupportedNodeVersion(process.version) ? "pass" : "warn",
22867
+ detail: isGuardianSupportedNodeVersion(process.version) ? `Node ${process.version} meets the >=20.20.0 floor` : `Node ${process.version} is below the supported >=20.20.0 floor; upgrade to Node 20.20+ or 22 LTS`
22868
+ },
22066
22869
  {
22067
22870
  id: "profile",
22068
22871
  label: "Guardian profile",
@@ -22164,6 +22967,26 @@ function stringFlag(flags, key) {
22164
22967
  const value = flags.get(key);
22165
22968
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
22166
22969
  }
22970
+ function booleanFlag(flags, key, defaultValue) {
22971
+ const value = flags.get(key);
22972
+ if (value === void 0) {
22973
+ return defaultValue;
22974
+ }
22975
+ if (value === true) {
22976
+ return true;
22977
+ }
22978
+ if (typeof value !== "string") {
22979
+ return defaultValue;
22980
+ }
22981
+ const normalized = value.trim().toLowerCase();
22982
+ if (["1", "true", "yes", "on"].includes(normalized)) {
22983
+ return true;
22984
+ }
22985
+ if (["0", "false", "no", "off"].includes(normalized)) {
22986
+ return false;
22987
+ }
22988
+ return defaultValue;
22989
+ }
22167
22990
  function copyStringFlags(flags, keys) {
22168
22991
  return keys.flatMap((key) => {
22169
22992
  const value = stringFlag(flags, key);
@@ -22311,19 +23134,22 @@ function openUrlInDefaultBrowser(url2, options = {}) {
22311
23134
  });
22312
23135
  });
22313
23136
  }
22314
- var GUARDIAN_CLI_VERSION, GUARDIAN_PROFILE_SCHEMA_VERSION, GUARDIAN_NPM_PACKAGE_NAME, GUARDIAN_GLOBAL_INSTALL_COMMAND, GUARDIAN_NPX_SETUP_COMMAND, GUARDIAN_FIRST_RUN_COMMAND, GUARDIAN_OPEN_CONTROL_TOWER_COMMAND, GUARDIAN_DEFAULT_CONTROL_TOWER_URL, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ID_ENV, GUARDIAN_DESKTOP_ADAPTER_SIMULATE_OPEN_ENV, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_ID, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_PROOF_SCHEMA_VERSION, GUARDIAN_SERVICE_PROOF_SCHEMA_VERSION, GUARDIAN_OS_KEY_STORAGE_PROOF_SCHEMA_VERSION, GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION, PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2, PROMPT_COACH_MODES, DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT, GUARDIAN_POSTURE_PROFILE_IDS, GUARDIAN_POSTURE_PROFILE_CATALOG, GUARDIAN_POLICY_PACK_MARKETPLACE_CATALOG, GUARDIAN_PROVIDER_IDS, GUARDIAN_SOURCE_TYPES, GUARDIAN_NOT_PROVEN_PRODUCTION_GATES, DEFAULT_POLICY_PACKS, GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY, GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY, GUARDIAN_BRIDGE_CONFIG_SCHEMA_VERSION, GUARDIAN_NATIVE_HOST_NAME, MCP_CLIENTS, NATIVE_HOST_BROWSERS, HELP_TEXT, normalizeGuardianPreferences, GUARDIAN_DATA_FILE_NAMES, GUARDIAN_DATA_DIR_NAMES;
23137
+ var GUARDIAN_CLI_VERSION, GUARDIAN_PROFILE_SCHEMA_VERSION, GUARDIAN_NPM_PACKAGE_NAME, GUARDIAN_NPM_REGISTRY, GUARDIAN_GLOBAL_INSTALL_COMMAND, GUARDIAN_NPX_SETUP_COMMAND, GUARDIAN_FIRST_RUN_COMMAND, GUARDIAN_OPEN_CONTROL_TOWER_COMMAND, GUARDIAN_RELEASE_DISPATCH_WORKFLOW, GUARDIAN_RELEASE_REPOSITORY, GUARDIAN_DEFAULT_CONTROL_TOWER_URL, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ID_ENV, GUARDIAN_DESKTOP_ADAPTER_SIMULATE_OPEN_ENV, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_ID, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_PROOF_SCHEMA_VERSION, GUARDIAN_SERVICE_PROOF_SCHEMA_VERSION, GUARDIAN_OS_KEY_STORAGE_PROOF_SCHEMA_VERSION, GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION, PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2, PROMPT_COACH_MODES, DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT, GUARDIAN_POSTURE_PROFILE_IDS, GUARDIAN_POSTURE_PROFILE_CATALOG, GUARDIAN_POLICY_PACK_MARKETPLACE_CATALOG, GUARDIAN_PROVIDER_IDS, GUARDIAN_SOURCE_TYPES, GUARDIAN_NOT_PROVEN_PRODUCTION_GATES, DEFAULT_POLICY_PACKS, GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY, GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY, GUARDIAN_BRIDGE_CONFIG_SCHEMA_VERSION, GUARDIAN_NATIVE_HOST_NAME, MCP_CLIENTS, NATIVE_HOST_BROWSERS, HELP_TEXT, normalizeGuardianPreferences, GUARDIAN_DATA_FILE_NAMES, GUARDIAN_DATA_DIR_NAMES, GUARDIAN_MIN_SUPPORTED_NODE_VERSION;
22315
23138
  var init_runtime = __esm({
22316
23139
  "packages/guardian-cli/src/runtime.ts"() {
22317
23140
  "use strict";
22318
23141
  init_src();
22319
23142
  init_src2();
22320
- GUARDIAN_CLI_VERSION = "0.1.3";
23143
+ GUARDIAN_CLI_VERSION = "0.1.4";
22321
23144
  GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
22322
23145
  GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
23146
+ GUARDIAN_NPM_REGISTRY = "https://registry.npmjs.org/";
22323
23147
  GUARDIAN_GLOBAL_INSTALL_COMMAND = `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}`;
22324
23148
  GUARDIAN_NPX_SETUP_COMMAND = `npx ${GUARDIAN_NPM_PACKAGE_NAME}@latest setup`;
22325
23149
  GUARDIAN_FIRST_RUN_COMMAND = "guardian setup";
22326
- GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian launch";
23150
+ GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian open";
23151
+ GUARDIAN_RELEASE_DISPATCH_WORKFLOW = "guardian-release-dispatch.yml";
23152
+ GUARDIAN_RELEASE_REPOSITORY = "Intelligent-Context-AI-Inc/ContextECF-GITHUB";
22327
23153
  GUARDIAN_DEFAULT_CONTROL_TOWER_URL = "http://127.0.0.1:4317/control-tower";
22328
23154
  GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY";
22329
23155
  GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID";
@@ -22749,28 +23575,6 @@ var init_runtime = __esm({
22749
23575
  "Release evidence includes artifact digests without signing secrets."
22750
23576
  ]
22751
23577
  },
22752
- {
22753
- id: "browser-store-distribution",
22754
- label: "Browser store distribution",
22755
- boundary: "Pending store submission, review, and release evidence.",
22756
- owner: "browser-release",
22757
- runtimeBoundary: "Pending store submission, review, and release evidence.",
22758
- releaseBoundary: "Browser store approval and listing evidence are not yet proven.",
22759
- evidencePacket: "browser-store-distribution",
22760
- evidenceRequiredFields: [
22761
- "stores",
22762
- "submitted_versions",
22763
- "review_status",
22764
- "package_digest_matches_release",
22765
- "listing_boundary_proof"
22766
- ],
22767
- closesWhen: [
22768
- "Chrome Web Store package id, version, and approval state are recorded.",
22769
- "Any claimed Edge or Firefox store distribution has matching approval evidence.",
22770
- "Store package digest matches the validated MV3 release artifact.",
22771
- "Store listing text uses the same proven/not-proven boundary."
22772
- ]
22773
- },
22774
23578
  {
22775
23579
  id: "high-risk-desktop-action-execution",
22776
23580
  label: "High-risk desktop action execution after authorization",
@@ -22851,19 +23655,26 @@ No global install:
22851
23655
 
22852
23656
  Open Control Tower:
22853
23657
  ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}
22854
- aliases: guardian tower, guardian control-tower
23658
+ start aliases: guardian launch, guardian tower, guardian control-tower
22855
23659
 
22856
23660
  Usage:
22857
23661
  guardian --version
22858
23662
  guardian version [--json]
22859
- guardian setup [--json] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
23663
+ guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
22860
23664
  guardian install [--json]
22861
23665
  guardian doctor [--json]
22862
23666
  guardian readiness [--json] [--strict]
23667
+ guardian release checklist --version=<semver> [--json]
23668
+ guardian release flow --version=<semver> [--json]
23669
+ guardian release verify --version=<semver> [--json]
23670
+ guardian release paste --version=<semver> [--json]
23671
+ guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--json]
23672
+ guardian release secrets [--json]
23673
+ guardian release browser-store [--json]
22863
23674
  guardian open [--json] [--print] [--url=http://127.0.0.1:<port>]
22864
23675
  guardian status [--json]
22865
23676
  guardian start [--json] [--host=127.0.0.1] [--port=4317]
22866
- guardian launch|tower|control-tower [--json] [--print] [--host=127.0.0.1] [--port=4317]
23677
+ guardian launch|tower|control-tower [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317]
22867
23678
  guardian stop [--json] [--url=http://127.0.0.1:<port>/control-tower]
22868
23679
  guardian service install [--json] [--platform=auto|launchd|systemd|windows-task-scheduler] [--force]
22869
23680
  guardian service status [--json]
@@ -22919,6 +23730,7 @@ Defaults are local-first: raw capture, cloud sync, learning graph, and app autop
22919
23730
  "permissions.json"
22920
23731
  ];
22921
23732
  GUARDIAN_DATA_DIR_NAMES = ["ecl", "receipts", "mcp"];
23733
+ GUARDIAN_MIN_SUPPORTED_NODE_VERSION = [20, 20, 0];
22922
23734
  }
22923
23735
  });
22924
23736
 
@@ -23837,10 +24649,16 @@ function confirmationTokenFor(receipt, actionRequest) {
23837
24649
  return `guardian-confirm:${stableId(
23838
24650
  receipt.receipt_hash,
23839
24651
  actionRequest.action_id,
24652
+ actionRequest.app_id,
23840
24653
  actionRequest.action_type,
23841
- actionRequest.payload_hash
24654
+ actionRequest.target_ref,
24655
+ actionRequest.payload_hash,
24656
+ normalizedPolicyPackBinding(actionRequest.policy_pack_ids)
23842
24657
  )}`;
23843
24658
  }
24659
+ function normalizedPolicyPackBinding(policyPackIds) {
24660
+ return [...new Set(policyPackIds)].sort().join(",");
24661
+ }
23844
24662
  function buildLocalActionExecutionPlan(actionRequest, receipt, now) {
23845
24663
  const core = {
23846
24664
  action_id: actionRequest.action_id,
@@ -24937,6 +25755,7 @@ __export(daemon_exports, {
24937
25755
  processGuardianControlTowerSourcePermissionRequest: () => processGuardianControlTowerSourcePermissionRequest,
24938
25756
  processGuardianDaemonHealthRequest: () => processGuardianDaemonHealthRequest,
24939
25757
  processGuardianDaemonStopRequest: () => processGuardianDaemonStopRequest,
25758
+ processGuardianLiveCoachEventRequest: () => processGuardianLiveCoachEventRequest,
24940
25759
  readGuardianDaemonJsonBody: () => readGuardianDaemonJsonBody,
24941
25760
  renderControlTowerStatusPage: () => renderControlTowerStatusPage,
24942
25761
  startGuardianDaemonLoopback: () => startGuardianDaemonLoopback
@@ -25063,7 +25882,8 @@ async function handleRequest(input2) {
25063
25882
  writeJson(input2.response, 200, {
25064
25883
  ok: true,
25065
25884
  service: "project-guardian-daemon",
25066
- rawContentPersistence: false
25885
+ rawContentPersistence: false,
25886
+ version: GUARDIAN_CLI_VERSION
25067
25887
  });
25068
25888
  return;
25069
25889
  }
@@ -25217,6 +26037,24 @@ async function handleRequest(input2) {
25217
26037
  writeAdminResponse(input2.response, result2.statusCode, result2.body, parsedBody2.redirect);
25218
26038
  return;
25219
26039
  }
26040
+ if (input2.request.method === "POST" && input2.request.url === "/v1/guardian/live-coach-event") {
26041
+ const suppliedToken2 = headerValue(input2.request, ADMIN_HEADER);
26042
+ const parsedBody2 = await readGuardianDaemonJsonBody(input2.request);
26043
+ if (!parsedBody2.ok) {
26044
+ writeJson(input2.response, parsedBody2.statusCode, parsedBody2.body);
26045
+ return;
26046
+ }
26047
+ const result2 = await processGuardianLiveCoachEventRequest({
26048
+ profile: input2.profile,
26049
+ token: input2.token,
26050
+ suppliedToken: suppliedToken2,
26051
+ body: parsedBody2.body,
26052
+ now: input2.now,
26053
+ store: input2.store
26054
+ });
26055
+ writeJson(input2.response, result2.statusCode, result2.body);
26056
+ return;
26057
+ }
25220
26058
  if (input2.request.method !== "POST" || input2.request.url !== "/v1/guardian/process-prompt") {
25221
26059
  writeJson(input2.response, 404, { ok: false, error: "not_found" });
25222
26060
  return;
@@ -25252,7 +26090,8 @@ function processGuardianDaemonHealthRequest(input2) {
25252
26090
  body: {
25253
26091
  ok: true,
25254
26092
  service: "project-guardian-daemon",
25255
- rawContentPersistence: false
26093
+ rawContentPersistence: false,
26094
+ version: GUARDIAN_CLI_VERSION
25256
26095
  }
25257
26096
  };
25258
26097
  }
@@ -25668,6 +26507,44 @@ async function processGuardianBrowserBridgeRequest(input2) {
25668
26507
  });
25669
26508
  return { statusCode: 200, body: { ok: true, decision } };
25670
26509
  }
26510
+ async function processGuardianLiveCoachEventRequest(input2) {
26511
+ if (!isAuthorized(input2.token, input2.suppliedToken)) {
26512
+ return {
26513
+ statusCode: 401,
26514
+ body: {
26515
+ ok: false,
26516
+ error: "unauthorized"
26517
+ }
26518
+ };
26519
+ }
26520
+ const envelope = parseLiveCoachEventEnvelope(input2.body);
26521
+ if (!envelope.ok) {
26522
+ return {
26523
+ statusCode: 400,
26524
+ body: {
26525
+ ok: false,
26526
+ error: envelope.error
26527
+ }
26528
+ };
26529
+ }
26530
+ const timestamp = validDateTime(envelope.request.capturedAt) ?? input2.now().toISOString();
26531
+ const transactionId = `txn:browser-live-coach:${digest4(
26532
+ `${envelope.request.provider}:${envelope.request.destination}:${envelope.request.category}:${timestamp}`
26533
+ ).slice(0, 20)}`;
26534
+ const receipt = buildLiveCoachReceipt(envelope.request, transactionId, timestamp);
26535
+ await input2.store.putReceipt(receipt);
26536
+ await input2.store.appendEvent(
26537
+ buildLiveCoachEvent(envelope.request, transactionId, timestamp, receipt)
26538
+ );
26539
+ return {
26540
+ statusCode: 200,
26541
+ body: {
26542
+ ok: true,
26543
+ receipt_id: receipt.receipt_id,
26544
+ raw_content_included: false
26545
+ }
26546
+ };
26547
+ }
25671
26548
  async function processBrowserPrompt(input2) {
25672
26549
  const timestamp = validDateTime(input2.request.capturedAt) ?? input2.now().toISOString();
25673
26550
  const transactionId = `txn:browser:${digest4(`${input2.request.promptText}:${timestamp}`).slice(0, 20)}`;
@@ -25846,6 +26723,95 @@ function parseBridgeEnvelope(value) {
25846
26723
  }
25847
26724
  };
25848
26725
  }
26726
+ function parseLiveCoachEventEnvelope(value) {
26727
+ if (typeof value !== "object" || value === null) {
26728
+ return { ok: false, error: "invalid_json_body" };
26729
+ }
26730
+ const envelope = value;
26731
+ if (envelope.adapter !== "browser_mv3" || typeof envelope.request !== "object" || envelope.request === null) {
26732
+ return { ok: false, error: "invalid_guardian_adapter_envelope" };
26733
+ }
26734
+ const candidate = envelope.request;
26735
+ if ("promptText" in candidate || "rawPrompt" in candidate || "detectedValue" in candidate) {
26736
+ return { ok: false, error: "raw_content_not_allowed_for_live_coach_event" };
26737
+ }
26738
+ const provider = parseProvider(candidate.provider);
26739
+ const destination = stringField(candidate, "destination");
26740
+ const pageOrigin = stringField(candidate, "pageOrigin");
26741
+ const category = parseLiveCoachCategory(candidate.category);
26742
+ const capturedAt = stringField(candidate, "capturedAt");
26743
+ if (!destination || !pageOrigin || !category || !capturedAt) {
26744
+ return { ok: false, error: "missing_required_live_coach_event_fields" };
26745
+ }
26746
+ return {
26747
+ ok: true,
26748
+ request: {
26749
+ provider,
26750
+ destination,
26751
+ pageOrigin,
26752
+ category,
26753
+ capturedAt
26754
+ }
26755
+ };
26756
+ }
26757
+ function parseLiveCoachCategory(value) {
26758
+ return value === "ssn" || value === "password" || value === "secret" || value === "payment" || value === "health" ? value : void 0;
26759
+ }
26760
+ function buildLiveCoachReceipt(request, transactionId, timestamp) {
26761
+ const core = {
26762
+ transaction_id: transactionId,
26763
+ provider: request.provider,
26764
+ destination_hash: digest4(request.destination),
26765
+ page_origin_hash: digest4(request.pageOrigin),
26766
+ category: request.category,
26767
+ created_at: timestamp,
26768
+ raw_content_included: false
26769
+ };
26770
+ return {
26771
+ schema_version: PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION,
26772
+ receipt_id: `receipt:${transactionId}:live-coach`,
26773
+ transaction_id: transactionId,
26774
+ receipt_type: "policy",
26775
+ disposition: "warn",
26776
+ policy_basis: [
26777
+ "live-sensitive-prompt-coach",
26778
+ `category:${request.category}`,
26779
+ `provider:${request.provider}`
26780
+ ],
26781
+ receipt_hash: `sha256:${digest4(JSON.stringify(core))}`,
26782
+ raw_content_included: false,
26783
+ created_at: timestamp,
26784
+ summary: `Guardian flagged ${liveCoachCategoryLabel(request.category)} while drafting in ${providerDisplayName(request.provider)}.`
26785
+ };
26786
+ }
26787
+ function buildLiveCoachEvent(request, transactionId, timestamp, receipt) {
26788
+ const payload = {
26789
+ provider: request.provider,
26790
+ destination_hash: digest4(request.destination),
26791
+ page_origin_hash: digest4(request.pageOrigin),
26792
+ category: request.category,
26793
+ raw_content_included: false
26794
+ };
26795
+ return {
26796
+ event_id: `event:${transactionId}:live-coach`,
26797
+ transaction_id: transactionId,
26798
+ event_type: "coach_presented",
26799
+ occurred_at: timestamp,
26800
+ actor: "guardian-daemon",
26801
+ summary: `Live Prompt Coach presented ${request.category} warning.`,
26802
+ payload_hash: `sha256:${digest4(JSON.stringify(payload))}`,
26803
+ receipt_id: receipt.receipt_id,
26804
+ graph_refs: [`provider:${request.provider}`, `receipt:${receipt.receipt_id}`],
26805
+ redaction_state: "metadata_only"
26806
+ };
26807
+ }
26808
+ function liveCoachCategoryLabel(category) {
26809
+ if (category === "ssn") return "possible SSN sharing";
26810
+ if (category === "password") return "possible credential sharing";
26811
+ if (category === "secret") return "possible secret sharing";
26812
+ if (category === "payment") return "possible financial data";
26813
+ return "possible health information";
26814
+ }
25849
26815
  function parseProvider(value) {
25850
26816
  return value === "chatgpt" || value === "claude" || value === "gemini" || value === "perplexity" ? value : "unknown";
25851
26817
  }