strictcli 0.38.0__tar.gz → 0.40.0__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 (102) hide show
  1. strictcli-0.40.0/.gitignore +25 -0
  2. {strictcli-0.38.0 → strictcli-0.40.0}/CLAUDE.md +1 -1
  3. {strictcli-0.38.0 → strictcli-0.40.0}/PKG-INFO +15 -3
  4. {strictcli-0.38.0 → strictcli-0.40.0}/README.md +13 -1
  5. {strictcli-0.38.0 → strictcli-0.40.0}/pyproject.toml +1 -1
  6. {strictcli-0.38.0 → strictcli-0.40.0}/strictcli/__init__.py +2831 -481
  7. {strictcli-0.38.0 → strictcli-0.40.0}/tests/conftest.py +16 -0
  8. {strictcli-0.38.0 → strictcli-0.40.0}/tests/flagship_app.py +3 -2
  9. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_call.py +140 -80
  10. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_command.py +72 -23
  11. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_provider.py +2 -2
  12. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_public_api.py +23 -3
  13. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_runner.py +71 -0
  14. strictcli-0.40.0/tests/test_claimed_rendering.py +121 -0
  15. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_classification.py +2 -2
  16. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_command_tags.py +21 -21
  17. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_config.py +20 -15
  18. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_config_fields.py +12 -3
  19. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_confirm.py +190 -4
  20. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_context.py +38 -16
  21. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_dependencies.py +11 -11
  22. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_dry_run_unsupported.py +7 -4
  23. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_dump_schema.py +80 -5
  24. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_effects.py +40 -22
  25. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_effects_bypass_check.py +4 -3
  26. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_infra_env.py +2 -1
  27. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_invoke.py +7 -7
  28. strictcli-0.40.0/tests/test_machine_mode.py +465 -0
  29. strictcli-0.40.0/tests/test_mcp.py +1692 -0
  30. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_mutex.py +191 -12
  31. strictcli-0.40.0/tests/test_owns_stdout.py +132 -0
  32. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_passthrough.py +1 -1
  33. strictcli-0.40.0/tests/test_payload_schema.py +576 -0
  34. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_provenance.py +31 -30
  35. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_provenance_phase2.py +5 -3
  36. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_reserved_quartet.py +22 -14
  37. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_tool_export.py +102 -8
  38. strictcli-0.40.0/tests/test_trace_store.py +892 -0
  39. strictcli-0.40.0/tests/test_ulid_vectors.py +72 -0
  40. {strictcli-0.38.0 → strictcli-0.40.0}/uv.lock +1 -1
  41. strictcli-0.38.0/.gitignore +0 -20
  42. strictcli-0.38.0/.strictcli/schema.json +0 -19
  43. strictcli-0.38.0/tests/test_mcp.py +0 -679
  44. {strictcli-0.38.0 → strictcli-0.40.0}/.claude/settings.json +0 -0
  45. {strictcli-0.38.0 → strictcli-0.40.0}/.github/workflows/ci.yml +0 -0
  46. {strictcli-0.38.0 → strictcli-0.40.0}/.github/workflows/publish.yml +0 -0
  47. {strictcli-0.38.0 → strictcli-0.40.0}/.rlsbl/config.json +0 -0
  48. {strictcli-0.38.0 → strictcli-0.40.0}/.rlsbl/lint/python.toml +0 -0
  49. {strictcli-0.38.0 → strictcli-0.40.0}/.rlsbl/managed-files.json +0 -0
  50. {strictcli-0.38.0 → strictcli-0.40.0}/LICENSE +0 -0
  51. {strictcli-0.38.0 → strictcli-0.40.0}/scripts/add_effect_classification.py +0 -0
  52. {strictcli-0.38.0 → strictcli-0.40.0}/scripts/add_forwarding_declaration.py +0 -0
  53. {strictcli-0.38.0 → strictcli-0.40.0}/strictcli/py.typed +0 -0
  54. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_arg_default.py +0 -0
  55. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_arg_default_validation.py +0 -0
  56. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_at_prefix.py +0 -0
  57. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_auto_version.py +0 -0
  58. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_discovery.py +0 -0
  59. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_schema.py +0 -0
  60. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_check_types.py +0 -0
  61. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_choices.py +0 -0
  62. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_choices_none.py +0 -0
  63. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_command_help_suggestion.py +0 -0
  64. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_compound_types.py +0 -0
  65. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_config_file_path.py +0 -0
  66. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_config_set_bugs.py +0 -0
  67. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_connection_env.py +0 -0
  68. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_coverage.py +0 -0
  69. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_deep_nesting.py +0 -0
  70. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_deprecated.py +0 -0
  71. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_e2e.py +0 -0
  72. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_env.py +0 -0
  73. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_exit_codes.py +0 -0
  74. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_flag_sets.py +0 -0
  75. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_flagship_preview.py +0 -0
  76. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_float_format.py +0 -0
  77. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_float_type.py +0 -0
  78. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_float_vectors.py +0 -0
  79. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_global_flag_conflict_position.py +0 -0
  80. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_global_flags.py +0 -0
  81. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_guard_v2.py +0 -0
  82. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_help.py +0 -0
  83. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_hermetic.py +0 -0
  84. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_int_type.py +0 -0
  85. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_keyword_flags.py +0 -0
  86. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_nesting.py +0 -0
  87. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_parser.py +0 -0
  88. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_registration.py +0 -0
  89. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_repeatable.py +0 -0
  90. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_reserved_global_flags.py +0 -0
  91. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_tagdsl.py +0 -0
  92. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_toml_loading.py +0 -0
  93. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_typed_args.py +0 -0
  94. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_unique.py +0 -0
  95. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_utilities.py +0 -0
  96. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_validate.py +0 -0
  97. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_variadic.py +0 -0
  98. {strictcli-0.38.0 → strictcli-0.40.0}/tests/test_visibility.py +0 -0
  99. {strictcli-0.38.0 → strictcli-0.40.0}/todo/.defer/deferred.md +0 -0
  100. {strictcli-0.38.0 → strictcli-0.40.0}/todo/.done/keyword-collision-in-flag-param-name.md +0 -0
  101. {strictcli-0.38.0 → strictcli-0.40.0}/todo/.done/original-idea.md +0 -0
  102. {strictcli-0.38.0 → strictcli-0.40.0}/todo/.done/public-check-runner-api.md +0 -0
@@ -0,0 +1,25 @@
1
+ node_modules/
2
+ __pycache__/
3
+ *.pyc
4
+ *.log
5
+ .DS_Store
6
+ coverage/
7
+ dist/
8
+ *.egg-info/
9
+ .rlsbl-notes-*.tmp
10
+ .rlsbl/lock
11
+ .credentials.json
12
+ .*-cache.json
13
+ .env
14
+ .env.local
15
+ *.local-only
16
+
17
+ .rlsbl-monorepo/lock
18
+
19
+ build/
20
+ target/
21
+
22
+ # Test apps run with this directory as cwd write schema dumps and coverage
23
+ # shards here. Nothing under python/ is a maintained artifact (unlike
24
+ # conformance/.strictcli/, which is committed on purpose).
25
+ .strictcli/
@@ -18,7 +18,7 @@ Releases go through [rlsbl](https://github.com/smm-h/rlsbl) monorepo releases.
18
18
  (they land in `.rlsbl-monorepo/releasables/py-strictcli/changes/unreleased.jsonl`).
19
19
  - To release: from the repo root, run `rlsbl monorepo release init`, edit the
20
20
  scaffolded release file (bump type, description, and context live in the file),
21
- then run `rlsbl monorepo release run --no-allow-dirty --watch --yes`.
21
+ then run `rlsbl monorepo release run --no-allow-dirty --watch --approve-consequential`.
22
22
  - Never publish or push manually — CI publishes to PyPI via Trusted Publishing.
23
23
 
24
24
  ## Conventions
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: strictcli
3
- Version: 0.38.0
3
+ Version: 0.40.0
4
4
  Summary: A strict CLI framework for Python
5
5
  Project-URL: Homepage, https://github.com/smm-h/strictcli
6
6
  Project-URL: Repository, https://github.com/smm-h/strictcli
@@ -391,7 +391,19 @@ Auto-registers a `check` command with tag DSL filtering
391
391
 
392
392
  ```python
393
393
  tools = app.as_tools()
394
- # Each Tool has: name, description, parameters (JSON Schema), execute
394
+ # Each Tool has: name, description, parameters (JSON Schema), effect,
395
+ # consequential, execute
396
+ ```
397
+
398
+ `effect` and `consequential` publish the effects-regime classification beside
399
+ the argument schema, so a caller can see before it calls that a tool changes
400
+ things and that invoking it requires stating consent:
401
+
402
+ ```python
403
+ release = next(t for t in tools if t.name == "release")
404
+ release.consequential # True
405
+ await release.execute() # InvokeError: ... the call must carry confirmation
406
+ await release.execute(approve_consequential=True) # proceeds
395
407
  ```
396
408
 
397
409
  ### MCP server
@@ -372,7 +372,19 @@ Auto-registers a `check` command with tag DSL filtering
372
372
 
373
373
  ```python
374
374
  tools = app.as_tools()
375
- # Each Tool has: name, description, parameters (JSON Schema), execute
375
+ # Each Tool has: name, description, parameters (JSON Schema), effect,
376
+ # consequential, execute
377
+ ```
378
+
379
+ `effect` and `consequential` publish the effects-regime classification beside
380
+ the argument schema, so a caller can see before it calls that a tool changes
381
+ things and that invoking it requires stating consent:
382
+
383
+ ```python
384
+ release = next(t for t in tools if t.name == "release")
385
+ release.consequential # True
386
+ await release.execute() # InvokeError: ... the call must carry confirmation
387
+ await release.execute(approve_consequential=True) # proceeds
376
388
  ```
377
389
 
378
390
  ### MCP server
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "strictcli"
7
- version = "0.38.0"
7
+ version = "0.40.0"
8
8
  description = "A strict CLI framework for Python"
9
9
  readme = "README.md"
10
10
  license = "MIT"