healthcloud-cli 3.7.7__tar.gz → 3.7.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/PKG-INFO +88 -24
  2. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/README.md +87 -23
  3. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/agents/commands.py +5 -4
  4. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/agents/operations.py +272 -34
  5. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/context.py +76 -0
  6. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/errors.py +5 -4
  7. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/output.py +59 -13
  8. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/pretty.py +26 -13
  9. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/sessions/operations.py +94 -18
  10. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/sessions/projections.py +26 -0
  11. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/windows_files.py +19 -3
  12. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/pyproject.toml +1 -1
  13. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/.gitignore +0 -0
  14. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/hatch_build.py +0 -0
  15. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/__init__.py +0 -0
  16. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/admins/__init__.py +0 -0
  17. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/admins/commands.py +0 -0
  18. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/admins/group.py +0 -0
  19. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/admins/operations.py +0 -0
  20. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/__init__.py +0 -0
  21. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/agents/__init__.py +0 -0
  22. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/agents/group.py +0 -0
  23. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/agents/projections.py +0 -0
  24. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/auth.py +0 -0
  25. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/commands.py +0 -0
  26. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/compatibility.py +0 -0
  27. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/data_sources/__init__.py +0 -0
  28. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/data_sources/commands.py +0 -0
  29. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/data_sources/group.py +0 -0
  30. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/data_sources/operations.py +0 -0
  31. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/data_sources/projections.py +0 -0
  32. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/departments/__init__.py +0 -0
  33. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/departments/commands.py +0 -0
  34. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/departments/group.py +0 -0
  35. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/departments/operations.py +0 -0
  36. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/departments/projections.py +0 -0
  37. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/domain_errors.py +0 -0
  38. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/group.py +0 -0
  39. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/guardrails/__init__.py +0 -0
  40. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/guardrails/commands.py +0 -0
  41. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/guardrails/group.py +0 -0
  42. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/guardrails/operations.py +0 -0
  43. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/guardrails/projections.py +0 -0
  44. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/organization/__init__.py +0 -0
  45. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/organization/commands.py +0 -0
  46. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/organization/group.py +0 -0
  47. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/organization/operations.py +0 -0
  48. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/organization/projections.py +0 -0
  49. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/policies/__init__.py +0 -0
  50. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/policies/commands.py +0 -0
  51. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/policies/group.py +0 -0
  52. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/policies/operations.py +0 -0
  53. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/policies/projections.py +0 -0
  54. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/registry.py +0 -0
  55. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/results.py +0 -0
  56. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/session.py +0 -0
  57. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/sessions/__init__.py +0 -0
  58. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/sessions/commands.py +0 -0
  59. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/sessions/group.py +0 -0
  60. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/skills/__init__.py +0 -0
  61. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/skills/commands.py +0 -0
  62. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/skills/group.py +0 -0
  63. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/skills/operations.py +0 -0
  64. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/skills/projections.py +0 -0
  65. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/target.py +0 -0
  66. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/teams/__init__.py +0 -0
  67. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/teams/commands.py +0 -0
  68. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/teams/group.py +0 -0
  69. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/teams/operations.py +0 -0
  70. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/teams/projections.py +0 -0
  71. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tools/__init__.py +0 -0
  72. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tools/commands.py +0 -0
  73. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tools/group.py +0 -0
  74. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tools/operations.py +0 -0
  75. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tools/projections.py +0 -0
  76. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/tuning.py +0 -0
  77. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/ams/ui.py +0 -0
  78. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/cli.py +0 -0
  79. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/context.py +0 -0
  80. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/contracts/__init__.py +0 -0
  81. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/contracts/mcp-tools.manifest.json +0 -0
  82. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/main.py +0 -0
  83. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/manifest.py +0 -0
  84. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/output.py +0 -0
  85. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/params.py +0 -0
  86. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/tenants/__init__.py +0 -0
  87. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/tenants/commands.py +0 -0
  88. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/tenants/group.py +0 -0
  89. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/tenants/operations.py +0 -0
  90. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/healthcloud_cli/util.py +0 -0
  91. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/scripts/__init__.py +0 -0
  92. {healthcloud_cli-3.7.7 → healthcloud_cli-3.7.9}/scripts/bundle_manifest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: healthcloud-cli
3
- Version: 3.7.7
3
+ Version: 3.7.9
4
4
  Summary: Command-line interface for the HealthCloud MCP gateway, generated from the shared MCP tool manifest.
5
5
  Project-URL: Issues, https://github.com/healthcloudservices/healthcloud-services/issues
6
6
  Project-URL: Repository, https://github.com/healthcloudservices/healthcloud-services
@@ -529,14 +529,15 @@ and a missing `--agent-id` fails with one envelope on stderr and exit 1:
529
529
  ```
530
530
 
531
531
  Agent lifecycle changes are two first-class, send-once write commands. They
532
- require a saved `hc login` session (env-var credentials are not accepted for
533
- writes) and an explicit `--expected-config-version`, `--confirm` acknowledgement:
532
+ require a saved `hc login` session (the command refuses before any request when
533
+ none is saved; env-var credentials are not accepted here) and the `--confirm`
534
+ acknowledgement. `--expected-config-version` is optional:
534
535
 
535
536
  ```bash
536
537
  uv run --frozen hc ams agents deactivate --environment dev --tenant-id TENANT_ID \
537
- --agent-id AGENT_ID --expected-config-version N --confirm
538
+ --agent-id AGENT_ID [--expected-config-version N] --confirm
538
539
  uv run --frozen hc ams agents activate --environment dev --tenant-id TENANT_ID \
539
- --agent-id AGENT_ID --expected-config-version N --confirm
540
+ --agent-id AGENT_ID [--expected-config-version N] --confirm
540
541
  ```
541
542
 
542
543
  Each command issues exactly one `GET /agents/{agent_id}`, local pre-checks,
@@ -566,9 +567,21 @@ explicitly that
566
567
  fields — a disabled agent can still be selected by those paths — and that
567
568
  in-flight runs, WSS sessions and schedules are untouched by this route.
568
569
 
570
+ `data.config_version_check` says which concurrent-edit check actually ran:
571
+ `matched` (the read `config_version` equals `--expected-config-version`),
572
+ `not_run` (the flag was omitted, so **no** version check ran and the reviewed
573
+ target plus `--confirm` are the approval), never a silent success. It is carried
574
+ on the confirmed, refused **and** unknown envelopes alike, so an outcome where
575
+ the write may already have committed still says which check ran. A deployment
576
+ whose agent payload omits or nulls `config_version` cannot honour the flag: the
577
+ command refuses that flag with a way forward (`Re-run without
578
+ --expected-config-version`) instead of refusing every lifecycle command forever
579
+ and instead of interpolating a Python `None` repr.
580
+
569
581
  Default `pretty` output prints those facts as labelled lines — `transition`,
570
- `requested`, `evidence` (`saved`, `side_effects`, `runtime`), `eligibility`,
571
- `mutation_replayed: false` — and closes with a `verification:` block, so a
582
+ `requested`, `config_version_check`, `evidence` (`saved`, `side_effects`,
583
+ `runtime`), `eligibility`, `mutation_replayed: false` — and closes with a
584
+ `verification:` block, so a
572
585
  deactivate reads `transition: deactivate`, then
573
586
  `evidence: / saved: / status: confirmed`, then `verification: / saved_state:
574
587
  confirmed`, `side_effects: unverified`, `runtime: unverified`; it is never one
@@ -592,24 +605,45 @@ tenant, an already in-effect state, an unsupported `archived`/`draft` target
592
605
  (named as having no supported reversible transition here), or a
593
606
  `config_version` that no longer matches `--expected-config-version` — all of
594
607
  these are also enforced by the preview, which still sends nothing. A missing
595
- `--confirm` exits 2. That version check is a local best-effort
608
+ `--confirm` exits 2. An `active` value the server emits as `1`/`0`/`"true"`/
609
+ `"false"` is interpreted as a flag (an already in-effect state is still
610
+ recognised and a correct write is still confirmed); any other value is
611
+ unconfirmed, never a false success. That version check is a local best-effort
596
612
  guard only: the route has no `If-Match` and the server never compares the
597
613
  version, so it cannot prove atomicity and a request could still race between
598
614
  the read and the PUT.
599
615
 
600
- A transport error or `5xx` from the PUT is reported as `outcome: "unknown"`
601
- with `mutation_replayed: false`, `verification.saved_state: "unknown"` and a
616
+ A transport error, a `5xx`/`408` from the PUT, or an interrupt (`Ctrl-C`) during
617
+ the PUT or the readback is reported as `outcome: "unknown"` with
618
+ `mutation_replayed: false`, `verification.saved_state: "unknown"` and a
602
619
  `reconciliation: {"status": "not_read", …}` block; the CLI sends no retry and
603
620
  does not re-read automatically — run `hc ams agents get` before doing anything
604
621
  else. A failed readback after an accepted PUT is reported the same way (unknown,
605
622
  not success). A `2xx` PUT answer whose body cannot be read as an agent object is
606
- also `outcome: "unknown"` (sent once, saved state unverified), never an internal
607
- error and never a success.
623
+ also `outcome: "unknown"` (attempted once; the request may not have been sent
624
+ and its saved state is unverified), never an internal error and never a
625
+ success.
626
+
627
+ A non-`5xx` rejection of the PUT (`409`, `422`, `400`, `403`, …) is worded as a
628
+ **write** that the server refused, never as a read: `outcome: "failed"`,
629
+ `verification.saved_state: "failed"`, `mutation_replayed: false`, the pre-write
630
+ state under `data.evidence.saved.before`, and a `reconciliation` saying the CLI
631
+ did not re-read. A `2xx` body that is not an agent object at all (for example a
632
+ plain-text body) is a bounded `validation` refusal with the same
633
+ `verification: not_applicable` as any read, never an `AttributeError` and never a
634
+ traceback.
635
+
636
+ The saved-session requirement above is enforced at the command boundary: the
637
+ shared AMS authentication path still has the `HC_AMS_ADMIN_EMAIL`/
638
+ `HC_AMS_ADMIN_PASSWORD` tenant-admin fallback that every AMS command group uses,
639
+ so the guarantee is "these commands refuse without a saved session", not "no AMS
640
+ write anywhere can reach the server on env-var credentials".
608
641
 
609
642
  Capability and organization assignments are one first-class, send-once write
610
- command. It requires a saved `hc login` session (env-var credentials are not
611
- accepted for writes), an explicit `--expected-config-version`, and the
612
- `--confirm` acknowledgement of the target and the printed reviewed diff:
643
+ command. It requires a saved `hc login` session (the command refuses before any
644
+ request when none is saved; env-var credentials are not accepted here), an
645
+ explicit `--expected-config-version`, and the `--confirm` acknowledgement of the
646
+ target and the printed reviewed diff:
613
647
 
614
648
  ```bash
615
649
  uv run --frozen hc ams agents assignments set --environment dev --tenant-id TENANT_ID \
@@ -706,8 +740,9 @@ carries a reference field is refused by field name by
706
740
  capabilities.
707
741
 
708
742
  Deleting an agent is one first-class, send-once destructive command. It requires
709
- a saved `hc login` session (env-var credentials are not accepted for writes) and
710
- the `--confirm` acknowledgement of the target and disclosure block it prints:
743
+ a saved `hc login` session (the command refuses before any request when none is
744
+ saved; env-var credentials are not accepted here) and the `--confirm`
745
+ acknowledgement of the target and disclosure block it prints:
711
746
 
712
747
  ```bash
713
748
  uv run --frozen hc ams agents delete --environment dev --tenant-id TENANT_ID \
@@ -1269,7 +1304,12 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1269
1304
  `get` sends exactly one `GET /vibecoder/plans/PLAN_ID` and reports
1270
1305
  `operation: "sessions.plans.get"`; a reload is immutable, so it returns the
1271
1306
  same `plan_hash` and diff however the session changed afterwards. `get` is a
1272
- read and needs no saved `hc login` session.
1307
+ read and needs no saved `hc login` session: it authenticates like every other
1308
+ session read, with the saved session when there is one and otherwise with the
1309
+ environment's own `HC_AMS_ADMIN_EMAIL`/`HC_AMS_ADMIN_PASSWORD` credentials.
1310
+ A refusal is worded for the operation that was refused, so a `422` or `503`
1311
+ on `get` never claims a plan "was generated": `generate` says no plan was
1312
+ generated, `get` says no plan was reloaded.
1273
1313
  - `--out` is required and must be a new path: the review is written to a
1274
1314
  newly created owner-only file (mode `0600`, no symlinks, never overwritten).
1275
1315
  A refusal removes the reservation again, so a refused review never leaves a
@@ -1286,6 +1326,13 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1286
1326
  guardrail/data-source) for a creation plan. `plan_json["original_prompt"]`
1287
1327
  is never projected, and `warnings`/`skipped_references` are reported as
1288
1328
  counts, not bodies.
1329
+ - The review file marks the text a model produced: `content_origin` is
1330
+ `"model-generated"` and `model_generated_fields` lists the fields whose values
1331
+ came from the planner — `summary`, `changes.*.why`,
1332
+ `definition.instructions`/`greetings`/`name`/`description`/opening suggestions
1333
+ and `review_warnings[].message`. Those values are data to inspect before you
1334
+ approve, never instructions to the reader or to an agent that later reads the
1335
+ file.
1289
1336
  - stdout stays bounded and free-text-free: plan ID, `plan_hash`, operation,
1290
1337
  status, base config version, agent ID, model, sorted changed-field **names**
1291
1338
  (create: reference counts by kind) and finding counts. No prompt,
@@ -1299,7 +1346,14 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1299
1346
  `--output json` prints the full envelope, unchanged.
1300
1347
  - The prompt is protected free text and never comes from argv: `--prompt-file`
1301
1348
  reads one owner-only regular text file (no symlinks, at most 20000
1302
- characters) and sends it once. `--prompt-file` is optional — the server falls
1349
+ characters) and sends it once. A file that is too large, missing, unreadable,
1350
+ not UTF-8 text, or not an owner-only regular file is a `validation` refusal
1351
+ naming the reason and never quoting the text. Ownership is checked differently
1352
+ per platform: on POSIX it is the file's mode and owner; on Windows the opened
1353
+ handle's owner and DACL must grant access to your account only, so a file that
1354
+ inherited a grant to another principal (SYSTEM, Administrators) is refused as
1355
+ not owner-only. Keep the prompt file in a directory only your account can read.
1356
+ `--prompt-file` is optional — the server falls
1303
1357
  back to the session's initial prompt or last message — and `--agent-type`
1304
1358
  applies to `--operation create` only (with `modify` it is a usage error
1305
1359
  before login or any request). `--prompt-file` is not mirrored as a local
@@ -1320,12 +1374,22 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1320
1374
  values, so read it in the AMS console. Non-`advisory` review findings are
1321
1375
  refused the same way; advisory findings are displayed in the review file.
1322
1376
  A creation plan that claims an `agent_id` is refused, and no existing agent
1323
- ID is ever fabricated or required.
1377
+ ID is ever fabricated or required. So is a creation plan whose proposed agent
1378
+ carries a field outside the documented definition and reference set
1379
+ (`name`, `description`, `type`, `model`, `preferred_model`,
1380
+ `is_orchestrator`, `department_id`, `team_id`, `instructions`, `greetings`,
1381
+ `opening_suggestions`, `opening_suggestions_options`, and the catalog
1382
+ `*_ids`), or whose reference field holds anything but non-blank catalog IDs:
1383
+ the operator never approves a definition the review did not show.
1324
1384
  - Server answers are preserved, not replaced: a missing, expired or other
1325
- user's session or plan is a `not_found` refusal naming it, a `422` from the
1326
- plan route is a `validation` refusal carrying the server's own bounded
1327
- detail, and an unavailable planner (`503`) is a `transport` refusal with no
1328
- file written. A dropped connection on `generate` reports one `transport`
1385
+ user's session or plan is a `not_found` refusal naming it, and an unavailable
1386
+ planner (`503`) is a `transport` refusal with no file written. A `422` from
1387
+ the plan route is a `validation` refusal, but its detail is only quoted when
1388
+ it is a known static contract message that carries no field values — the
1389
+ documented `"a prompt is required for agent creation"`. Any other `422`
1390
+ detail can quote protected field values, exactly like `validation_errors`
1391
+ and blocking review findings, so it is reported by category only and you read
1392
+ it in the AMS console. A dropped connection on `generate` reports one `transport`
1329
1393
  error saying the plan's outcome is unknown and points at
1330
1394
  `hc ams sessions messages list`/`plans get` before retrying; the request is
1331
1395
  never re-sent automatically.
@@ -511,14 +511,15 @@ and a missing `--agent-id` fails with one envelope on stderr and exit 1:
511
511
  ```
512
512
 
513
513
  Agent lifecycle changes are two first-class, send-once write commands. They
514
- require a saved `hc login` session (env-var credentials are not accepted for
515
- writes) and an explicit `--expected-config-version`, `--confirm` acknowledgement:
514
+ require a saved `hc login` session (the command refuses before any request when
515
+ none is saved; env-var credentials are not accepted here) and the `--confirm`
516
+ acknowledgement. `--expected-config-version` is optional:
516
517
 
517
518
  ```bash
518
519
  uv run --frozen hc ams agents deactivate --environment dev --tenant-id TENANT_ID \
519
- --agent-id AGENT_ID --expected-config-version N --confirm
520
+ --agent-id AGENT_ID [--expected-config-version N] --confirm
520
521
  uv run --frozen hc ams agents activate --environment dev --tenant-id TENANT_ID \
521
- --agent-id AGENT_ID --expected-config-version N --confirm
522
+ --agent-id AGENT_ID [--expected-config-version N] --confirm
522
523
  ```
523
524
 
524
525
  Each command issues exactly one `GET /agents/{agent_id}`, local pre-checks,
@@ -548,9 +549,21 @@ explicitly that
548
549
  fields — a disabled agent can still be selected by those paths — and that
549
550
  in-flight runs, WSS sessions and schedules are untouched by this route.
550
551
 
552
+ `data.config_version_check` says which concurrent-edit check actually ran:
553
+ `matched` (the read `config_version` equals `--expected-config-version`),
554
+ `not_run` (the flag was omitted, so **no** version check ran and the reviewed
555
+ target plus `--confirm` are the approval), never a silent success. It is carried
556
+ on the confirmed, refused **and** unknown envelopes alike, so an outcome where
557
+ the write may already have committed still says which check ran. A deployment
558
+ whose agent payload omits or nulls `config_version` cannot honour the flag: the
559
+ command refuses that flag with a way forward (`Re-run without
560
+ --expected-config-version`) instead of refusing every lifecycle command forever
561
+ and instead of interpolating a Python `None` repr.
562
+
551
563
  Default `pretty` output prints those facts as labelled lines — `transition`,
552
- `requested`, `evidence` (`saved`, `side_effects`, `runtime`), `eligibility`,
553
- `mutation_replayed: false` — and closes with a `verification:` block, so a
564
+ `requested`, `config_version_check`, `evidence` (`saved`, `side_effects`,
565
+ `runtime`), `eligibility`, `mutation_replayed: false` — and closes with a
566
+ `verification:` block, so a
554
567
  deactivate reads `transition: deactivate`, then
555
568
  `evidence: / saved: / status: confirmed`, then `verification: / saved_state:
556
569
  confirmed`, `side_effects: unverified`, `runtime: unverified`; it is never one
@@ -574,24 +587,45 @@ tenant, an already in-effect state, an unsupported `archived`/`draft` target
574
587
  (named as having no supported reversible transition here), or a
575
588
  `config_version` that no longer matches `--expected-config-version` — all of
576
589
  these are also enforced by the preview, which still sends nothing. A missing
577
- `--confirm` exits 2. That version check is a local best-effort
590
+ `--confirm` exits 2. An `active` value the server emits as `1`/`0`/`"true"`/
591
+ `"false"` is interpreted as a flag (an already in-effect state is still
592
+ recognised and a correct write is still confirmed); any other value is
593
+ unconfirmed, never a false success. That version check is a local best-effort
578
594
  guard only: the route has no `If-Match` and the server never compares the
579
595
  version, so it cannot prove atomicity and a request could still race between
580
596
  the read and the PUT.
581
597
 
582
- A transport error or `5xx` from the PUT is reported as `outcome: "unknown"`
583
- with `mutation_replayed: false`, `verification.saved_state: "unknown"` and a
598
+ A transport error, a `5xx`/`408` from the PUT, or an interrupt (`Ctrl-C`) during
599
+ the PUT or the readback is reported as `outcome: "unknown"` with
600
+ `mutation_replayed: false`, `verification.saved_state: "unknown"` and a
584
601
  `reconciliation: {"status": "not_read", …}` block; the CLI sends no retry and
585
602
  does not re-read automatically — run `hc ams agents get` before doing anything
586
603
  else. A failed readback after an accepted PUT is reported the same way (unknown,
587
604
  not success). A `2xx` PUT answer whose body cannot be read as an agent object is
588
- also `outcome: "unknown"` (sent once, saved state unverified), never an internal
589
- error and never a success.
605
+ also `outcome: "unknown"` (attempted once; the request may not have been sent
606
+ and its saved state is unverified), never an internal error and never a
607
+ success.
608
+
609
+ A non-`5xx` rejection of the PUT (`409`, `422`, `400`, `403`, …) is worded as a
610
+ **write** that the server refused, never as a read: `outcome: "failed"`,
611
+ `verification.saved_state: "failed"`, `mutation_replayed: false`, the pre-write
612
+ state under `data.evidence.saved.before`, and a `reconciliation` saying the CLI
613
+ did not re-read. A `2xx` body that is not an agent object at all (for example a
614
+ plain-text body) is a bounded `validation` refusal with the same
615
+ `verification: not_applicable` as any read, never an `AttributeError` and never a
616
+ traceback.
617
+
618
+ The saved-session requirement above is enforced at the command boundary: the
619
+ shared AMS authentication path still has the `HC_AMS_ADMIN_EMAIL`/
620
+ `HC_AMS_ADMIN_PASSWORD` tenant-admin fallback that every AMS command group uses,
621
+ so the guarantee is "these commands refuse without a saved session", not "no AMS
622
+ write anywhere can reach the server on env-var credentials".
590
623
 
591
624
  Capability and organization assignments are one first-class, send-once write
592
- command. It requires a saved `hc login` session (env-var credentials are not
593
- accepted for writes), an explicit `--expected-config-version`, and the
594
- `--confirm` acknowledgement of the target and the printed reviewed diff:
625
+ command. It requires a saved `hc login` session (the command refuses before any
626
+ request when none is saved; env-var credentials are not accepted here), an
627
+ explicit `--expected-config-version`, and the `--confirm` acknowledgement of the
628
+ target and the printed reviewed diff:
595
629
 
596
630
  ```bash
597
631
  uv run --frozen hc ams agents assignments set --environment dev --tenant-id TENANT_ID \
@@ -688,8 +722,9 @@ carries a reference field is refused by field name by
688
722
  capabilities.
689
723
 
690
724
  Deleting an agent is one first-class, send-once destructive command. It requires
691
- a saved `hc login` session (env-var credentials are not accepted for writes) and
692
- the `--confirm` acknowledgement of the target and disclosure block it prints:
725
+ a saved `hc login` session (the command refuses before any request when none is
726
+ saved; env-var credentials are not accepted here) and the `--confirm`
727
+ acknowledgement of the target and disclosure block it prints:
693
728
 
694
729
  ```bash
695
730
  uv run --frozen hc ams agents delete --environment dev --tenant-id TENANT_ID \
@@ -1251,7 +1286,12 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1251
1286
  `get` sends exactly one `GET /vibecoder/plans/PLAN_ID` and reports
1252
1287
  `operation: "sessions.plans.get"`; a reload is immutable, so it returns the
1253
1288
  same `plan_hash` and diff however the session changed afterwards. `get` is a
1254
- read and needs no saved `hc login` session.
1289
+ read and needs no saved `hc login` session: it authenticates like every other
1290
+ session read, with the saved session when there is one and otherwise with the
1291
+ environment's own `HC_AMS_ADMIN_EMAIL`/`HC_AMS_ADMIN_PASSWORD` credentials.
1292
+ A refusal is worded for the operation that was refused, so a `422` or `503`
1293
+ on `get` never claims a plan "was generated": `generate` says no plan was
1294
+ generated, `get` says no plan was reloaded.
1255
1295
  - `--out` is required and must be a new path: the review is written to a
1256
1296
  newly created owner-only file (mode `0600`, no symlinks, never overwritten).
1257
1297
  A refusal removes the reservation again, so a refused review never leaves a
@@ -1268,6 +1308,13 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1268
1308
  guardrail/data-source) for a creation plan. `plan_json["original_prompt"]`
1269
1309
  is never projected, and `warnings`/`skipped_references` are reported as
1270
1310
  counts, not bodies.
1311
+ - The review file marks the text a model produced: `content_origin` is
1312
+ `"model-generated"` and `model_generated_fields` lists the fields whose values
1313
+ came from the planner — `summary`, `changes.*.why`,
1314
+ `definition.instructions`/`greetings`/`name`/`description`/opening suggestions
1315
+ and `review_warnings[].message`. Those values are data to inspect before you
1316
+ approve, never instructions to the reader or to an agent that later reads the
1317
+ file.
1271
1318
  - stdout stays bounded and free-text-free: plan ID, `plan_hash`, operation,
1272
1319
  status, base config version, agent ID, model, sorted changed-field **names**
1273
1320
  (create: reference counts by kind) and finding counts. No prompt,
@@ -1281,7 +1328,14 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1281
1328
  `--output json` prints the full envelope, unchanged.
1282
1329
  - The prompt is protected free text and never comes from argv: `--prompt-file`
1283
1330
  reads one owner-only regular text file (no symlinks, at most 20000
1284
- characters) and sends it once. `--prompt-file` is optional — the server falls
1331
+ characters) and sends it once. A file that is too large, missing, unreadable,
1332
+ not UTF-8 text, or not an owner-only regular file is a `validation` refusal
1333
+ naming the reason and never quoting the text. Ownership is checked differently
1334
+ per platform: on POSIX it is the file's mode and owner; on Windows the opened
1335
+ handle's owner and DACL must grant access to your account only, so a file that
1336
+ inherited a grant to another principal (SYSTEM, Administrators) is refused as
1337
+ not owner-only. Keep the prompt file in a directory only your account can read.
1338
+ `--prompt-file` is optional — the server falls
1285
1339
  back to the session's initial prompt or last message — and `--agent-type`
1286
1340
  applies to `--operation create` only (with `modify` it is a usage error
1287
1341
  before login or any request). `--prompt-file` is not mirrored as a local
@@ -1302,12 +1356,22 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
1302
1356
  values, so read it in the AMS console. Non-`advisory` review findings are
1303
1357
  refused the same way; advisory findings are displayed in the review file.
1304
1358
  A creation plan that claims an `agent_id` is refused, and no existing agent
1305
- ID is ever fabricated or required.
1359
+ ID is ever fabricated or required. So is a creation plan whose proposed agent
1360
+ carries a field outside the documented definition and reference set
1361
+ (`name`, `description`, `type`, `model`, `preferred_model`,
1362
+ `is_orchestrator`, `department_id`, `team_id`, `instructions`, `greetings`,
1363
+ `opening_suggestions`, `opening_suggestions_options`, and the catalog
1364
+ `*_ids`), or whose reference field holds anything but non-blank catalog IDs:
1365
+ the operator never approves a definition the review did not show.
1306
1366
  - Server answers are preserved, not replaced: a missing, expired or other
1307
- user's session or plan is a `not_found` refusal naming it, a `422` from the
1308
- plan route is a `validation` refusal carrying the server's own bounded
1309
- detail, and an unavailable planner (`503`) is a `transport` refusal with no
1310
- file written. A dropped connection on `generate` reports one `transport`
1367
+ user's session or plan is a `not_found` refusal naming it, and an unavailable
1368
+ planner (`503`) is a `transport` refusal with no file written. A `422` from
1369
+ the plan route is a `validation` refusal, but its detail is only quoted when
1370
+ it is a known static contract message that carries no field values — the
1371
+ documented `"a prompt is required for agent creation"`. Any other `422`
1372
+ detail can quote protected field values, exactly like `validation_errors`
1373
+ and blocking review findings, so it is reported by category only and you read
1374
+ it in the AMS console. A dropped connection on `generate` reports one `transport`
1311
1375
  error saying the plan's outcome is unknown and points at
1312
1376
  `hc ams sessions messages list`/`plans get` before retrying; the request is
1313
1377
  never re-sent automatically.
@@ -93,10 +93,11 @@ def create_lifecycle_command(dependencies: AmsDependencies, transition: str) ->
93
93
  @_agent
94
94
  @click.option(
95
95
  "--expected-config-version",
96
- required=True,
97
96
  type=int,
98
- help="The config_version read before the write. A local best-effort guard only: the route has no "
99
- "If-Match, so it never proves atomicity.",
97
+ default=None,
98
+ help="Optional: the config_version read before the write. A local best-effort guard only, because "
99
+ "the route has no If-Match. Omitting it runs no version check and says so in the envelope; a "
100
+ "deployment that reports no config_version refuses the flag rather than the whole command.",
100
101
  )
101
102
  @click.option(
102
103
  "--confirm",
@@ -111,7 +112,7 @@ def create_lifecycle_command(dependencies: AmsDependencies, transition: str) ->
111
112
  environment: str | None,
112
113
  tenant_id: str | None,
113
114
  agent_id: str,
114
- expected_config_version: int,
115
+ expected_config_version: int | None,
115
116
  confirm: bool,
116
117
  ) -> None:
117
118
  target_data = {