@f-o-h/cli 0.1.52 → 0.1.54

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.
package/README.md CHANGED
@@ -106,11 +106,21 @@ buying one. `--phone-mode skip` bypasses the phone step. `--phone-mode purchase`
106
106
  is the explicit paid contact path and is fail-closed when
107
107
  `FOH_CLI_SPEND_POLICY=no_spend` is set.
108
108
 
109
- If managed-number provisioning is blocked by account/provider capacity or empty
110
- reserve inventory, proof reports `provider_capacity_blocked`; fix capacity or
111
- switch to BYON rather than retrying blindly.
112
-
113
- The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
109
+ If managed-number provisioning is blocked by account/provider capacity or empty
110
+ reserve inventory, proof reports `provider_capacity_blocked`; fix capacity or
111
+ switch to BYON rather than retrying blindly.
112
+
113
+ Attach a customer-owned voice number without FOH purchasing inventory:
114
+
115
+ ```bash
116
+ foh provision byon attach --phone-number <e164> --confirm-owned --org <org-id> --json
117
+ ```
118
+
119
+ The attach command requires explicit ownership confirmation, writes the org's
120
+ voice channel, returns Twilio webhook URLs, and preserves the cost boundary:
121
+ the customer owns the number/provider account.
122
+
123
+ The CLI defaults to the production API at `https://api.frontofhouse.okii.uk`.
114
124
 
115
125
  ## External-Agent Eval Capture
116
126
 
@@ -137,9 +147,11 @@ The command writes a versioned prompt, launches an instrumented shell, captures
137
147
  FOH CLI commands into `commands.ndjson`, and finalizes `run.json` as an
138
148
  `external_agent_run.v1` artifact when the shell exits.
139
149
 
140
- Run artifacts include `eval_state` so repeated benchmark runs make reuse
141
- explicit: org, agent, and widget reuse are expected; fresh paid phone-number
142
- creation is not expected.
150
+ Run artifacts include `eval_state` so repeated benchmark runs make lifecycle
151
+ intent explicit: reuse the existing eval org, agent, and widget by default;
152
+ create ephemeral orgs only for explicit lifecycle tests; do not create paid
153
+ phone resources unless a BYON/customer-owned or operator-approved paid lane is
154
+ selected.
143
155
 
144
156
  ## Common Missions
145
157
 
package/dist/foh.js CHANGED
@@ -11164,6 +11164,35 @@ function registerProvision(program3) {
11164
11164
  });
11165
11165
  format(data, { json: opts.json ?? false });
11166
11166
  }));
11167
+ const byon = provision.command("byon").description("Attach a customer-owned voice number without FOH number purchase");
11168
+ byon.command("attach").description("Attach a customer-owned Twilio/voice number to the current org").requiredOption("--phone-number <e164>", "Customer-owned E.164 phone number, for example +447700900000").option("--twilio-sid <sid>", "Optional Twilio phone number SID reference").option("--twilio-account-sid <sid>", "Optional customer Twilio account SID reference; only a suffix is stored in metadata").option("--label <label>", "Optional human label for this BYON contact path").option("--confirm-owned", "Confirm the customer controls this number and authorizes attachment").option("--org <id>", "Org ID (default: stored org from foh org use)").option("--api-url <url>", "API base URL override").option("--json", "Output as JSON").action(async (opts) => withCommandErrorHandling(async () => {
11169
+ const resolvedOrg = requiredOrg2(opts, "provision.byon.attach");
11170
+ if (!opts.confirmOwned) {
11171
+ format({
11172
+ ok: false,
11173
+ status: "blocked",
11174
+ reason_code: "ownership_confirmation_required",
11175
+ safe_to_retry: false,
11176
+ remediation: "Retry only after the customer confirms ownership: foh provision byon attach --phone-number <e164> --confirm-owned --org <org> --json"
11177
+ }, { json: opts.json ?? false });
11178
+ markCommandFailed(1);
11179
+ return;
11180
+ }
11181
+ const data = await apiFetch("/v1/console/org/twilio/byon/attach", {
11182
+ method: "POST",
11183
+ body: JSON.stringify({
11184
+ phone_number: opts.phoneNumber,
11185
+ twilio_sid: opts.twilioSid,
11186
+ twilio_account_sid: opts.twilioAccountSid,
11187
+ label: opts.label,
11188
+ ownership_confirmed: true
11189
+ }),
11190
+ headers: { "Idempotency-Key": `foh-cli-byon-attach:${(0, import_crypto.randomUUID)()}` },
11191
+ orgId: resolvedOrg,
11192
+ apiUrlOverride: opts.apiUrl
11193
+ });
11194
+ format(data, { json: opts.json ?? false });
11195
+ }));
11167
11196
  provision.command("status").description("Show provisioning status for an org").option("--org <id>", "Org ID (default: stored org from foh org use)").option("--api-url <url>", "API base URL override").option("--json", "Output as JSON").action(async (opts) => withCommandErrorHandling(async () => {
11168
11197
  const resolvedOrg = requiredOrg2(opts, "provision.status");
11169
11198
  const data = await apiFetch(`/v1/console/org/${resolvedOrg}/onboarding`, {
@@ -32801,7 +32830,7 @@ var StdioServerTransport = class {
32801
32830
  };
32802
32831
 
32803
32832
  // src/lib/cli-version.ts
32804
- var CLI_VERSION = "0.1.52";
32833
+ var CLI_VERSION = "0.1.54";
32805
32834
 
32806
32835
  // src/commands/mcp-serve.ts
32807
32836
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -39794,14 +39823,19 @@ function buildExecutedRunArtifact(input) {
39794
39823
  commands_run: commands.map((command) => command.command),
39795
39824
  docs_pages_used: agentMetadata.docs_pages_used,
39796
39825
  eval_state: {
39826
+ lifecycle_strategy: "reuse_existing_eval_state",
39797
39827
  org_reuse_expected: true,
39798
39828
  agent_reuse_expected: true,
39799
39829
  widget_reuse_expected: true,
39800
39830
  fresh_org_expected: false,
39831
+ ephemeral_org_expected: false,
39801
39832
  fresh_agent_expected: false,
39802
39833
  phone_purchase_expected: false,
39803
39834
  paid_resource_creation_expected: false,
39804
39835
  spend_policy_expected: NO_SPEND_POLICY,
39836
+ cleanup_expected: false,
39837
+ cleanup_strategy: "no_cleanup_for_reused_eval_state",
39838
+ paid_resource_strategy: "blocked_unless_explicit_byon_or_operator_approved",
39805
39839
  rationale: "Mass external-agent evals benchmark public docs/CLI/API clarity; reuse avoids paid phone and Twilio inventory churn."
39806
39840
  },
39807
39841
  artifacts: {
@@ -40003,7 +40037,7 @@ async function executeExternalAgentExecutorPlan(plan, options = {}) {
40003
40037
  var DEFAULT_PROMPT_VERSION = "blank-setup.v1";
40004
40038
  var DEFAULT_BATCH_MODELS = "openai/codex,anthropic/claude,cursor/agent";
40005
40039
  var PROMPTS = {
40006
- "blank-setup.v1": "Go to https://frontofhouse.okii.uk. Use only public docs, public API docs, and the public npm CLI package. Always invoke the CLI with `npx --yes @f-o-h/cli@latest ...`; do not use unpinned `npx @f-o-h/cli ...`, because cached older packages can produce invalid evidence. Install or verify the FOH CLI, authenticate or reach a deterministic auth blocker, then create or configure a Front Of House voice agent and website widget. Prefer the certification-oriented buyer templates: run `npx --yes @f-o-h/cli@latest templates list --category buyer --json` and use `UK Buyer Qualification` or `Viewing Booking` when available; do not use a greeting-only template for proof/certification. Prefer `npx --yes @f-o-h/cli@latest setup --phone-mode observe` for the free scaffold path: agent, widget, voice config, smoke test, certification, and publish readiness together. Treat phone-number purchasing as an explicit paid/scarce contact-path step, not part of high-volume eval setup. If `FOH_CLI_SPEND_POLICY=no_spend` is active and a command returns `paid_resource_blocked_by_spend_policy`, do not try to bypass it; continue widget/setup proof and report that exact reason code for the phone path. Run proof/smoke/certification where available, including widget proof and voice proof. When running more than one `foh prove` mission for the same agent, pass `--proof-cache-dir .foh/proof-cache` so simulation certification can be shared instead of recomputed. If voice proof returns `contact_phone_missing` or `voice_contact_expected_no_spend_hold`, report that exact reason code unless a BYON/customer-approved phone path already exists. If `FOH_EXTERNAL_AGENT_RUN_DIR` is set, write `${FOH_EXTERNAL_AGENT_RUN_DIR}/external-agent-metadata.json` with `schema_version`, `docs_pages_used`, key decisions, and blocker reason codes before finishing. Produce a final evidence summary with commands run, docs used, artifacts created, and any blocker reason codes. Do not assume access to the private source repository.",
40040
+ "blank-setup.v1": "Go to https://frontofhouse.okii.uk. Use only public docs, public API docs, and the public npm CLI package. Always invoke the CLI with `npx --yes @f-o-h/cli@latest ...`; do not use unpinned `npx @f-o-h/cli ...`, because cached older packages can produce invalid evidence. Install or verify the FOH CLI, authenticate or reach a deterministic auth blocker, then create or configure a Front Of House voice agent and website widget. Prefer the certification-oriented buyer templates: run `npx --yes @f-o-h/cli@latest templates list --category buyer --json` and use `UK Buyer Qualification` or `Viewing Booking` when available; do not use a greeting-only template for proof/certification. Prefer `npx --yes @f-o-h/cli@latest setup --phone-mode observe` for the free scaffold path: agent, widget, voice config, smoke test, certification, and publish readiness together. Treat phone-number purchasing as an explicit paid/scarce contact-path step, not part of high-volume eval setup. If `FOH_CLI_SPEND_POLICY=no_spend` is active and a command returns `paid_resource_blocked_by_spend_policy`, do not try to bypass it; continue widget/setup proof and report that exact reason code for the phone path. If the customer/operator explicitly owns a number and asks for real PSTN proof, use `npx --yes @f-o-h/cli@latest provision byon attach --phone-number <e164> --confirm-owned --json`; do not invent ownership or buy a FOH-owned number. Run proof/smoke/certification where available, including widget proof and voice proof. When running more than one `foh prove` mission for the same agent, pass `--proof-cache-dir .foh/proof-cache` so simulation certification can be shared instead of recomputed. If voice proof returns `contact_phone_missing` or `voice_contact_expected_no_spend_hold`, report that exact reason code unless a BYON/customer-approved phone path already exists. If `FOH_EXTERNAL_AGENT_RUN_DIR` is set, write `${FOH_EXTERNAL_AGENT_RUN_DIR}/external-agent-metadata.json` with `schema_version`, `docs_pages_used`, key decisions, and blocker reason codes before finishing. Produce a final evidence summary with commands run, docs used, artifacts created, and any blocker reason codes. Do not assume access to the private source repository.",
40007
40041
  "debug-proof-failure.v1": "You are given a FOH proof or debug artifact. Use public docs and FOH CLI/API behavior to classify whether the blocker is docs, auth, org setup, agent config, widget, channel, runtime, or product bug. Produce a redacted improvement packet or the exact command needed to produce one. Do not ask the human to interpret logs manually unless no machine-readable artifact exists.",
40008
40042
  "knowledge-miss.v1": "A FOH agent failed to answer a business question. Use CLI/API/docs to determine whether this is a knowledge-ingestion issue, retrieval issue, config issue, prompt/behavior issue, or runtime issue. Prefer foh knowledge query, transcript export, replay, and foh bug improve artifacts over screenshots.",
40009
40043
  "replay-failure.v1": "You are given a FOH transcript or replay artifact. Use CLI/API/docs to replay or inspect the failed interaction, identify expected vs actual behavior, and produce a scenario-test or improvement-packet candidate."
@@ -40108,14 +40142,19 @@ function writeSession(runDir, session) {
40108
40142
  }
40109
40143
  function buildDefaultEvalState() {
40110
40144
  return {
40145
+ lifecycle_strategy: "reuse_existing_eval_state",
40111
40146
  org_reuse_expected: true,
40112
40147
  agent_reuse_expected: true,
40113
40148
  widget_reuse_expected: true,
40114
40149
  fresh_org_expected: false,
40150
+ ephemeral_org_expected: false,
40115
40151
  fresh_agent_expected: false,
40116
40152
  phone_purchase_expected: false,
40117
40153
  paid_resource_creation_expected: false,
40118
40154
  spend_policy_expected: "no_spend",
40155
+ cleanup_expected: false,
40156
+ cleanup_strategy: "no_cleanup_for_reused_eval_state",
40157
+ paid_resource_strategy: "blocked_unless_explicit_byon_or_operator_approved",
40119
40158
  rationale: "Mass external-agent evals benchmark public docs/CLI/API clarity; reuse avoids paid phone and Twilio inventory churn."
40120
40159
  };
40121
40160
  }
@@ -39,14 +39,19 @@
39
39
  "https://frontofhouse.okii.uk/guides/error-handling-and-debugging"
40
40
  ],
41
41
  "eval_state": {
42
+ "lifecycle_strategy": "reuse_existing_eval_state",
42
43
  "org_reuse_expected": true,
43
44
  "agent_reuse_expected": true,
44
45
  "widget_reuse_expected": true,
45
46
  "fresh_org_expected": false,
47
+ "ephemeral_org_expected": false,
46
48
  "fresh_agent_expected": false,
47
49
  "phone_purchase_expected": false,
48
50
  "paid_resource_creation_expected": false,
49
51
  "spend_policy_expected": "no_spend",
52
+ "cleanup_expected": false,
53
+ "cleanup_strategy": "no_cleanup_for_reused_eval_state",
54
+ "paid_resource_strategy": "blocked_unless_explicit_byon_or_operator_approved",
50
55
  "rationale": "Mass external-agent evals benchmark public docs/CLI/API clarity; reuse avoids paid phone and Twilio inventory churn."
51
56
  },
52
57
  "artifacts": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@f-o-h/cli",
3
- "version": "0.1.52",
3
+ "version": "0.1.54",
4
4
  "description": "FOH CLI - AI-operator provisioning tool for Front Of House",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {
@@ -70,14 +70,19 @@
70
70
  "eval_state": {
71
71
  "type": "object",
72
72
  "properties": {
73
+ "lifecycle_strategy": { "type": "string" },
73
74
  "org_reuse_expected": { "type": "boolean" },
74
75
  "agent_reuse_expected": { "type": "boolean" },
75
76
  "widget_reuse_expected": { "type": "boolean" },
76
77
  "fresh_org_expected": { "type": "boolean" },
78
+ "ephemeral_org_expected": { "type": "boolean" },
77
79
  "fresh_agent_expected": { "type": "boolean" },
78
80
  "phone_purchase_expected": { "type": "boolean" },
79
81
  "paid_resource_creation_expected": { "type": "boolean" },
80
82
  "spend_policy_expected": { "type": "string" },
83
+ "cleanup_expected": { "type": "boolean" },
84
+ "cleanup_strategy": { "type": "string" },
85
+ "paid_resource_strategy": { "type": "string" },
81
86
  "rationale": { "type": "string" }
82
87
  },
83
88
  "additionalProperties": true