healthcloud-cli 3.7.0__tar.gz → 3.7.2__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.
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/PKG-INFO +97 -19
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/README.md +96 -18
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/operations.py +74 -5
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/errors.py +2 -15
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/policies/operations.py +73 -5
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/pretty.py +128 -1
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/results.py +53 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/skills/operations.py +58 -4
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/teams/operations.py +58 -4
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/cli.py +17 -9
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/contracts/mcp-tools.manifest.json +533 -3
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/output.py +13 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/pyproject.toml +1 -1
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/.gitignore +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/hatch_build.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/admins/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/admins/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/admins/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/admins/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/agents/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/agents/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/agents/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/agents/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/agents/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/auth.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/compatibility.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/context.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/data_sources/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/data_sources/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/data_sources/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/data_sources/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/data_sources/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/domain_errors.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/guardrails/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/guardrails/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/guardrails/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/guardrails/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/guardrails/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/organization/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/organization/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/organization/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/organization/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/organization/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/output.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/policies/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/policies/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/policies/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/policies/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/registry.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/session.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/sessions/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/sessions/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/sessions/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/sessions/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/sessions/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/skills/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/skills/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/skills/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/skills/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/target.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/teams/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/teams/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/teams/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/teams/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tools/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tools/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tools/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tools/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tools/projections.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/tuning.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/ui.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/windows_files.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/context.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/contracts/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/main.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/manifest.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/params.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/tenants/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/tenants/commands.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/tenants/group.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/tenants/operations.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/util.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/scripts/__init__.py +0 -0
- {healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/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.
|
|
3
|
+
Version: 3.7.2
|
|
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
|
|
@@ -316,6 +316,27 @@ otherwise it prompts (with hidden password input). It stores only the email,
|
|
|
316
316
|
tenant/environment binding, access/refresh tokens and expiry in the strict
|
|
317
317
|
owner-only `~/.healthcloud/cli/ams-session.json`; it never stores the password.
|
|
318
318
|
|
|
319
|
+
By default (`pretty`) these three commands print readable lines — never a raw
|
|
320
|
+
JSON blob and never a token:
|
|
321
|
+
|
|
322
|
+
```text
|
|
323
|
+
$ hc login --environment dev --tenant-id TENANT_ID
|
|
324
|
+
saved session: dev / TENANT_ID
|
|
325
|
+
email: admin@example.test
|
|
326
|
+
expires_at: 2026-11-02T01:42:29Z
|
|
327
|
+
$ hc logout
|
|
328
|
+
saved session removed: true
|
|
329
|
+
server session revoked: false
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
`hc login --status` prints the same three lines for the saved session, and a
|
|
333
|
+
second `hc logout` reports `saved session removed: false`. `--output json` (and
|
|
334
|
+
`--output raw`, which these commands treat as JSON) prints exactly the objects
|
|
335
|
+
they have always printed: `{"schema_version": 1, "ok": true, "session":
|
|
336
|
+
{"schema_version": 1, "environment", "tenant_id", "email", "expires_at"}}`
|
|
337
|
+
for `login`/`--status`, and `{"schema_version": 1, "ok": true, "removed":
|
|
338
|
+
true|false, "server_session_revoked": false}` for `logout`.
|
|
339
|
+
|
|
319
340
|
For CI and agents, log in non-interactively: pass `--email` and pipe the password
|
|
320
341
|
to `--password-stdin` (read as exactly one stdin line, never echoed, never a
|
|
321
342
|
flag value — there is no `--password` option):
|
|
@@ -545,6 +566,16 @@ explicitly that
|
|
|
545
566
|
fields — a disabled agent can still be selected by those paths — and that
|
|
546
567
|
in-flight runs, WSS sessions and schedules are untouched by this route.
|
|
547
568
|
|
|
569
|
+
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
|
|
572
|
+
deactivate reads `transition: deactivate`, then
|
|
573
|
+
`evidence: / saved: / status: confirmed`, then `verification: / saved_state:
|
|
574
|
+
confirmed`, `side_effects: unverified`, `runtime: unverified`; it is never one
|
|
575
|
+
raw JSON line. `--output json` prints the full envelope above, byte-identical to
|
|
576
|
+
before. An unknown outcome still prints its one-line `error:` plus the
|
|
577
|
+
reconciliation on stderr.
|
|
578
|
+
|
|
548
579
|
Pre-checks refuse with exit 1 and **no write**: a missing `--confirm` (exit 2
|
|
549
580
|
usage error, before login), an agent outside the explicit tenant, an already
|
|
550
581
|
in-effect state, an unsupported `archived`/`draft` target (named as having no
|
|
@@ -615,6 +646,12 @@ server audit log records an `UPDATE` with the payload. Runtime enforcement of
|
|
|
615
646
|
the new references is unobservable: no serving readback route exists, so this
|
|
616
647
|
command never claims it.
|
|
617
648
|
|
|
649
|
+
Default `pretty` output prints the same facts as labelled lines: `agent_id`,
|
|
650
|
+
`changed` (each field with `before`/`after`/`added`/`removed`),
|
|
651
|
+
`config_version: {before, after}`, `evidence` (`saved`, `side_effects`,
|
|
652
|
+
`runtime`), `mutation_replayed: false`, and a closing `verification:` block.
|
|
653
|
+
`--output json` prints the full envelope described here, unchanged.
|
|
654
|
+
|
|
618
655
|
`tool_ids` and `data_source_ids` address **unscoped global catalogs** by design;
|
|
619
656
|
the server checks tenant scope only for the department, team, skill, policy and
|
|
620
657
|
guardrail references. This command does not imply otherwise, and it does not
|
|
@@ -689,6 +726,13 @@ of restore and has no `--force`, no `--dry-run`, no interactive prompt and no
|
|
|
689
726
|
`--expected-config-version` — the route has no `If-Match` or version check, so a
|
|
690
727
|
version flag would advertise protection the server does not offer.
|
|
691
728
|
|
|
729
|
+
Default `pretty` output prints the result as labelled lines next to the stderr
|
|
730
|
+
disclosure: `agent_id`, `deleted: true`, `target`, `disclosure`, `evidence`
|
|
731
|
+
(`deleted`/`side_effects`/`runtime`), `mutation_replayed: false`, and a closing
|
|
732
|
+
`verification:` block. `--output json` prints the full envelope, unchanged. The
|
|
733
|
+
reviewed target and disclosure above are still printed to stderr in `pretty`
|
|
734
|
+
mode only; `--output json`/`raw` keep stderr machine-parsable.
|
|
735
|
+
|
|
692
736
|
Refusals claim nothing and send nothing extra: a missing `--confirm` is an exit
|
|
693
737
|
2 usage error before login or any request; an agent outside the explicit tenant,
|
|
694
738
|
the tenant identity mismatch and a delete target that no longer exists are
|
|
@@ -751,10 +795,14 @@ uv run --frozen hc ams departments delete --environment dev --tenant-id TENANT_I
|
|
|
751
795
|
reports a `validation` refusal that names the department, the tenant that
|
|
752
796
|
received it, and tells you to run `hc ams departments get` — it never claims
|
|
753
797
|
a landed write was a stopped no-op.
|
|
754
|
-
- If the transport times out
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
798
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
799
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
800
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
801
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
802
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
803
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
804
|
+
unknown and to check `hc ams departments get` before retrying. It never
|
|
805
|
+
re-sends the write and never re-reads on its own.
|
|
758
806
|
|
|
759
807
|
Read-only team listing and inspection are also complete and unpaged. The bounded
|
|
760
808
|
projection omits descriptions and creator identities; it includes evaluation-suite
|
|
@@ -797,10 +845,14 @@ uv run --frozen hc ams teams delete --environment dev --tenant-id TENANT_ID --
|
|
|
797
845
|
`validation` refusal that reports the landed write truthfully: it names the
|
|
798
846
|
team and the tenant that actually received it and points to `hc ams teams
|
|
799
847
|
get` — it never claims a landed write was stopped.
|
|
800
|
-
- If the transport times out
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
848
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
849
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
850
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
851
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
852
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
853
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
854
|
+
unknown and to check `hc ams teams get` before retrying. It never re-sends
|
|
855
|
+
the write and never re-reads on its own.
|
|
804
856
|
|
|
805
857
|
The organization hierarchy is the backend-built department/team/agent tree. The
|
|
806
858
|
CLI preserves its order and nesting without issuing entity reads, joining records,
|
|
@@ -862,10 +914,14 @@ uv run --frozen hc ams skills delete --environment dev --tenant-id TENANT_ID --s
|
|
|
862
914
|
landed write truthfully: it names the skill and the tenant that actually
|
|
863
915
|
received it and points to `hc ams skills get` — it never claims a landed
|
|
864
916
|
write was stopped.
|
|
865
|
-
- If the transport times out
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
917
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
918
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
919
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
920
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
921
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
922
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
923
|
+
unknown and to check `hc ams skills get` before retrying. It never re-sends
|
|
924
|
+
the write and never re-reads on its own.
|
|
869
925
|
|
|
870
926
|
Read-only policy catalog listing and inspection are complete and unpaged. The
|
|
871
927
|
bounded projection includes only policy IDs, names, department IDs, guardrail
|
|
@@ -954,10 +1010,14 @@ uv run --frozen hc ams policies delete --environment dev --tenant-id TENANT_ID -
|
|
|
954
1010
|
landed write truthfully: it names the policy and the tenant that actually
|
|
955
1011
|
received it and points to `hc ams policies get` — it never claims a landed
|
|
956
1012
|
write was stopped.
|
|
957
|
-
- If the transport times out
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1013
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
1014
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
1015
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
1016
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
1017
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
1018
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
1019
|
+
unknown and to check `hc ams policies get` before retrying. It never
|
|
1020
|
+
re-sends the write and never re-reads on its own.
|
|
961
1021
|
|
|
962
1022
|
Governed authoring sessions and their messages are first-class commands over the
|
|
963
1023
|
VibeCoder session routes. Creating a session and appending a message make no model
|
|
@@ -981,6 +1041,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
|
|
|
981
1041
|
"continuation": null}`). `get` emits `operation: "sessions.get"` and
|
|
982
1042
|
`data.session`. The projections never include the session's protected
|
|
983
1043
|
`initial_prompt`, tenant or user identity, or arbitrary response fields.
|
|
1044
|
+
- Default `pretty` output prints `list` as a table with honest headers —
|
|
1045
|
+
`ID`, `AGENT ID`, `OPERATION`, `STATUS`, `EXPIRES AT` for sessions and `ID`,
|
|
1046
|
+
`ROLE`, `MODE`, `PLAN ID`, `CREATED AT` for messages — followed by an entry
|
|
1047
|
+
count (`1 entry` / `N entries`), and `(no entries)` for an empty list. These
|
|
1048
|
+
projections carry no `name`, so no `NAME` column is invented and the `id` is
|
|
1049
|
+
always shown. `get`, `create` and `messages add` print `key: value` lines.
|
|
1050
|
+
`--output json` prints the full envelope exactly as before; pretty output is
|
|
1051
|
+
additive and never changes the envelope.
|
|
984
1052
|
- `create` and `messages add` require a saved `hc login` session (env-var
|
|
985
1053
|
credentials are not accepted for writes). Each write is sent exactly once and
|
|
986
1054
|
the envelope carries the server's authoritative readback:
|
|
@@ -1153,6 +1221,12 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
|
|
|
1153
1221
|
(create: reference counts by kind) and finding counts. No prompt,
|
|
1154
1222
|
instructions, greeting, summary, message content or plan value is printed to
|
|
1155
1223
|
stdout, stderr, a diagnostic or an error string.
|
|
1224
|
+
- Default `pretty` output renders `generate`, `get`, `apply`, `rollback` and
|
|
1225
|
+
`reconcile` as labelled lines — `plan:` with the bounded metadata, then
|
|
1226
|
+
`evidence:` (`saved`/`side_effects`/`runtime`) and `mutation_replayed: false`
|
|
1227
|
+
where the command reports them, and a closing `verification:` block for the
|
|
1228
|
+
writes. A write is never printed as a raw JSON blob in the default mode.
|
|
1229
|
+
`--output json` prints the full envelope, unchanged.
|
|
1156
1230
|
- The prompt is protected free text and never comes from argv: `--prompt-file`
|
|
1157
1231
|
reads one owner-only regular text file (no symlinks, at most 20000
|
|
1158
1232
|
characters) and sends it once. `--prompt-file` is optional — the server falls
|
|
@@ -1407,8 +1481,12 @@ and `hc ams organization hierarchy`) render in two modes (`--output` on the root
|
|
|
1407
1481
|
`hc` command; `pretty` is the default):
|
|
1408
1482
|
|
|
1409
1483
|
- **`pretty`** (default): a compact human view. Lists print an `ID`/`NAME`
|
|
1410
|
-
table with an entry count; a
|
|
1411
|
-
|
|
1484
|
+
table with an entry count; a collection whose rows have no `name` (sessions,
|
|
1485
|
+
messages, attachments) prints a table of that command's own columns plus the
|
|
1486
|
+
count, and `(no entries)` when empty. A single record prints `key: value`
|
|
1487
|
+
lines, the organization hierarchy prints an indented tree, and write or
|
|
1488
|
+
reconciliation evidence prints labelled `key: value` lines (the write's
|
|
1489
|
+
`verification:` block included) instead of JSON. Each failed AMS command
|
|
1412
1490
|
prints one stderr line, `error: <message> (<category>)` (flag/argument
|
|
1413
1491
|
usage errors from Click print Click's standard usage message instead).
|
|
1414
1492
|
- **`json`**: the stable result envelope (below) on stdout. When stdout is not
|
|
@@ -298,6 +298,27 @@ otherwise it prompts (with hidden password input). It stores only the email,
|
|
|
298
298
|
tenant/environment binding, access/refresh tokens and expiry in the strict
|
|
299
299
|
owner-only `~/.healthcloud/cli/ams-session.json`; it never stores the password.
|
|
300
300
|
|
|
301
|
+
By default (`pretty`) these three commands print readable lines — never a raw
|
|
302
|
+
JSON blob and never a token:
|
|
303
|
+
|
|
304
|
+
```text
|
|
305
|
+
$ hc login --environment dev --tenant-id TENANT_ID
|
|
306
|
+
saved session: dev / TENANT_ID
|
|
307
|
+
email: admin@example.test
|
|
308
|
+
expires_at: 2026-11-02T01:42:29Z
|
|
309
|
+
$ hc logout
|
|
310
|
+
saved session removed: true
|
|
311
|
+
server session revoked: false
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`hc login --status` prints the same three lines for the saved session, and a
|
|
315
|
+
second `hc logout` reports `saved session removed: false`. `--output json` (and
|
|
316
|
+
`--output raw`, which these commands treat as JSON) prints exactly the objects
|
|
317
|
+
they have always printed: `{"schema_version": 1, "ok": true, "session":
|
|
318
|
+
{"schema_version": 1, "environment", "tenant_id", "email", "expires_at"}}`
|
|
319
|
+
for `login`/`--status`, and `{"schema_version": 1, "ok": true, "removed":
|
|
320
|
+
true|false, "server_session_revoked": false}` for `logout`.
|
|
321
|
+
|
|
301
322
|
For CI and agents, log in non-interactively: pass `--email` and pipe the password
|
|
302
323
|
to `--password-stdin` (read as exactly one stdin line, never echoed, never a
|
|
303
324
|
flag value — there is no `--password` option):
|
|
@@ -527,6 +548,16 @@ explicitly that
|
|
|
527
548
|
fields — a disabled agent can still be selected by those paths — and that
|
|
528
549
|
in-flight runs, WSS sessions and schedules are untouched by this route.
|
|
529
550
|
|
|
551
|
+
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
|
|
554
|
+
deactivate reads `transition: deactivate`, then
|
|
555
|
+
`evidence: / saved: / status: confirmed`, then `verification: / saved_state:
|
|
556
|
+
confirmed`, `side_effects: unverified`, `runtime: unverified`; it is never one
|
|
557
|
+
raw JSON line. `--output json` prints the full envelope above, byte-identical to
|
|
558
|
+
before. An unknown outcome still prints its one-line `error:` plus the
|
|
559
|
+
reconciliation on stderr.
|
|
560
|
+
|
|
530
561
|
Pre-checks refuse with exit 1 and **no write**: a missing `--confirm` (exit 2
|
|
531
562
|
usage error, before login), an agent outside the explicit tenant, an already
|
|
532
563
|
in-effect state, an unsupported `archived`/`draft` target (named as having no
|
|
@@ -597,6 +628,12 @@ server audit log records an `UPDATE` with the payload. Runtime enforcement of
|
|
|
597
628
|
the new references is unobservable: no serving readback route exists, so this
|
|
598
629
|
command never claims it.
|
|
599
630
|
|
|
631
|
+
Default `pretty` output prints the same facts as labelled lines: `agent_id`,
|
|
632
|
+
`changed` (each field with `before`/`after`/`added`/`removed`),
|
|
633
|
+
`config_version: {before, after}`, `evidence` (`saved`, `side_effects`,
|
|
634
|
+
`runtime`), `mutation_replayed: false`, and a closing `verification:` block.
|
|
635
|
+
`--output json` prints the full envelope described here, unchanged.
|
|
636
|
+
|
|
600
637
|
`tool_ids` and `data_source_ids` address **unscoped global catalogs** by design;
|
|
601
638
|
the server checks tenant scope only for the department, team, skill, policy and
|
|
602
639
|
guardrail references. This command does not imply otherwise, and it does not
|
|
@@ -671,6 +708,13 @@ of restore and has no `--force`, no `--dry-run`, no interactive prompt and no
|
|
|
671
708
|
`--expected-config-version` — the route has no `If-Match` or version check, so a
|
|
672
709
|
version flag would advertise protection the server does not offer.
|
|
673
710
|
|
|
711
|
+
Default `pretty` output prints the result as labelled lines next to the stderr
|
|
712
|
+
disclosure: `agent_id`, `deleted: true`, `target`, `disclosure`, `evidence`
|
|
713
|
+
(`deleted`/`side_effects`/`runtime`), `mutation_replayed: false`, and a closing
|
|
714
|
+
`verification:` block. `--output json` prints the full envelope, unchanged. The
|
|
715
|
+
reviewed target and disclosure above are still printed to stderr in `pretty`
|
|
716
|
+
mode only; `--output json`/`raw` keep stderr machine-parsable.
|
|
717
|
+
|
|
674
718
|
Refusals claim nothing and send nothing extra: a missing `--confirm` is an exit
|
|
675
719
|
2 usage error before login or any request; an agent outside the explicit tenant,
|
|
676
720
|
the tenant identity mismatch and a delete target that no longer exists are
|
|
@@ -733,10 +777,14 @@ uv run --frozen hc ams departments delete --environment dev --tenant-id TENANT_I
|
|
|
733
777
|
reports a `validation` refusal that names the department, the tenant that
|
|
734
778
|
received it, and tells you to run `hc ams departments get` — it never claims
|
|
735
779
|
a landed write was a stopped no-op.
|
|
736
|
-
- If the transport times out
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
780
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
781
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
782
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
783
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
784
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
785
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
786
|
+
unknown and to check `hc ams departments get` before retrying. It never
|
|
787
|
+
re-sends the write and never re-reads on its own.
|
|
740
788
|
|
|
741
789
|
Read-only team listing and inspection are also complete and unpaged. The bounded
|
|
742
790
|
projection omits descriptions and creator identities; it includes evaluation-suite
|
|
@@ -779,10 +827,14 @@ uv run --frozen hc ams teams delete --environment dev --tenant-id TENANT_ID --
|
|
|
779
827
|
`validation` refusal that reports the landed write truthfully: it names the
|
|
780
828
|
team and the tenant that actually received it and points to `hc ams teams
|
|
781
829
|
get` — it never claims a landed write was stopped.
|
|
782
|
-
- If the transport times out
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
830
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
831
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
832
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
833
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
834
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
835
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
836
|
+
unknown and to check `hc ams teams get` before retrying. It never re-sends
|
|
837
|
+
the write and never re-reads on its own.
|
|
786
838
|
|
|
787
839
|
The organization hierarchy is the backend-built department/team/agent tree. The
|
|
788
840
|
CLI preserves its order and nesting without issuing entity reads, joining records,
|
|
@@ -844,10 +896,14 @@ uv run --frozen hc ams skills delete --environment dev --tenant-id TENANT_ID --s
|
|
|
844
896
|
landed write truthfully: it names the skill and the tenant that actually
|
|
845
897
|
received it and points to `hc ams skills get` — it never claims a landed
|
|
846
898
|
write was stopped.
|
|
847
|
-
- If the transport times out
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
899
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
900
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
901
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
902
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
903
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
904
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
905
|
+
unknown and to check `hc ams skills get` before retrying. It never re-sends
|
|
906
|
+
the write and never re-reads on its own.
|
|
851
907
|
|
|
852
908
|
Read-only policy catalog listing and inspection are complete and unpaged. The
|
|
853
909
|
bounded projection includes only policy IDs, names, department IDs, guardrail
|
|
@@ -936,10 +992,14 @@ uv run --frozen hc ams policies delete --environment dev --tenant-id TENANT_ID -
|
|
|
936
992
|
landed write truthfully: it names the policy and the tenant that actually
|
|
937
993
|
received it and points to `hc ams policies get` — it never claims a landed
|
|
938
994
|
write was stopped.
|
|
939
|
-
- If the transport times out
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
995
|
+
- If the transport times out, the connection drops mid-write, or the server
|
|
996
|
+
answers an HTTP 5xx/408 before a readable result, the write's outcome is
|
|
997
|
+
unknown: the CLI exits 1 with an `unknown` envelope
|
|
998
|
+
(`verification.saved_state: unknown`, `verification.side_effects:
|
|
999
|
+
unverified`, `data.mutation_replayed: false`, and
|
|
1000
|
+
`data.reconciliation.status: not_read`) whose message says the outcome is
|
|
1001
|
+
unknown and to check `hc ams policies get` before retrying. It never
|
|
1002
|
+
re-sends the write and never re-reads on its own.
|
|
943
1003
|
|
|
944
1004
|
Governed authoring sessions and their messages are first-class commands over the
|
|
945
1005
|
VibeCoder session routes. Creating a session and appending a message make no model
|
|
@@ -963,6 +1023,14 @@ uv run --frozen hc ams sessions messages add --environment dev --tenant-id TENAN
|
|
|
963
1023
|
"continuation": null}`). `get` emits `operation: "sessions.get"` and
|
|
964
1024
|
`data.session`. The projections never include the session's protected
|
|
965
1025
|
`initial_prompt`, tenant or user identity, or arbitrary response fields.
|
|
1026
|
+
- Default `pretty` output prints `list` as a table with honest headers —
|
|
1027
|
+
`ID`, `AGENT ID`, `OPERATION`, `STATUS`, `EXPIRES AT` for sessions and `ID`,
|
|
1028
|
+
`ROLE`, `MODE`, `PLAN ID`, `CREATED AT` for messages — followed by an entry
|
|
1029
|
+
count (`1 entry` / `N entries`), and `(no entries)` for an empty list. These
|
|
1030
|
+
projections carry no `name`, so no `NAME` column is invented and the `id` is
|
|
1031
|
+
always shown. `get`, `create` and `messages add` print `key: value` lines.
|
|
1032
|
+
`--output json` prints the full envelope exactly as before; pretty output is
|
|
1033
|
+
additive and never changes the envelope.
|
|
966
1034
|
- `create` and `messages add` require a saved `hc login` session (env-var
|
|
967
1035
|
credentials are not accepted for writes). Each write is sent exactly once and
|
|
968
1036
|
the envelope carries the server's authoritative readback:
|
|
@@ -1135,6 +1203,12 @@ uv run --frozen hc ams sessions plans reconcile --environment dev --tenant-id TE
|
|
|
1135
1203
|
(create: reference counts by kind) and finding counts. No prompt,
|
|
1136
1204
|
instructions, greeting, summary, message content or plan value is printed to
|
|
1137
1205
|
stdout, stderr, a diagnostic or an error string.
|
|
1206
|
+
- Default `pretty` output renders `generate`, `get`, `apply`, `rollback` and
|
|
1207
|
+
`reconcile` as labelled lines — `plan:` with the bounded metadata, then
|
|
1208
|
+
`evidence:` (`saved`/`side_effects`/`runtime`) and `mutation_replayed: false`
|
|
1209
|
+
where the command reports them, and a closing `verification:` block for the
|
|
1210
|
+
writes. A write is never printed as a raw JSON blob in the default mode.
|
|
1211
|
+
`--output json` prints the full envelope, unchanged.
|
|
1138
1212
|
- The prompt is protected free text and never comes from argv: `--prompt-file`
|
|
1139
1213
|
reads one owner-only regular text file (no symlinks, at most 20000
|
|
1140
1214
|
characters) and sends it once. `--prompt-file` is optional — the server falls
|
|
@@ -1389,8 +1463,12 @@ and `hc ams organization hierarchy`) render in two modes (`--output` on the root
|
|
|
1389
1463
|
`hc` command; `pretty` is the default):
|
|
1390
1464
|
|
|
1391
1465
|
- **`pretty`** (default): a compact human view. Lists print an `ID`/`NAME`
|
|
1392
|
-
table with an entry count; a
|
|
1393
|
-
|
|
1466
|
+
table with an entry count; a collection whose rows have no `name` (sessions,
|
|
1467
|
+
messages, attachments) prints a table of that command's own columns plus the
|
|
1468
|
+
count, and `(no entries)` when empty. A single record prints `key: value`
|
|
1469
|
+
lines, the organization hierarchy prints an indented tree, and write or
|
|
1470
|
+
reconciliation evidence prints labelled `key: value` lines (the write's
|
|
1471
|
+
`verification:` block included) instead of JSON. Each failed AMS command
|
|
1394
1472
|
prints one stderr line, `error: <message> (<category>)` (flag/argument
|
|
1395
1473
|
usage errors from Click print Click's standard usage message instead).
|
|
1396
1474
|
- **`json`**: the stable result envelope (below) on stdout. When stdout is not
|
{healthcloud_cli-3.7.0 → healthcloud_cli-3.7.2}/healthcloud_cli/ams/departments/operations.py
RENAMED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from ..context import AmsDependencies
|
|
6
6
|
from ..domain_errors import DomainReadRefused
|
|
7
|
-
from ..results import succeeded
|
|
7
|
+
from ..results import is_unknown_write_status, succeeded, unknown_write
|
|
8
8
|
from ..target import TenantTarget
|
|
9
9
|
from .projections import department_projection
|
|
10
10
|
|
|
@@ -27,6 +27,18 @@ UNKNOWN_OUTCOME = (
|
|
|
27
27
|
"department's current server state before deciding whether to retry."
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
+
UNKNOWN_HTTP_OUTCOME = (
|
|
31
|
+
"The department write was sent once and its outcome is now unknown: the server answered with an "
|
|
32
|
+
"error status before a readable result, so the request may have been processed. Run "
|
|
33
|
+
"`hc ams departments get` to check the department's current server state before deciding whether "
|
|
34
|
+
"to retry."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
UNKNOWN_RECONCILIATION = (
|
|
38
|
+
"This command did not re-read the department after the uncertain write; run "
|
|
39
|
+
"`hc ams departments list` before doing anything else."
|
|
40
|
+
)
|
|
41
|
+
|
|
30
42
|
|
|
31
43
|
def _department_id(value: str) -> str:
|
|
32
44
|
if not isinstance(value, str) or not value.strip():
|
|
@@ -140,11 +152,26 @@ def create_department(
|
|
|
140
152
|
)
|
|
141
153
|
except HealthCloudNetworkError:
|
|
142
154
|
# Sent once: the request may have landed; the outcome is unknown, never retried here.
|
|
143
|
-
|
|
155
|
+
unknown_write(
|
|
156
|
+
"departments.create",
|
|
157
|
+
_target(target),
|
|
158
|
+
UNKNOWN_OUTCOME,
|
|
159
|
+
{"department": None},
|
|
160
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
161
|
+
)
|
|
144
162
|
except HealthCloudHTTPError as error:
|
|
145
163
|
refusal = _create_not_found(error, parent_department_id)
|
|
146
164
|
if refusal is not None:
|
|
147
165
|
raise refusal from error
|
|
166
|
+
if is_unknown_write_status(getattr(error, "status_code", None)):
|
|
167
|
+
# A 5xx/408 may have committed server-side: report it as unknown, never a retry shape.
|
|
168
|
+
unknown_write(
|
|
169
|
+
"departments.create",
|
|
170
|
+
_target(target),
|
|
171
|
+
UNKNOWN_HTTP_OUTCOME,
|
|
172
|
+
{"department": None},
|
|
173
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
174
|
+
)
|
|
148
175
|
raise
|
|
149
176
|
# The write has already landed server-side; a mismatching readback must never be
|
|
150
177
|
# reported as a stopped no-op. Name the tenant that actually received it.
|
|
@@ -174,11 +201,25 @@ def update_department(
|
|
|
174
201
|
try:
|
|
175
202
|
department = resource.update(department_id, **fields)
|
|
176
203
|
except HealthCloudNetworkError:
|
|
177
|
-
|
|
204
|
+
unknown_write(
|
|
205
|
+
"departments.update",
|
|
206
|
+
_target(target, department_id),
|
|
207
|
+
UNKNOWN_OUTCOME,
|
|
208
|
+
{"department": None},
|
|
209
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
210
|
+
)
|
|
178
211
|
except HealthCloudHTTPError as error:
|
|
179
212
|
refusal = _not_found(error, department_id)
|
|
180
213
|
if refusal is not None:
|
|
181
214
|
raise refusal from error
|
|
215
|
+
if is_unknown_write_status(getattr(error, "status_code", None)):
|
|
216
|
+
unknown_write(
|
|
217
|
+
"departments.update",
|
|
218
|
+
_target(target, department_id),
|
|
219
|
+
UNKNOWN_HTTP_OUTCOME,
|
|
220
|
+
{"department": None},
|
|
221
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
222
|
+
)
|
|
182
223
|
raise
|
|
183
224
|
_identity(department, target, department_id)
|
|
184
225
|
return _write_result("departments.update", target, department_id, {"department": department_projection(department)})
|
|
@@ -193,11 +234,25 @@ def _lifecycle(dependencies: AmsDependencies, target: TenantTarget, department_i
|
|
|
193
234
|
try:
|
|
194
235
|
department = getattr(resource, method)(department_id)
|
|
195
236
|
except HealthCloudNetworkError:
|
|
196
|
-
|
|
237
|
+
unknown_write(
|
|
238
|
+
f"departments.{method}",
|
|
239
|
+
_target(target, department_id),
|
|
240
|
+
UNKNOWN_OUTCOME,
|
|
241
|
+
{"department": None},
|
|
242
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
243
|
+
)
|
|
197
244
|
except HealthCloudHTTPError as error:
|
|
198
245
|
refusal = _not_found(error, department_id)
|
|
199
246
|
if refusal is not None:
|
|
200
247
|
raise refusal from error
|
|
248
|
+
if is_unknown_write_status(getattr(error, "status_code", None)):
|
|
249
|
+
unknown_write(
|
|
250
|
+
f"departments.{method}",
|
|
251
|
+
_target(target, department_id),
|
|
252
|
+
UNKNOWN_HTTP_OUTCOME,
|
|
253
|
+
{"department": None},
|
|
254
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
255
|
+
)
|
|
201
256
|
raise
|
|
202
257
|
_identity(department, target, department_id)
|
|
203
258
|
return _write_result(
|
|
@@ -225,10 +280,24 @@ def delete_department(dependencies: AmsDependencies, target: TenantTarget, depar
|
|
|
225
280
|
try:
|
|
226
281
|
resource.delete(department_id)
|
|
227
282
|
except HealthCloudNetworkError:
|
|
228
|
-
|
|
283
|
+
unknown_write(
|
|
284
|
+
"departments.delete",
|
|
285
|
+
_target(target, department_id),
|
|
286
|
+
UNKNOWN_OUTCOME,
|
|
287
|
+
{"deleted": None},
|
|
288
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
289
|
+
)
|
|
229
290
|
except HealthCloudHTTPError as error:
|
|
230
291
|
refusal = _not_found(error, department_id)
|
|
231
292
|
if refusal is not None:
|
|
232
293
|
raise refusal from error
|
|
294
|
+
if is_unknown_write_status(getattr(error, "status_code", None)):
|
|
295
|
+
unknown_write(
|
|
296
|
+
"departments.delete",
|
|
297
|
+
_target(target, department_id),
|
|
298
|
+
UNKNOWN_HTTP_OUTCOME,
|
|
299
|
+
{"deleted": None},
|
|
300
|
+
reconciliation_detail=UNKNOWN_RECONCILIATION,
|
|
301
|
+
)
|
|
233
302
|
raise
|
|
234
303
|
return _write_result("departments.delete", target, department_id, {"deleted": True})
|
|
@@ -10,7 +10,7 @@ from typing import Any
|
|
|
10
10
|
import click
|
|
11
11
|
from pydantic import ValidationError
|
|
12
12
|
|
|
13
|
-
from ..
|
|
13
|
+
from ..output import output_mode
|
|
14
14
|
from .domain_errors import DomainReadRefused
|
|
15
15
|
from .pretty import error_line, success_text, unknown_details
|
|
16
16
|
from .results import failed
|
|
@@ -135,19 +135,6 @@ def emit_compact_json(value: dict, *, err: bool = False) -> None:
|
|
|
135
135
|
click.echo(json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True), err=err)
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def _output_mode() -> str:
|
|
139
|
-
"""The root ``--output`` mode for the running command; pretty is the default.
|
|
140
|
-
|
|
141
|
-
Raw is refused for AMS before any read runs, but its refusals keep the
|
|
142
|
-
structured JSON error envelope, so raw renders like json.
|
|
143
|
-
"""
|
|
144
|
-
|
|
145
|
-
ctx = click.get_current_context(silent=True)
|
|
146
|
-
cfg = ctx.find_object(CliConfig) if ctx is not None else None
|
|
147
|
-
mode = getattr(cfg, "output", None)
|
|
148
|
-
return "json" if mode in ("json", "raw") else "pretty"
|
|
149
|
-
|
|
150
|
-
|
|
151
138
|
def _render_success(envelope: dict, mode: str) -> None:
|
|
152
139
|
if mode != "json":
|
|
153
140
|
click.echo(success_text(envelope))
|
|
@@ -190,7 +177,7 @@ def run_domain(operation: str, target: dict, callback: Callable[[], Any], *, rea
|
|
|
190
177
|
``verification`` block in the error envelope.
|
|
191
178
|
"""
|
|
192
179
|
|
|
193
|
-
mode =
|
|
180
|
+
mode = output_mode()
|
|
194
181
|
|
|
195
182
|
def _fail(error: BaseException) -> None:
|
|
196
183
|
"""Classify ``error``, render the error envelope, and exit bounded."""
|